From a8482a5f0d8179d2a7d3a016e577c95a575013d0 Mon Sep 17 00:00:00 2001 From: Umut CAN Date: Tue, 22 Sep 2026 16:52:23 +0300 Subject: [PATCH] docs(spec): align tracks B+G with the written plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The five gaps the plan's reconciliation found, each resolved in the spec: part placement lives in draw_part(at=, rotation=) so the dataclasses carry no origin; engineering/sheet/refs.py is gone with the contract correction; image_attach takes no clip and titleblock_apply no position (the ISO 7200 corner is fixed by the standard) — both recorded as out of 1.6; balloon_add places one balloon per call against the item numbers bom_extract already assigned. Records the four feature tables that ship empty (DIN 509, DIN 471/472, DIN 332-1, ISO 3601-2): no row could be verified against the standard here, so the structure, the row-key contract and the refusal ship without rows, and the features draw from explicit dimensions until the tables are transcribed. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd --- .../specs/2026-09-22-v1.6-mech-design.md | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) 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**