Commit Graph

4 Commits

Author SHA1 Message Date
rob b9b0871ac3 Unify CLI/voice cut list onto the CutPlan (single source of truth)
format_cutlist now renders from build_cut_plan(scene) via a new
format_plan_cutlist(plan), instead of its own board-feet/shopping math. The CLI,
voice, and BOM window all read the same CutPlan now, so they can't disagree —
and kerf, sanding allowance, species, offcut reuse, and unplaced warnings all
surface in the text cut list automatically.

- cut_rows/shopping/board_feet kept (still used elsewhere) but no longer back
  the text renderer.
- Output shape preserved (CUT LIST / Total / SHOPPING) plus species labels,
  rough→final lines, and a WON'T FIT section.
- tests: CLI shopping counts == BOM CutPlan counts (kerf case), species +
  sanding surfaced, unplaced flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 22:06:49 -03:00
rob e4f9cedf4a Add plywood (sheet stock)
Plywood is sheet stock — fixed thickness, width cut per-panel. lumber.py adds
ply-1/8…ply-3/4 specs + is_plywood/plywood_thickness and normalizes "3/4
plywood" -> "ply-3/4". scene.place(stock, length, width_in=) requires a width
for plywood (lumber ignores it). Cut list reports plywood in sq-ft and buys it
in 4×8 sheets (lumber stays board-feet / 8' sticks).

Wired through CLI (place --width), voice (wood-place width arg + prompt note),
and the Parts-tab manual add (plywood in the dropdown + a width field enabled
for plywood). Geometry/export/render work unchanged (section = thickness×width).

91 tests pass; verified a plywood top renders as a thin panel and exports to STEP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 12:33:49 -03:00
rob aabf289562 Cut list accounts for protruding tenons
A tenon adds length beyond the board's end, so the real piece you cut is longer
than length_in. cutlist.cut_length() now adds end-tenon protrusions to the cut
length used by the cut list, board-feet, and the buy-list (subtractive features
like mortises/holes don't change the stock you buy, so they're ignored). The
cut list notes when lengths include tenons.

70 tests pass (end-tenon extends cut length; cut features don't).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 16:04:20 -03:00
rob 914c86303f Add 3D orientation, richer operations, and cut list
3D orientation (the key gap): boards now have yaw/tilt/roll, so legs and
uprights can stand vertically. geometry.py and viewer.py apply the full
rotation; join is orientation-aware (vertical boards rest their base on the
target face). Old rotation_deg scenes migrate transparently.

New operations + CLI subcommands + wood-* tools: stand, lay, rotate, move,
trim (cut to length), copy, rename (human aliases, resolvable by name), clear.
Parts resolve by id OR name.

Cut list (cutlist.py): grouped cut list, board-feet (nominal), and an 8'-stick
shopping estimate with waste — the workshop-assistant payoff.

Driver: auto-discovers all wood-* tools (glob), richer prompt that decomposes
"build a table" into place/stand/join/move and labels parts. Verified: one
sentence -> an 8-board table base with a correct cut list.

14 wood-* CmdForge tools regenerated. 36 tests passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 01:42:33 -03:00