woodshop/SHOP_PACKET_PLAN.md

96 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 |