f0c50d772fca5f97d6281b15248da83710364acb
14
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0abbe55041 |
bench: matrix v6 adds arch_roundtrip; four architectural correctness checks; the live arch smoke
The evidence for track F, in the shape tracks A, E and B + G used. - benchmarks/tasks_v6.py: 19 tasks, DEFAULT_MATRIX = "v6"; v5 to v2 stay addressable. arch_roundtrip draws the example plan with arch_plan_from_spec and reads it back without the spec: rooms_detect must find each labelled room within 0.1 % of its label and of the net floor computed by hand (4825 x 5750 and 3825 x 5750), the schedules must list D1, D2, W1, W2, and the plan is gated on a zero-issue critique and a finalize score of at least 90. A test removes one room label and the gate fails naming arch_room_unlabelled. - Four correctness checks, every number worked out by hand in the docstring: L / T / X junction corners and wall areas, a 4 x 5 m room labelled 20.00 m2 rather than its 21.84 m2 axis area, a door interrupting both faces, and a plan of plain lines read as 20 and 15 m2 at confidence 0.6. The published A/B report is re-run over 43 checks: 26 / 43 -> 43 / 43, zero regressed. - scripts/smoke_arch_com.py runs the whole plan once on a live seat and closes every document it opens; the CHANGELOG records what it returned. - The token suite measures a TOOL_PACKS=core,arch row; check_doc_numbers derives the task count from the v6 matrix; CLAUDE.md, both READMEs and the spec status line say what shipped. - fix(com): the first live smoke exited 1 - the room reader found 0 wall segments. Measured on AutoCAD 2026 (2026-09-23): with a makepy cache, ModelSpace.Item(i) returns the gen_py IAcadEntity wrapper (type(item).__name__ == "IAcadEntity") and item.StartPoint on an AcDbLine raises AttributeError, so every entity_list row lost its type-specific properties (28 wall LINEs, 0 with start/end). _entity_info now re-dispatches exactly that wrapper through _com_unnarrow; after the fix 38 of 53 rows carry start/end and the smoke exits 0 with both rooms at 27 743 750 / 21 993 750 mm2 and 0 critique issues. Re-dispatch measured at ~1.7 ms per entity (dynamic vs gencache alike). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |
||
|
|
898e775f93 |
bench: matrix v5 adds mech_assembly; the correctness suite grows with the mechanical and sheet checks
The evidence for tracks B and G, in the shape tracks A and E used.
- benchmarks/tasks_v5.py: 18 tasks, DEFAULT_MATRIX = "v5"; v4, v3 and v2 stay
addressable so an earlier report reproduces exactly rather than being only
described. mech_assembly is roadmap criterion 3 - a flange-coupling sheet
built from the part model and the sheet standard, through the code the
tools call (apply_titleblock, draw_part/add_view/dimension_part,
insert_std_part, extract_records -> draw_bom_table, add_balloon), gated on
two numbers that cannot be negotiated: drawing_critique(focus=None) returns
zero issues and the finalize score is at least 90 (it scores 100, 18/18 on
the v5 matrix). The adapter returns the focuses that fired, so a
regression names itself, and a test drops one balloon to prove the gate
fails and names mech_bom_balloon_mismatch.
- Seven correctness checks (32 -> 39). mech_section_hatch_area is the one
that cannot be faked: a sleeve of length 60, outside diameter 40 and bore
20 cuts two faces totalling 1200 mm^2 exactly, read back out of the drawing
through entity_measure. sheet_frame_iso5457_a3 pins the A3 frame (20,10 to
410,287 inside the 420 x 297 trimmed sheet); mech_iso286_on_dimension pins
40 H7 at +0.025/0 through the layout; std_part_iso4014_m12 pins s = 18 and
k = 7.5 by value; mech_thread_unrepresented_is_caught is the seventh: a
quality gate that never fires is not a gate.
- scripts/smoke_mech_com.py executed every new COM path once on AutoCAD 2026
(25.1s): frame, title block, a sectioned shaft with 12 dimensions, an ISO
4014 block with 1 ACADMCP_MECH chunk, a weld symbol, the parts list read off
the drawing, a linked balloon, an xref attached / listed / detached, a
31687-byte .dwg (AC1032) through ActiveX SaveAs, critique 0 issues, exit 0,
every scratch document closed. It retries RPC_E_CALL_REJECTED (measured:
the first call after Documents.Add is refused) and tracks its documents by
the document list, since SaveAs renames them.
- Defects the evidence found, each fixed with a test that fails on the old
code:
* ezdxf dimension_diameter put the text beyond the SECOND chord point;
ActiveX AddDimDiametric puts it beyond the first (measured live: a d50
from (x,170) to (x,220), leader 10, text at (x,160)). Headlessly every
front-view diameter stood on its own chain dimension. ezdxf now follows
ActiveX.
* draw_part's anchor goes on MECH; ActiveX refuses entity.Layer on a
missing layer (measured -0x7ffdfff7 'Key not found'). draw.py ensures
every target layer before the first entity.
* bom.extract_records filtered on INSERT; ActiveX names it BLOCKREFERENCE
(ObjectName AcDbBlockReference) - the live parts list was empty.
* COM _entity_info reported no dimension text_position: ModelSpace.Item
narrows to IAcadEntity, which has no TextPosition (measured
AttributeError); read through _com_unnarrow (TextPosition measured on
AcDbDiametricDimension, WCS). dim_overlap compared bbox centres and a
diameter collided with its own bore.
* pid graph raised KeyError 'start' mid-critique on a LINE whose point read
AutoCAD refused while busy; such a line is left out.
* the validator read "ISO 4014 - M12x60" as fake dimension text.
- The published A/B report is re-run over the grown suite rather than
re-typed (26/39 -> 39/39, 13 fixed, 0 regressed), check_doc_numbers derives
the task count from the v5 matrix, the token table is remeasured with a
TOOL_PACKS=core,mech row (193 tools / 61,673 tokens), and the README's
collected-tests figure is retaken (3990).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
|
||
|
|
39e6e2f9e4 |
docs(settings): track E shipped — CLAUDE.md sections 18-20, README, changelog with the live COM smoke record
CLAUDE.md gains items 18-20 (styles, page setup & templates, environment), the grown drawing_settings facade on item 11, lean 55 / 52 and TOOL_PACKS=all|core,pid,settings, and three conventions: layer states are ours (ACADMCP_LAYERSTATES XRECORD, mode "xrecord"), page-setup evidence is the PDF's own /MediaBox, nothing interprets coordinates in UCS. README token table re-measured on this tree with benchmarks/token_suite.py (ratio/v1 estimates): full 199 tools / 59,315 tokens, core,settings 190 / 55,593, core 168 / 48,825, lean 55 / 16,360, search 2 / 356; corpus re-derived from discovery.aliases: 186 AutoCAD command names, 933 synonym phrases, 204 tools. Styles & standards row, page setup & templates row, final environment wording, and "Known limitations of the settings track". CHANGELOG Unreleased: the track E intro, Added (styles, page setup & templates, environment, drawing_settings growth, benchmark evidence), Fixed (the Track A hardening list), Changed (three groups, packs, measured idle cost, release snapshot 204 · 8 · 5 · 3284). Spec status: implemented. Where the plan's text and the tree disagreed, the tree wins: mleaderstyle_create is implemented on both engines through the ACAD_MLEADERSTYLE dictionary and no `mleaderstyle` capability key exists (spec §4, capability maps), so the docs say so instead of calling it ezdxf-only; the Task 7 fix (tolerant ACADMCP_PID payloads, crossings tested against the arc) joins the hardening list the plan left it out of. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |
||
|
|
c2942d3c94 |
bench: matrix v4 adds page_setup_truth; correctness suite grows to 32 with three settings checks (A/B vs v1.5.1: 26 -> 32 / 32)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |
||
|
|
2be5e4180d |
docs(pid): track A shipped — CLAUDE.md, README, changelog with the live COM smoke record
scripts/smoke_pid_com.py runs the whole track against the live AutoCAD in a new document. ComBackend.connect() is lazy by design, so the script reads reachability from system_status()["connected"] rather than from connect() as the plan sketched, and closes its document without saving unless --keep is passed. On this machine (AutoCAD 2026, "25.1s (LMS Tech)") it exits 0: 5 nodes, 4 edges, 0 dangling, confidence_min 1.0, 0 critique issues, 2 XDATA chunks — identical to the headless engine on the same spec. The first attempt exited 2 on a stale win32com gen_py cache (a package folder holding only __pycache__); an environment fault, no backend change needed. A/B against v1.5.1 published as ab-v1.5.1-vs-v1.6.0-dev.json: 26/29 -> 29/29, three miss -> pass, zero regressed. check_doc_numbers.py now names the report and the two row labels in one place (AB_REPORT, AB_*_LABEL), and README.md / benchmarks/README.md carry the new rows; the v1.5.0 and v1.4.0 tables stay as history. README: P&ID row, the showcase and catalogue images, the token table re-measured (161 / 44,930 by default, 152 / 41,420 with TOOL_PACKS=core, lean 50 / 14,007), every stale count reconciled (154 -> 166 registered, 149 -> 161 advertised, corpus 158/672 -> 162/731 by the same count, 19 -> 20 groups, 6 -> 8 resources, six-task matrix with pid_roundtrip), a "Known limitations of the P&ID track" subsection, and the snapshot line at this machine's 2423 collected tests (CI has not run on this tree; noted in the changelog with the pre-existing 1369 vs 1363 drift). CLAUDE.md: section 17, sections 5 and 7 counts, TOOL_PACKS, the two 1.6 contracts and the reader rules. Spec status -> implemented. The plan and spec markdown were reformatted by ruff (fenced Python only) because `ruff format --check .` was already red on them at HEAD and the gate requires the whole tree clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |
||
|
|
8d9c444b76 |
bench: matrix v4 adds pid_roundtrip; correctness suite grows to 29 with three P&ID checks
tasks_v4.py extends v3 with one task the reader can fail on its own: the example spec is drawn through pid_from_spec's code and read back by the graph builder, which never sees the spec. The runner, the chart and the doc-number gate now default to v4; --matrix v3 / v2 reproduce the earlier sets, and tests/test_benchmark_v3.py labels its full-matrix run "v3" explicitly now that the default has moved. The plan's adapter check expected the two unnumbered lines to come back with no line number; draw_line builds one from the default number_format (bare sequence when size/service/spec/insulation are empty), so the task asserts the two authored numbers on the two process lines and sequence- built XDATA numbers on the other two instead. The published A/B report still covers 26 checks; Task 21 re-runs it against v1.5.1, which is what clears the remaining doc-number drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd |
||
|
|
6b9860e68e |
docs: apply 27 corrections from the adversarial triage, and rework the perf lane
The triage over the 43 unaddressed verdicts returned 4 code and 35 doc items. The code ones shipped in e24b46d; these are the documents. Twenty-one applied mechanically after a validation pass confirmed each locator still matched exactly once and each replacement was supported by the tree. Ten were held back because a re-verify pass found them mutually exclusive -- three patches rewriting the same benchmarks/README block, three rewriting the same OCS paragraph -- and applying them in sequence would have corrupted the files. Those were resolved by hand into one coherent edit each. One was rejected. The corrections worth naming: - **The A/B table contradicted itself in three files.** benchmarks/README.md and CLAUDE.md said 24 checks / 21-24 / 87.5% / "fixed 3" while the suite has 26 and the published JSON says 21/26, 80.8%, five fixed. All three now agree, and the five are split into the three new-capability `miss -> pass` and the two repaired-defect `fail -> pass`, which is the distinction the lane exists to make. - **"Every number below is produced by a script"** was false twice over: section 5's nine scores are literals a human assigned, and section 4 now quotes hand-collected timings. The claim is narrowed to the charts, which really are all rendered from committed data, and both exceptions are named. - **The OCS paragraph over-quantified.** TEXT rotation was given as the single exception; z components and HATCH boundaries are also entity-frame, and the live backend records `2d_polyline_coordinates_not_verified_against_live_autocad` in the same reason string. It now points at `ocs_normalized` as the live list. - **Transactions were shown as bare parity.** The server itself grades them differently -- `FeatureCapability(True, "undo_mark")` on COM against `(True, "snapshot")` headless -- and COM rollback sends `_UNDO B` without confirming it landed. The row says so. - **"Raw commands: Opt-in"** named a switch that does not exist. Both tools are registered unconditionally; `DANGEROUS_COMMANDS_ENABLED` only disables the sanitizer. - **"Wave A shipped 13 of a planned 39"** hardened an approximation: the only source writes `~39`. - **CAD_PROGID** said nothing beyond the connection was tested against BricsCAD/ZWCAD/GstarCAD, implying the connection was. It was not. Perf lane reworked against a fresh paired measurement. The old text claimed "28% slower than v1.4.0, median of three runs" and that `EZDXF_CALL_TIMEOUT=0` restored v1.4.0's numbers "exactly". Three problems: `perf_suite` runs each workload once per invocation and cannot produce a median, "exactly" was refuted by the figures in its own sentence, and the number moved when the timeout wrapper was rebuilt. It now reports the guard's cost -- +20.8% and +19.9%, three paired runs, median taken by hand -- says the figures have no published artifact, and says the wrapper rework recovered about a third of the v1.5.0 overhead rather than closing it. perf-ezdxf.json and the perf chart regenerated against the shipped code, and the README table rebuilt from that artifact so the two cannot drift. 1267 passed, 1 xfailed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b03a7615b1 |
release: v1.5.0 — discovery layer, honesty debt closed, Wave A
Tool count 131 -> 154; 474 -> 1242 collected tests. The release exists for two measured reasons. A 149-tool catalog costs a client ~40,300 tokens before it has asked for anything, and a drafter searching the way drafters think -- FILLET, BPOLY, QSELECT, WBLOCK -- scored df=0 against the stock index, because those words were simply not in the data. Discovery and batching - DISCOVERY_MODE=search replaces the catalog with search_tools + call_tool, ranked over an AutoCAD command and synonym corpus (discovery/aliases.py) on top of fastmcp's BM25 index. Measured: 40,305 -> 356 tokens advertised. - cad_batch runs a step list in one round trip; fields= projects result-heavy responses. The `core` profile is gone -- discovery replaced it. Honesty debt (Tier 0) - OCS/ECS: `extrusion` appeared nowhere in this codebase, so mirrored and rotated geometry reported coordinates that were quietly wrong. backends/ocs.py translates at the backend boundary; every tool coordinate is WCS on both engines, and a tilted plane refuses rather than answering with a number that looks fine. - drawing_save_as(fmt="dwg") wrote DXF bytes to a .dwg path. drawing_audit never repaired. analysis_measure_area shoelaced points the caller typed in. - ezdxf calls gained a per-call timeout, so one hung call can no longer wedge a server whose document lock is a single asyncio.Lock. Architecture - The 1854-line backend ABC is 19 contract modules; @capability(key, reason=) makes optional methods declarative and a gate fails on undeclared holes. - 8 layout/viewport tools, CHSPACE, CAD_PROGID escape hatch. - Wave A: selection filters, boundary tracing, hatch depth, annotation objects, measurement -- 13 tools of a planned 39. The REGION and 2D-boolean family was cut on evidence: add_region() yields zero ACIS bytes and the greiner_hormann substitute loses 28.2% of the area on a square with one semicircular edge. Verified against a live AutoCAD 2026, which found four COM defects no amount of reading would have caught -- AcadPViewport has no ViewCenter, and the line that set it had been swallowed by a bare except since v1.4. Benchmark v3 (15 tasks) and what it caught - v2 scored this server 10/10, which carried no information: every task in it exercised something the server was built around. Five tasks were added because they can fail, and three did while being written -- a hatch could not be measured though the refusal listed HATCH as measurable, the boundary tools and the measure tool disagreed about the same shape (139.2177 vs 139.2699), and a circle stored as two bulged vertices measured 0.0. - Competitor reports are NOT re-scored. They are pinned v1.4 runs against v2 and were never asked these five questions; the chart shows those rows `not run`. - Correctness A/B: 21/24 -> 24/24, zero regressions. Performance, stated plainly The published v1.4 perf report was recorded on CPython 3.14 and the new one on 3.11.15, so the apparent 2-6x speedup is the interpreter, not this release. Re-measured on one interpreter, v1.5.0 is 28% slower creating entities and 22% slower on the 10k roundtrip. Fully attributed: EZDXF_CALL_TIMEOUT=0 restores v1.4.0's exact numbers. That is the deadlock fix being paid for, the knob is documented, and winning it back is on the 1.6 roadmap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e04c814cb8 |
docs(release): v1.4.0 - changelog, README live-benchmark section, CLAUDE.md sync, consistency gates
- CHANGELOG 1.4.0 section (infra + features), Unreleased now lists the 1.5 openers - README: v1.4 snapshot (131 tools / 6 resources / 5 prompts / 474 tests), CI + PyPI badges, live-run benchmark table + chart, mcp-name registry marker - CLAUDE.md: sections 15 (layouts) + 16 (solids), tool profiles, ISO 286 fits; counts synced to the live surface - tests/test_release_consistency.py: locks pyproject/version.py/CHANGELOG/README/server.json versions, README counts vs registrations, section-header counts, Dockerfile COPY vs wheel includes, mcp-name marker Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
712cf00c5c |
v1.2.0
Adds production-grade engineering features and tools: 2D GD&T (feature control frames + datum features) via engineering/gdt.py, ISO‑129 dimension tolerance support (engineering/tolerances.py) and an ezdxf/COM plumbing for toleranced dims, a scalar drawing score + invalidity ratio (engineering/scoring.py) wired into drawing_finalize, in-place entity editors (entity_edit_text/entity_edit_geometry), and a friendly drawing_settings facade. Includes server tool wiring, COM/ezdxf backend implementations, datum-consistency critique, many unit tests, README/CLAUDE/CHANGELOG updates, and a version bump to 1.2.0. Also corrects COM backend capability label (entities_2d). |
||
|
|
2c2fba1459 |
docs: release v1.1.0 — accurate counts, changelog, audit report
- pyproject: version 1.0.0 -> 1.1.0 - README: 110 tools / 5 resources (was 87 / 6), 318 tests, new "Closed-Loop Quality Gate" highlight, Engineering + Premium tool categories, refreshed roadmap (1.1 shipped; 1.2 closed-loop moat; 1.3 ISO production). - CHANGELOG: comprehensive [1.1.0] entry (Added/Changed/Fixed/Security). - CLAUDE.md: drop removed CommandResult dataclass; ~110 tool count. - docs/analysis/03-AUDIT-VERIFICATION.md: the verified audit + fix plan. |
||
|
|
9258da429f |
Add AutoCAD MCP premium skill and backend APIs
Introduce the autocad-mcp-premium skill with workflow docs, examples, and references (.claude/skills/autocad-mcp-premium/*). Add PlanSpec/critique plumbing and engineering helpers (engineering/plan_spec.py, engineering/critique.py) plus tests and a smoke script. Extend backend API (backends/base.py) with corner operations and premium meta-tools (trim/extend/fillet/chamfer, drawing_plan, drawing_critique, point_from_snap, construction_xline/clear, drawing_apply_iso_layers, dimension_auto, entity_select_smart) and implement COM backend corner ops (backends/com_backend.py) with placeholders for meta-tools. Update CLAUDE.md to document the premium drawing rules and standard workflow. Misc: add examples, references, and tests for premium features, and minor server/backend adjustments. |
||
|
|
88a9005a6a |
Add deterministic engineering CAD layer (gear, keyway, titleblock, validator)
Introduces an engineering/ package that lets MCP clients produce production- quality technical drawings without LLM-improvised geometry. Adds 7 new MCP tools, an 8-step pre-completion validator, and an automatic linetype + layer bootstrap on drawing_new so CENTER/HIDDEN/PHANTOM and standard mechanical layers (GEOMETRY, DIM, HATCH, TEXT, TITLEBLOCK, ...) are always available. - engineering/gear.py: pure-Python involute math, 40+ points/flank, helical + spur front views, deterministic section A-A (no helix lines in section). - engineering/keyway.py: DIN 6885 keyway table + parametric keyed bore / side-section drawers. - engineering/titleblock.py: ISO 7200 A3 (420x297 mm) title block; title text is written verbatim to the title cell. - engineering/validator.py: DrawingValidator with 8 checks (real DIMENSION entities, no hidden orphans, linetypes loaded, bore + keyway in both views when expected, title consistency e.g. forbid 'HELICAL SPUR GEAR' when helix_angle truthy, saved-to-disk + file-on-disk, screenshot exported, dwg path returned). - backends/ezdxf_backend.py: AutoCAD-only linetype fallback (HIDDEN, BORDER families) so ezdxf doc gets correct patterns when linetype_load is called for names ezdxf.tools.standards does not ship. - backends/base.py: concrete helpers set_layer_active / ensure_linetypes. - server.py: Section 12 with 7 engineering tools, drawing_new(bootstrap= True), and an ENGINEERING WORKFLOW block in the MCP instructions string. - 30 new tests covering gear math, DIN6885 lookup, ISO A3 layout, title verbatim, and every validator check. Tool count 89 -> 96. |
||
|
|
7b121ab416 | Initial commit |