test: the Maze residue is /fp:fast, not port drift — encode the real bar

The bisect settled it. The difference survives every stage removal down to
"corridors + carve ONLY", which is character-for-character transcribed code, so
it is not in anything the decomposition added.

Cause, read out of the engine rather than assumed (VCToolChain.cs):

    case FPSemanticsMode.Default: // Default is imprecise FP semantics.
    case FPSemanticsMode.Imprecise: Arguments.Add("/fp:fast"); break;

with UBT's own doc: "the compiler is allowed to transform math expressions in
ways that might result in differently rounded results". Identical source in two
translation units may reassociate differently, worth ~1 ULP. It shows up on
exactly the ~2% of samples inside the SDF blend shell, where Blend - Sdf
catastrophically cancels; outside it Carve is exactly 0 or 1 and both agree.

So MazeEquivalence now grades what it can actually assert:
  - hard fail  : any isosurface crossing (geometry moves)
  - info       : differences at ULP scale (the unavoidable floor)
  - warn       : anything larger, which IS port drift, and runs the bisect
A test that warns on every port would get ignored by the port that matters.

Recorded in OPSTACK-PLAN 2.6, and as AUDIT C9 for the part that outlives this
refactor: ARCHITECTURE 9.1's "every peer regenerates identically" holds only
between bit-identical binaries under /fp:fast. Fine for one build on one
platform; a real desync source for a Linux server plus Windows clients both
regenerating authoritative geometry. The FPSemantics::Precise knob exists but
must not be turned speculatively -- it blocks the vectorisation T2.a was chasing,
on the hot loop, for an unmeasured cost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 14:15:43 +02:00
parent 23605d5350
commit af5f2103b3
4 changed files with 184 additions and 8 deletions
+14
View File
@@ -196,6 +196,20 @@ strategically:** if bit-identity were required, the cheap path would be to wrap
as one monolithic op — 8 opaque ops that don't compose, i.e. **the switch with extra steps and zero
gain.** Releasing that constraint is what permits *real* decomposition into the primitives in §2.5.
> **✅ CONFIRMED THE HARD WAY, 2026-07-27 — and it turns out bit-identity was never available anyway.**
> The Maze port reproduced `GetMazeDensity` to within 1 ULP on 2.3% of samples, with **zero
> isosurface crossings**. A four-stage bisect showed the residue surviving into code that is
> character-for-character transcribed, which pointed at the toolchain: the plugin compiles with
> **`/fp:fast`** (UnrealBuildTool's Windows default), which explicitly licenses the compiler to
> reassociate the same expression differently per translation unit. So **no port of this kind can be
> bit-identical, at any level of care.** See `AUDIT-2026-07.md §C9` — which also flags the part that
> matters more than this plan does: the multiplayer model's "every peer regenerates identically"
> holds only between bit-identical binaries.
>
> **The operational bar for every remaining archetype port, encoded in
> `VoxelForge.OpStack.MazeEquivalence`:** hard-fail on any isosurface crossing (that moves geometry);
> tolerate ULP-scale deltas (unavoidable); warn on anything larger (that is real port drift).
**The bar instead:** for each ported archetype, an authored op stack must reproduce the *character* of the
old one — same scale, same navigability, same feel, recognisably the same kind of place. Judged by Jahni
on a screenshot at a fixed seed, not by a diff. Expect and accept a one-time re-tune, exactly as the T2.a