docs: park the ULP residue as AUDIT C10; strip the diagnostic scaffolding

Jahni's call to pin it and move on, and the right one -- six builds spent and the
information stopped being worth the cost.

The final run closed it as far as it can be: SDFs identical everywhere (counted
unconditionally, 0 differ), yet two character-identical carve implementations in
the SAME translation unit fed a provably identical input differ by 1 ULP on
126/5000. That is only possible if they compile to different instruction
sequences, which /fp:fast permits based on surrounding context with no single
isolable axis. Hypothesis 3 was right about the mechanism and wrong about every
clean variable proposed for it, which is why four well-designed isolation tests
came back negative.

AUDIT C10 records the observation, what is proven (SDF bit-exact 126/126, zero
isosurface crossings), the five refuted hypotheses in a table so nobody repeats
them at a build each, why the settling experiment is blocked (shared-PCH / IWYU
debt), and the rule that actually matters: never run both density paths in one
world and never compare them for equality. That is NOT a client-desync risk --
within a binary the field is proven bit-pure and every peer runs the same path --
the cross-platform concern is C9, which stands on its own.

Corrected OPSTACK-PLAN 2.6 and C9: my earlier "/fp:fast across translation units"
explanation was measurably wrong and is removed rather than softened.

MazeEquivalence keeps the permanent value (equivalence with ULP grading,
window-invariance, box-verdict brute force) and drops the verbatim copy,
three-way, bisect, inlining and constness experiments.

Phase 1 closed: Maze decomposes into 7 ops, SDF bit-exact, 0 isosurface
crossings, window-invariant, and 23 of 60 tiles proved uniform where ClassifyTile
proves zero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 15:00:46 +02:00
parent b6ccb1c9f1
commit 34f06dfea7
4 changed files with 193 additions and 559 deletions
+56 -6
View File
@@ -279,12 +279,11 @@ not merely *permitted* to diverge — they are compiled under different rules.
**Two consequences, one benign and one not:**
**Benign — refactors cannot be bit-identical.** The same expression compiled into two translation
units may reassociate differently, worth ~1 ULP. So "the port reproduces the original exactly" is
not an achievable bar for the op-stack work, and `OPSTACK-PLAN §2.6`'s bar (recognisably the same
*place*, judged on a screenshot) was the right call for reasons beyond the ones it gave. The
acceptance criterion is now encoded in `VoxelForge.OpStack.MazeEquivalence`: **hard-fail on any
isosurface crossing, tolerate ULP-scale deltas, warn on anything larger.**
**Benign — refactors are not bit-identical in practice.** See `§C10` for the measured detail: the
Maze port reproduces the original's SDF *bit for bit* but its final density differs by 1-2 ULP on
~2% of samples, with zero isosurface crossings. The acceptance criterion is encoded in
`VoxelForge.OpStack.MazeEquivalence`: **hard-fail on any isosurface crossing, tolerate ULP-scale
deltas, warn on anything larger.**
**Not benign — `ARCHITECTURE §9.1`'s multiplayer model rests on this.** The plan is "replicate the
seed + layout + diff, never the geometry; every peer regenerates identically." That guarantee is
@@ -333,6 +332,57 @@ risk is real. That is one build, and it settles it.
---
### C10 — The op-stack ULP residue: PARKED, with the evidence, 2026-07-27
**Status: accepted and closed by decision (Jahni), not by explanation.** Do not reopen this without
reading the whole entry — five hypotheses have already been measured and refuted, and re-deriving
them costs a build each.
**The observation.** `VoxelForge.OpStack.MazeEquivalence`: the ported Maze operator stack differs
from `GetMazeDensity` on ~2% of samples (454/20000) by 1-2 ULP. Deterministic — same samples, same
delta, same coordinates on every run.
**What is PROVEN by measurement, and is the reason this is benign:**
- **Zero isosurface crossings out of 20000.** Not one triangle would move. The two are
*geometrically identical*.
- **The SDF is reproduced BIT FOR BIT** — 126/126 of the mismatches, and `stack SDF != verbatim SDF`
counted unconditionally came back **0**. So the lattice sweep, the edge hashes, the `{-1,0}³`
node set and `VoxelSDF::Capsule` are all exactly correct. The port has no logic error in the part
that shapes the world.
- The entire difference is born in the final SDF→density conversion, amplified because `Blend - Sdf`
cancels catastrophically at the edge of the blend shell.
**What was tested and REFUTED** (each cost a build; listed so nobody repeats them):
| # | Hypothesis | Refuted by |
|---|---|---|
| 1 | `FVector` float→double→float round-trip in the noise coords | identical result after the change |
| 2 | A transcription slip in the roughness window / carve blend / octaves | a four-stage bisect: residue survives into `corridors + carve ONLY` |
| 3 | `/fp:fast` reassociating across **translation units** | three-way test: generator TU == test TU exactly (0 differ) |
| 4 | Different **inlining context** (virtual call vs straight-line) | `FORCEINLINE` vs `FORCENOINLINE` in one TU: 0 differ |
| 5 | **Compile-time-constant** `Blend` vs runtime member | const and runtime forms bit-identical to each other; both miss the verbatim on the same 126 |
**Where that leaves it.** Two carve implementations, character-identical, in the **same translation
unit**, fed a **provably identical** input, produce outputs differing by 1 ULP on 126 of 5000. For
deterministic code that is only possible if they compile to different instruction sequences — which
is exactly what `/fp:fast` permits, based on surrounding context, with no single isolable axis. So
hypothesis 3 was right about the *mechanism* and wrong about every clean variable proposed for it.
**The one experiment that would settle it** is building this module with
`FPSemantics = FPSemanticsMode.Precise`. **It is blocked**: doing so costs VoxelForge the engine's
shared PCH and exposes ~30 missing includes across seven files (see the note in `VoxelForge.Build.cs`).
Clearing that IWYU debt is worth doing on its own terms; it is not worth doing to chase 1 ULP.
**The operational rule that DOES matter, and is the real takeaway:**
**never run the archetype `switch` and the operator stack in the same world, and never compare their
outputs for equality.** A half-migrated strate would produce a seam. This is **not** a client-desync
risk — within one binary the field is proven bit-pure across threads and query order
(`VoxelForge.Determinism.DensityPurity`) and every peer runs the same path. The genuine
cross-platform concern is `§C9`, which stands independently.
---
### Threading — what's *right*, for the record
Worth stating plainly, because it's the part that's easy to get wrong and this doesn't: