← back to pin list

Brick 36: Spread Y on part-list nests (+ hand-layout bridge fix 2026-09-19)

kerfmaster pin list · UI / workflow decisions

recordStates what the code does today. Auditable against the code — this is the only type that can go stale.

Content last changed 2026-09-19 — computed from the item itself, not typed.

Built 2026-09-03. ENGINE pl_spread.py (docstring = design record): each sheet's placements group into COLUMNS by transitive world-bbox X overlap (true sampled extents, the brick-3 arc lesson); within a column, bbox-overlapping runs are MESHED UNITS that move as one rigid body (the pack's slide-to-contact meshing is preserved exactly); n units make n+1 gaps (bottom edge, between, top edge) with required minimums from the per-part bridges (larger governs, conservatively over the whole unit); if the perfectly even value clears every minimum, every gap becomes it (the 2026-08-28 edges-included refinement), else every gap takes its required value + the same even extra -- no pair ever below its ruled clearance. A bbox Y-gap is a sound LOWER bound on the true-outline distance, so the arithmetic can never violate the ruled value; X never moves (spreading is a Y operation -- the remnant slab and used_x stand).

SERVER: POST /api/jobs/<id>/plspread -- geometry rebuilt by the ONE builder run_partnest uses (_pl_build, factored out this brick: one seam, master and pack can never read a part differently); THE GATE is the pack's own outline audit (pln._audit -- separate arithmetic from the spread's bbox construction, the 3A76 lesson) plus a fresh sheet-wide lead judge (pl_tool.judge); any miss REFUSES whole in honest words, nothing saved. Moved placements drop posted sheet programs, every O-number kept; Pack again = the reset. Spread record (per-column form even vs required+extra, meshed units) persists on partnest.json.

UI: Spread Y button beside Pack again in the Nest drawer, applied-date note on the drawer. DEFECT CAUGHT IN THE BUILD: every list save wiped partlist.json's frames record (partrotate metadata the client never sends) -- the save now preserves it. Proven: test_pl_spread.py 18 NEW controls + live e2e on a scratch clone of the real Lathrup pack (29 placements moved, audit margins +0.005 over ruled, even form on all 9 columns, one meshed unit) + real-mouse Playwright click; 10 suites green. DEFECT FIXED 2026-09-03 (Jordan's refused Spread Y on the real 97-part Lathrup pack): the spread's extents were BARE OUTLINES, so evening could put a lead envelope inside the ruled clearance -- the audit gate caught it (crescent 2805's lead 0.1621 from its twin, under 0.2) and refused whole, exactly as designed. Fix per the nest-objective-function ruling (the unit is part + lead envelope, never bare geometry): the caller passes outline + lead points, the standoff joins every between-gap's required minimum, and a column that no longer fits at ruled gaps is LEFT AS PACKED and named in the report (refusing the whole spread over one full column was the wrong remedy). Controls 18 -> 22 (the crescent miss reproduced and held, standoff-governs); real spread applied via the server's own codepath: all 10 sheets evened, audit gap +0.005 / lead +0.0165 / edge +0.005 over ruled.