fix(dimensions): diameter and radius callouts measured the leader as geometry

`add_diameter_dim` / `add_radius_dim` measure to the point they are handed;
`leader_length` is a text placement. The ezdxf backend passed
`centre + (radius + leader)` as that point, so the leader became part of the
measurement: a true 40 mm bore was dimensioned 60 at the default
`leader_length=10`, and 108 at 34. Radius callouts were `leader_length` too
large the same way.

This is the worst class of defect for this project -- a wrong number, at
default settings, on the one part of a drawing that exists to carry numbers --
and it shipped in v1.4.0 and earlier. The size now comes from `radius` and
`location` only places the text.

The live COM backend was never affected: ActiveX's AddDimDiametric takes the
two chord points and the leader length as separate arguments. The two engines
had been disagreeing by 2 x leader_length on the same call.

Found while building the drawing for the new README, whose own bore callout was
wrong. Two checks added to correctness_suite.py; both report fail -> pass
against v1.4.0, not miss -> pass, which is what separates a repaired defect
from new capability in that lane. A/B is now 21/26 -> 26/26, five fixed, zero
regressed.

README rewritten from scratch
- Hero is a real ISO A3 sheet the server drew: m6 z24 involute spur gear, DIN
  6885 keyed bore, section A-A, ISO 129 dimensions, ISO 286 H7 fit, ISO 7200
  title block, 56 entities, drawing_critique clean. New
  scripts/render_readme_showcase.py rebuilds it, and the tool-call sequence
  that produces it is printed in the page.
- Star history chart, badge row, capability matrix, five evidence lanes, and a
  "what this release is bad at" section carrying the 28% throughput regression.
- Every image and repo link is now an absolute URL: README.md is the PyPI long
  description, where relative paths 404.

Corrections this work forced, all measured
- The df=0 example was wrong. FILLET is already in entity_fillet's own text;
  the commands that genuinely scored zero are WBLOCK, PEDIT, OVERKILL,
  LAYTRANS and MATCHPROP.
- 40,305 tokens is the tools/list wire payload; ~25,143 is the part forwarded
  to the model. The old wording said "of schema", which is neither.
- `--tokenizer anthropic` needs a package and credentials this repo does not
  lock, and refuses rather than falling back. Said so.
- Discovery ranks over the 149-tool advertised catalog, not the 154 registered.
- Five middlewares, not four; the fifth is what makes refusals machine-readable.
- Five of the 27 capability keys are environment-dependent, so the matrix
  carries footnotes instead of bare ticks.
- "Every coordinate is WCS" has one deliberate exception: TEXT rotation.
- render_live_chart's axis still said "fixed 10-task matrix" while our bar came
  from v3's fifteen. Each bar now carries its own matrix.
- .env.example said MAX_UNDO_STACK=50 (code: 5) and omitted four real
  variables, two of them the remote-HTTP controls.
- server.json described an empty ALLOWED_PATHS as blocking access. It disables
  the allowlist.
- server.py called the lean profile ~46 tools; it is 47.
- backends/capability.py cited a test file that does not exist.

1249 passed, 1 xfailed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Umut CAN
2026-08-06 11:24:44 +03:00
co-authored by Claude Opus 5
parent e27071ab48
commit 8f405bddf3
14 changed files with 1316 additions and 851 deletions
+24 -4
View File
@@ -355,10 +355,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
exactly this, but a refusal is still an exception and was being caught by the
generic handler — "your engine cannot reach this" and "your server got this
wrong" are different findings about a competitor.
- Three measurement checks added to `correctness_suite.py` (24, was 21). They
are new capability rather than repaired regressions — v1.4.0 misses them by
not having the method — and they are there because all three broke during
this release and nothing outside their own unit tests would have noticed.
- Five checks added to `correctness_suite.py` (26, was 21), and the two kinds
read differently in the A/B table. Three measurement checks are new
capability — v1.4.0 misses them by not having the method (`miss → pass`) —
and are there because all three broke during this release. Two dimension
checks are repaired defects: v1.4.0 has the methods and gets them wrong
(`fail → pass`). Result against v1.4.0: 21/26 → 26/26, five fixed, zero
regressed.
### Changed
@@ -704,6 +707,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `release.yml` now runs `ruff format --check .` alongside `ruff check .`,
matching the CI lint job — the release gate previously skipped formatting.
- **Every headless diameter and radius dimension reported the wrong number, at
default settings.** `add_diameter_dim` / `add_radius_dim` measure to the point
they are given; `leader_length` is a *text placement*. Passing
`centre + (radius + leader)` as that point made the leader part of the
measurement, so a true ⌀40 bore was dimensioned **60** with the default
`leader_length=10`, and **108** at 34. Radius callouts were `leader_length`
too large the same way. This is the worst class of defect for this project —
a wrong number, silently, on the one part of a drawing that exists to carry
numbers — and it shipped in v1.4.0 and earlier. Now the size comes from
`radius` and `location` only places the text.
The live COM backend was never affected: ActiveX's `AddDimDiametric` takes
the two chord points and the leader length as separate arguments, so the two
engines had been disagreeing by `2 × leader_length` on the same call.
Found while building the sheet in the README's hero image, whose own bore
callout was wrong. Two checks added to `correctness_suite.py` (26, was 24);
both report `fail → pass` against v1.4.0 rather than `miss → pass`, which is
what distinguishes a repaired defect from new capability in that lane.
- **A HATCH could not be measured, and the refusal listed HATCH as
measurable.** `entity_measure` had no HATCH branch, so a hatch fell through
to the generic error — whose own text named HATCH among the measurable types.