# ADR-015 — Derive the template datum from geometry, never from the reported parametric window - **Status:** Accepted - **Date:** 2026-09-05 - **Amends:** PRD 7.14 (recorded there as a hazard), PRD 11.14 (the measurement) - **Deciders:** orchestrator - **Raised by:** reviewer R-C1, finding N6 — which judged that updating PRD 7.14 alone *might* suffice. The decision to record an ADR was not the reviewer's. - **Evidence:** live measurement on Fusion 2704.1.53 (PRD 11.14) ## Context A miter template is a paper wrap. It is useless unless the fabricator can align it to a known line on the tube — the **datum** (PRD 4, FR-3.1). The datum is an angular origin on a cylindrical or conical face, so the obvious implementation is to take the face's parametric window and measure from its start: `θ = v − vmin`. **That obvious implementation is wrong, and it fails silently.** Measured across nine cylindrical faces at `r = 14.3 mm` on Fusion 2704.1.53 (PRD 11.14): | Source | Reported `v` window | |---|---| | `parametricRange()` on an **untrimmed** cylindrical face | `[0, 2π]` | | `parametricRange()` on a **trimmed** cylindrical face | `[−π, +π]` | | `textureCoordinates` on **the same untrimmed face** | `[−π, +π]` | One face, two APIs, two windows. The window is a per-face, per-API report, not a property of the surface. The underlying parameterization is **stable**: `v = 0` landed on `+X` on all nine faces measured, worst deviation `0.000e+00`. Only the reported *window* moves. So a datum taken as `v − vmin` shifts by `π` — half a wrap, **44.925 mm of arc at `r = 14.3 mm`** — between a trimmed and an untrimmed face of the same tube. This is the failure mode PRD 7 exists to catalogue: the template still prints, still looks correct, still wraps. It is simply clocked half a turn around the tube, and the error is only discovered after the metal is cut. The hazard is not hypothetical bookkeeping. Trimming is not something the add-in controls — it is a consequence of how the *user* modeled the intersection, and PRD 2 fixes that the add-in reads geometry and never creates it. So both cases will occur in normal use, on the same tube, in the same document. ## Decision **The datum is derived from an explicit geometric direction and asserted against PRD 4. No datum, anywhere in the codebase, is derived from `vmin` or `vmax`.** Concretely, for a face with axis `a` and a chosen reference direction `d` in the plane perpendicular to `a`: 1. Take `d` from geometry that exists independently of the parameterization — the intersection direction, an explicit user selection (FR-3.1 "clock to"), or a documented world-axis fallback. 2. Compute the angle of a point as `atan2(P·(a × d), P·d)`, a value that does not depend on what window any API reports. 3. **Assert the handedness convention of PRD 4 in code**, not in a comment. PRD 7.1 records that a mirrored template looks perfect and fits nothing. `parametricRange()` remains fine for what it actually is: a *width*, used to place samples inside the face. Its **endpoints** are never a datum. ## Consequences - Every datum implementation carries a geometric reference direction. There is no code path that reads `vmin` to establish an origin, and its absence is checkable by grep in review. - The datum survives the user trimming, re-cutting or rebuilding a face, because it never depended on how the kernel reported that face's window. - `tests/` must include a face in **both** trimmed and untrimmed form and assert the datum agrees between them. That test is the one that would catch a regression here, and it cannot be written without a fixture pair — PRD 13.2's programmatic corpus. - A cost: the reference direction must be chosen and justified per surface type, which is more work than reading `vmin`. That is the point. ## Alternatives rejected - **Normalize the window first** (shift whatever is reported to a canonical `[0, 2π]`). Rejected: it assumes the two APIs disagree only by a phase offset, which is exactly the unverified assumption that produced the hazard. It also leaves the datum defined in terms of a reported quantity, so the next API that reports a third window reintroduces the bug. - **Always read the window from one chosen API** (`parametricRange()` only). Rejected: the measurement shows that *the same API* reports different windows for trimmed and untrimmed faces of the same tube, so fixing the API does not fix the datum. - **Document the hazard and rely on care.** Rejected. This defect class already survived one review cycle in this repo as PRD 6.0's cone row, and it survived precisely because it was prose that no test reads. A constraint that only lives in prose is not enforced.