G-1 records the standing lesson for this document: an interface document should contain no statement a reader will take as fact when it is not yet one. Three remained in it. Section 2 chain diagram read DECIDES against CT 101, which decides nothing and sets no header. Section 5 routing table listed /m/stl as members. Section 5 stated flatly that export is gated today. Section 8 said the opposite of all three, further down, where an outside implementer would reach it second. None of the three is now removed or softened. The scheme stays and each says which it is - where the line falls once enforced, not where it falls now. README: deploy/ added to the layout, absent since 12 SEP. The reading order no longer contradicts PROCESS section 8 and HANDOFF section 0, and points at DIVERGENCES.md. The AGPL section 13 obligation is marked not met, stated in the document that states the obligation. ACCEPTANCE section 7 records that its correction finally landed in HANDOFF section 7, and why parking a correction in a second document is a bad pattern: it sat here for three weeks while the wrong numbers stayed where people read first. Applied by anchored patcher. Suite 643 passed, oracle intact. Documentation only.
165 lines
7.4 KiB
Markdown
165 lines
7.4 KiB
Markdown
# ACCEPTANCE.md
|
||
|
||
**What the acceptance suite asserts, and to what tolerance.**
|
||
|
||
This document exists because until now the answer lived in two places, neither of
|
||
them readable: a `tolerance` block inside a hashed JSON fixture, and one line of
|
||
`test_oracle.py`. A person asking "how close does the port have to be?" had to
|
||
read code to find out, and the reason for the numbers was nowhere.
|
||
|
||
Last updated 2026-09-13. Section 7's correction landed; F-034 closed 2026-08-22.
|
||
|
||
---
|
||
|
||
## 1. What is being compared
|
||
|
||
The port is measured against a frozen 123-case oracle generated by the OpenSCAD
|
||
reference at revision 8.0.0, under OpenSCAD 2021.01 with BOSL2 `92d697c2`. 113
|
||
cases the reference accepted, 10 it rejected.
|
||
|
||
The oracle does **not** record full-precision geometry. It records what
|
||
OpenSCAD's `echo` printed, which is C's `%g` at default precision — **six
|
||
significant figures**. That fact is load-bearing and most of this document
|
||
follows from it.
|
||
|
||
## 2. Two tolerance regimes
|
||
|
||
**Regime A — declared absolute.** The oracle's own `tolerance` block:
|
||
`lengths_mm = 1e-4`, `areas_mm2 = 1e-3`. Applies to every compared float except
|
||
the three keys named below.
|
||
|
||
**Regime B — six-significant-figure last place.** Applies to
|
||
`SECTION_AREA_MM2`, `VOLUME_MM3` and `MASS_G` only.
|
||
|
||
```
|
||
ulp(v) = 10 ** (floor(log10(|v|)) - 5) the value of the last digit
|
||
the reference actually wrote down
|
||
bound = 8 * ulp(expected)
|
||
```
|
||
|
||
Concretely, across the oracle's observed magnitudes:
|
||
|
||
| key | magnitude | last place | worst observed | bound |
|
||
|---|---|---|---|---|
|
||
| `SECTION_AREA_MM2` | 117 – 474 mm² | 0.001 | 0.003 (3 ULP) | 0.008 |
|
||
| `VOLUME_MM3` | 11,742 – 47,364 mm³ | 0.1 | 0.3 (3 ULP) | 0.8 |
|
||
| `MASS_G` | 14.6 – 58.7 g | 0.0001 | 0.0005 (5 ULP) | 0.0008 |
|
||
|
||
The bound scales with magnitude by construction, so it needs no revision if a
|
||
future case is an order of magnitude larger or smaller.
|
||
|
||
## 3. Expectation statements
|
||
|
||
These are what a passing suite means. Each is asserted by a test.
|
||
|
||
**E-1 — Every accepted case builds.** `build(family, profile, params)` returns a
|
||
`Result` for all 113. A raise is a failure, not a rejection.
|
||
|
||
**E-2 — Every rejected case is rejected.** All 10 raise `ProfileRejected`, and
|
||
the message is non-empty and names the parameter and the limit. Reproducing the
|
||
geometry while accepting a case the reference refused is not a passing port.
|
||
|
||
**E-3 — Counts are exact.** `SECTION_PARTS`, `STRAP_CHANNELS` and
|
||
`BUNDLE_COUNT` match with zero tolerance.
|
||
|
||
**E-4 — Everything that positions material is exact to regime A.**
|
||
`ENVELOPE_X_MM`, `ENVELOPE_Y_MM`, `MIN_WALL_ACTUAL_MM` and every profile extra
|
||
(`AF_*`, `FIN_*`, `SPOKE_*`, `RING_*`, `T_*`) agree within 1e-4 mm.
|
||
|
||
Measured: **exact in all 123 cases, no exceptions.** This is the strongest claim
|
||
the project makes and regime B must never be extended to cover any of it. If a
|
||
future change makes one of these keys need a looser bound, the change is wrong.
|
||
|
||
**E-5 — The three discretisation-limited keys agree to regime B.**
|
||
`SECTION_AREA_MM2`, `VOLUME_MM3` and `MASS_G` agree within 8 ULP of the oracle's
|
||
six-significant-figure record.
|
||
|
||
These three are one underlying quantity reported three times: volume is area ×
|
||
100 mm, mass is volume × 1.24 g/cm³ ÷ 1000. Verified across all 113 accepted
|
||
cases — `VOLUME/AREA` is exactly 100.0 with a maximum deviation of 2.8e-14, and
|
||
`MASS/VOLUME` is uniform to 1e-8. One bound therefore governs all three
|
||
honestly, rather than three unrelated policies.
|
||
|
||
**E-6 — The tolerance policy is not vacuous.** For every compared value, the
|
||
bound in force is at most 1e-4 relative. This is asserted directly, so a future
|
||
edit that loosens the comparison until it stops catching regressions fails a
|
||
test rather than passing silently.
|
||
|
||
**E-7 — The oracle is unmodified.** Its recorded hash covers the whole document
|
||
except the hash field. Editing the fixture to make a test pass breaks this by
|
||
design.
|
||
|
||
**E-8 — The 2D path imports no CAD kernel.** Building a cross-section must not
|
||
pull in `cadquery`, `OCP` or `build123d`.
|
||
|
||
**E-9 — The suite is green.** There are no expected failures. A red `make test`
|
||
means something is wrong.
|
||
|
||
## 4. Why the accuracy criterion does not source these numbers
|
||
|
||
The project's stated accuracy criterion is 0.01 mm over the entire set
|
||
(`PRECISION.md`). The obvious move — bound the area error by
|
||
`perimeter × 0.01 mm` — was measured on 20260822 and rejected.
|
||
|
||
Re-expressing every measured area discrepancy as the uniform boundary
|
||
displacement that would produce it gives `|dA| / P`, which is directly
|
||
comparable to the criterion:
|
||
|
||
```
|
||
median 0.000e+00 mm
|
||
p95 9.075e-06 mm
|
||
max 1.434e-05 mm one seven-hundredth of the criterion
|
||
```
|
||
|
||
A `perimeter × 0.01` bound would be 1.86 mm² at the smallest section and
|
||
4.54 mm² at the largest — between 1,800 and 4,500 times the worst real
|
||
discrepancy. It would catch nothing.
|
||
|
||
Perimeter is also the wrong normaliser. It anti-correlates with the error: the
|
||
largest discrepancy, 0.003 mm², occurs at P = 209.26 mm, and the smallest,
|
||
0.001 mm², at P = 454.41 mm. The error is driven by how many corners tip from 12
|
||
arc segments to 13 (F-034), which is a property of the arrangement, not of
|
||
boundary length. Dividing by perimeter widens the spread from a factor of 3 to a
|
||
factor of 6.5.
|
||
|
||
The real quantiser is the reference's own six-significant-figure `echo`. Every
|
||
discrepancy in the set is 0.001, 0.002 or 0.003 mm² — one, two or three units in
|
||
the last digit the reference ever recorded. Regime B is a bound on the mechanism
|
||
that actually produces the disagreement.
|
||
|
||
Physically, both boundaries sit within 0.0027 mm (4x) and 0.0043 mm (3x) of a
|
||
true arc and within ~0.4 µm of each other. Two orders inside the criterion. The
|
||
geometry was never in question; only the comparison was.
|
||
|
||
## 5. What would invalidate this
|
||
|
||
- **Any case exceeding 3 ULP.** The mechanism would have changed and the bound
|
||
would no longer describe it. Investigate before widening.
|
||
- **A case where `VOLUME/AREA` is not the model length**, or where
|
||
`MASS/VOLUME` is not the density ÷ 1000. E-5's single-bound justification
|
||
rests on that propagation.
|
||
- **Regime B extended to any key in E-4.** See E-4.
|
||
- **A surviving mutation.** The bound must be demonstrated to catch a
|
||
deliberately introduced regression. A comparison that no longer notices is
|
||
worse than the 30 known failures were, because it is silent.
|
||
|
||
## 6. What this document does not say
|
||
|
||
It says nothing about whether a member is structurally adequate, and nothing
|
||
about manufacturing tolerance. Passing acceptance means *this implementation
|
||
reproduces the reference*, not *this part is fit for use*. `PRECISION.md` §7
|
||
holds the list of what the compiler does not do, and it governs.
|
||
|
||
## 7. Correction to HANDOFF.md §7
|
||
|
||
The per-profile breakdown recorded there — Three-Fin 9, Y 7, A Frame 5,
|
||
Rectangle 5, T 1, Four-Fin 1 — sums to 28 against a stated total of 30.
|
||
Measured, the distribution is **Three-Fin 10, Y 7, A Frame 6, Rectangle 5, T 1,
|
||
Four-Fin 1 = 30**. Three-Fin and A Frame were each undercounted by one.
|
||
|
||
**Applied 2026-09-13.** `HANDOFF.md` §7 now carries the measured figures. The
|
||
correction sat here, and in F-034's resolution, for three weeks while the wrong
|
||
numbers stayed in the document a successor reads first — which is the argument
|
||
against leaving a correction notice parked in a second document. It is kept as
|
||
history rather than deleted, because F-034's resolution cites it.
|