kerfmaster pin list ยท UI / workflow decisions
rulingA decision by Aristide or Jordan. True because it was decided; it can be superseded, but it cannot be stale.
Content last changed 2026-09-19 โ computed from the item itself, not typed.
The agreed shape, from his answers point by point:
Delivery mode agreed: no mock -- build the real thing and iterate in Jordan's hands (the feel IS the deliverable; a static picture cannot show drag/stack ease). Not built yet; commissioned beside pl-nest-hand-editor.
SESSION 1 BUILT 2026-09-14 (Jordan's 'Go ahead with what you suggest'): the tray core is LIVE. SERVER: POST /api/jobs/<id>/group binds a job to its group -- the part-list job it lives inside on the Jobs home; ANNOTATION only (no stage record, nothing drops, the job works the same opened directly), {clear:true} takes it out; refusal ladder plain-400 in honest words (missing list id, self, a part list inside a group, no such job, target not a part list). run_pipeline records parts_detected {parts, debris} on every heal via the split door's OWN grouper + debris gate (_count_parts -- the note and a later split can never disagree; >5000-prim drawings skip the count, an aid never worth slowing every heal). CLIENT (app.js/app.css/index.html): a multi-file pick or drop opens the TRAY -- one card per file, NOTHING uploads until confirm (Cancel/Escape discards with nothing sent); drag a card onto another with the real mouse to STACK into a group (stacked-sheets visual, auto-name from the member stems, editable), chip x takes a file back out; customer per card/stack as ONE type-ahead field over the registry (case-insensitive match or created once; blank = Unfiled); the confirm button states the outcome ('Create 1 group + 2 individual jobs'). Confirm runs the batch with live progress words: uploads, SPLITS multi-part files behind the scenes (a single-part file IS its row; an odd refusal lands the whole file as one row, named in the summary -- never silent), creates the part-list job, saves one row per part qty 1 (natural sort; unhealed parts left off and named), files the list under the customer, binds every member (file jobs + split children) to the group. JOBS HOME: members render INSIDE the group's card ('N part jobs inside' unfolds an indented sub-list), never loose in the folders; search still finds a member directly, its card naming the group. The Intake section shows the non-nagging note ('this file carries N separate parts') beside the split button when the record carries it. Proven: app/verify_tray.js 17 live real-mouse Playwright checks over the public URL (nothing-before-confirm, stack/unstack/restack, type-ahead customer created, 3 rows qty 1 from a 2-part kit + a solo file, members nested not loose, search-names-group; scratch jobs + test customer removed after). SESSION 2 BUILT 2026-09-15 (Aristide 'continue' in his ratified order): the HOME drag is live -- grab any job card and drop it on a GROUP card (a part-list job, or its unfolded member list) to move the job inside; drag a grouped member off (drop on empty space) to take it out. Same pointer-event gesture as the tray (no HTML5 dnd -- one real-mouse language); a hint bar words the drop live ('drop: move X into Y' / 'take X out of Y', Esc cancels), the target card lights, a sub-6px drag stays a click (the card still opens), Escape cancels with nothing sent, and every drop posts through the standing /group door -- a bad drop (a part list onto a group) toasts the server's own refusal words and nothing moves. Client-only (app.js gesture + app.css drag styles), live on refresh. Proven: app/verify_homedrag.js 14 live real-mouse Playwright checks over the public URL (mid-drag words + highlight, move recorded + nested card, persistence across a fresh page, take-out, Escape, click-through, refusal verbatim, zero page errors; scratch fixtures removed); verify_tray.js 17 re-run green. Honest limits: the gesture moves ONE card per drag (no multi-select band on the home yet); the tray orders no machine x material (list-level pick after upload, per his answer 4); older multi-part jobs get their note on their next re-heal (the record is written by the pipeline).