woodshop/SHOP_PACKET_PLAN.md

5.5 KiB
Raw Permalink Blame History

Shop Packet Plan

A living plan for turning the BOM into a shop-packet generator. Adjust as we go.

Status: Phases 04 implemented (cutplan.py model; multi-strategy auto-layout; deterministic instructions + AI polish; rule-based jig suggestions; constrained drag-edit layout). Logic is unit-tested; the drag/print GUI needs a real display to verify interactively.

Review fixes applied: one active CutPlan rendered by every tab; unplaced parts surfaced in Shopping; process-stable shuffle (hashlib); kerf-gap validation; drop stock-type compatibility; waste/score recompute after manual edits; rotation legality (settings/grain); position-aware jig grouping.

Phase 1 now complete: bounded branch-and-bound exact lumber packing (_min_bins/_pack_lumber_exact, ≤12 pieces, FFD-seeded with a count bound), guillotine free-rectangle plywood packing (_pack_plywood_guillotine, best-area-fit + rotation), a real "Best of 100" control in the Cut Layout tab, and richer scoring that prefers more & longer reusable offcuts (reusable_in tie-break). Lock-aware re-optimization also landed (locked pieces preserved through "Find better layout"/"Best of N").

Remaining follow-ups: grain-direction in auto-layout, on-hand offcut inventory, opt-in jig material in the BOM.

Guiding principle

The math layer is deterministic and inspectable; AI is used only for narrative (instruction wording, jig explanations). Cut lengths, kerf, counts, layouts, jig dimensions, validation, and warnings all come from code — the AI never invents a number.

UI language: say "Optimize" / "Find better layout", never "optimal" (woodworking wants explainable good layouts, not slow provably-perfect ones).

Data flow

Scene → CutItems → StockInventory → CutPlan → ShopPacket(view)

The keystone: CutPlan (cutplan.py)

Dataclasses, JSON-friendly, stable IDs everywhere (CutItem.id, StockPiece.id, Placement.id) — never rely on list position. Serializable from day one (to_dict/from_dict) so we can save manual layouts, compare strategies, export, debug.

  • ShopSettings — kerf, stick/sheet sizes, offcut-usable thresholds, plywood rotation allowed, grain direction (future), tolerances (mortise/tenon clearance, sanding allowance, reveal). Defaults present from day one even before they're in the UI.
  • CutItem — a required piece (part id, stock, length, width, is_sheet, note e.g. "incl. tenon").
  • StockPiece — a physical stick/sheet with its placements and waste regions.
  • Placement — a cut item on a stock piece: position (x[,y]), rotated?, locked?.
  • WasteRegion — leftover, with a reusable flag (≥ threshold).
  • CutPlan — settings, items, stock_pieces, unplaced, strategy, score, warnings.
    • score = {stock_count, waste_area, reusable_offcuts, warnings, strategy_name} — detailed, so the UI can explain why one layout beats another.
  • build_cut_plan(scene, settings=None, strategy="decreasing") -> CutPlan.
  • validate_cut_plan(plan) -> [problems] — no piece outside stock, no overlaps, kerf respected, every item placed-or-warned, stock dims respected, rotations legal.

ShopPacket stays thin (a view/composition over cut rows + shopping rows + cut plan + warnings) until CutPlan is solid.

Phases (commit after each)

Phase 0 — CutPlan + ShopSettings (keystone). New cutplan.py with the model + build_cut_plan + validate_cut_plan. Port the current FFD (lumber) / shelf (plywood) packers behind it. Keep old APIs (layout.nest_lumber/ nest_plywood/stock_counts/waste_summary, cutlist.shopping/waste_summary) as thin wrappers over build_cut_plan so existing tests/UI keep working. BOM window renders from CutPlan. Tests: lumber, plywood, kerf, tenon extra length, unplaced/oversize warnings, JSON roundtrip.

Phase 1 — smart auto-layout. Strategies behind the buttons: FFD, BFD, bounded exact (small jobs, capped), random restarts / best-of-N for big jobs; objective "minimize stock, then maximize useful offcuts (bonus for common 12/24/36″)". Plywood: per-panel rotation; shelf/guillotine/maxrects; score by sheet count, waste area, reusable-offcut size. Buttons: Optimize · Try Alternative · Best of N; surface warnings.

Phase 2 — structured instructions. Deterministic ordered steps from CutPlan + scene (buy → cut per plan → mark joinery → repeated cuts/jigs → cut/drill features → dry-fit → assemble → finish); then AI polishes wording (numbers stay from code). Instructions tab.

Phase 3 — jig suggestions (rule-based → AI explanation). Detect patterns (identical crosscuts, repeated end-offsets, repeated mortises/holes, mirrored L/R, repeated angles, repeated panel widths) → candidates with computed dims (stop block, spacer, drill template, story stick, mortise template, angle sled). AI explains build/use. Jigs are shop aids kept separate from project parts — optional, opt-in before any jig material enters the BOM. Jigs tab.

Phase 4 — constrained manual layout editing. Drag in the layout view as a constrained planner: snap to stock edges / kerf / neighbors; invalid = red; move pieces between sticks/sheets; rotate plywood (if grain allows); lock a piece so re-optimization works around it; live "valid / invalid / saves a stick / wastes more" feedback. Builds on CutPlan.locked + validate_cut_plan.

Deterministic vs AI

Code (deterministic) AI (narrative only)
lengths, kerf, counts, layouts, scores, jig dims, validation, warnings instruction wording, jig build/use explanations, summaries