# 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-08-22, closing F-034. --- ## 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.