diff --git a/docs/superpowers/specs/2026-09-22-v1.6-mech-design.md b/docs/superpowers/specs/2026-09-22-v1.6-mech-design.md index 27e6368..8f05015 100644 --- a/docs/superpowers/specs/2026-09-22-v1.6-mech-design.md +++ b/docs/superpowers/specs/2026-09-22-v1.6-mech-design.md @@ -67,6 +67,21 @@ SECTION 24 Sheet and delivery (11). the `dwg_write` capability and names the ODA route). - XLSX export unless `openpyxl` is present (the `[pdf]`-extra pattern); CSV is always available. +- Clipping a raster underlay (`image_attach` places and scales; a clip boundary + is a 1.7 item), and placing a title block anywhere but the ISO 7200 corner the + standard fixes. +- **Four feature tables ship empty** (recorded 2026-09-22, during planning): + DIN 509 E/F, DIN 471 / DIN 472, DIN 332-1 A/B and ISO 3601-2. Their structure, + SOURCE, row-key contract and coverage refusal ship; no row does, because no + row could be verified against the standard's own table on this machine (the + repository's web tool is out of credits). The features draw correctly from + explicit dimensions — `Undercut(profile=…)`, `RetainingGroove(m=, d2=)`, + `CentreHole(d1=, d2=, d3=, t=)`, `ORingGroove(b=, h=)` — and every lookup is + refused by name until a row is transcribed. Filling a table later is a data + edit with no code change, and a shape test already fails any row that lands + missing a column the drawing code reads. The alternative — plausible numbers — + ships a wrong workshop drawing, which is the one failure this repository + refuses to risk. ## 3. Architecture @@ -99,7 +114,6 @@ engineering/sheet/ revision.py revision block rows + revcloud + triangle tags bom.py ISO 7573 parts list: extract → rows → table; balloons ISO 6433 extract.py attributes/XDATA → CSV (always) / XLSX (optional dependency) - refs.py xref attach/list/reload/bind/detach, image attach backends/contracts/refs.py (new) xref_attach, xref_manage, image_attach, drawing_export_dwg server.py SECTION 21 (6) · SECTION 22 (3) · SECTION 23 (5) · SECTION 24 (11) @@ -143,7 +157,6 @@ class RevolvedPart: segments: tuple[Segment, ...] # left to right along +X features: tuple[Feature, ...] = () material: str = "steel" # drives the ISO 128-50 hatch - origin: tuple[float, float] = (0.0, 0.0) # part-local; the tool places it in WCS @dataclass(frozen=True) class PrismaticPart: @@ -152,7 +165,6 @@ class PrismaticPart: thickness: float # along +Z features: tuple[Feature, ...] = () material: str = "steel" - origin: tuple[float, float] = (0.0, 0.0) ``` Rules the model enforces **before any write** (the repository's validate-first @@ -331,7 +343,7 @@ where the part was not built from the model (a foreign drawing being finished). along the top, 50 mm modules), centring marks, trimming marks. Geometry is pinned against the ISO 5457 table by test — the frame is the one thing every sheet has, so a wrong margin is visible on every drawing this server makes. -- `titleblock_apply(size, fields, position)` — ISO 7200 data fields for every +- `titleblock_apply(size, fields)` — ISO 7200 data fields for every sheet size; the existing `titleblock_apply_iso_a3` becomes a thin alias that calls it with `size="A3"` so no caller breaks. Carries the projection-angle symbol chosen by the part tools. @@ -343,9 +355,10 @@ where the part was not built from the model (a foreign drawing being finished). standard, material, mass if known). Never modifies the drawing. - `bom_table(rows|auto, at, standard="ISO 7573", direction)` — draws the parts list as a real TABLE, growing upwards from the title block per ISO 7573. -- `balloon_add(handles|rows, at, start, leader_to, arrangement)` — ISO 6433 item - references, auto-numbered to match the parts list, linked by XDATA so a rerun - renumbers instead of duplicating. +- `balloon_add(item, at, leader_to, targets)` — one ISO 6433 item reference per + call (the caller loops over the rows `bom_extract` already numbered), linked to + its targets by XDATA so a rerun renumbers in place instead of duplicating. The + `mech_bom_balloon_mismatch` focus is what proves a balloon and its row agree. - `data_extract(scope, format, path)` — the same rows to CSV (always) or XLSX (refused with `xlsx_write` when `openpyxl` is absent, naming the extra). - `xref_attach(path, at, scale, rotation, kind)` — external reference as @@ -354,7 +367,7 @@ where the part was not built from the model (a foreign drawing being finished). `list`, `detach` and `path` work headlessly; `reload` and `bind` on a live seat or headlessly through `ezdxf.xref` where it is faithful — where it is not, the `xref_live` capability refuses honestly rather than pretending. -- `image_attach(path, at, scale, rotation, clip)` — raster underlay +- `image_attach(path, at, scale, rotation)` — raster underlay (`add_image_def` + `add_image`), both engines. - `drawing_export_dwg(path, version)` — COM `SaveAs` natively; headless through `ezdxf.addons.odafc` **only when the ODA File Converter is installed**