fix(mesh): distinct anchor assignment -- no two resources may claim one buffer

Selection was per-resource and greedy, so two resources could take one vertex
buffer while a valid one sat unused. A runtime capture proved that wrong for the
mirrored e106 hull twins: the container holds both halves and the engine draws
each from its own address. Now the first claimant keeps a buffer and later
resources re-anchor past everything already claimed (coverage can never regress;
grouped-pool models untouched).

Against the 46 capture-named Stage_S02 buffers: exact anchors 29 -> 40, unclaimed
12 -> 4. Disc-wide: 5480 resources decoded (unchanged), cross-container
inconsistency 125 -> 46.

The twins' mirror therefore lives in the DATA, not in the placement matrix: the
embedded e106_bdy_02 row and the two assertions encoding the old convention are
updated, each with the reason recorded. Full suite green incl. disc/ISO gates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 03:16:51 +00:00
parent 1815490d01
commit d83bdd3b68
5 changed files with 143 additions and 16 deletions

View File

@@ -842,6 +842,38 @@ fixes the twins but cannot reach blocks the validator still rejects. The pair of
changes is the fix; either alone is a half-measure, which is why neither has been
made yet.
### ✅ Fixed: distinct anchor assignment (2026-08-12)
The selection is no longer per-resource-greedy. After the parallel decode, the
models are walked in container order: the first claimant keeps a buffer, and any
later resource that chose the same one is **re-anchored past every buffer already
claimed**. A resource that finds no free candidate keeps its collided decode, so
coverage can never regress. Grouped-pool models are untouched.
Measured against the 46 capture-named `Stage_S02` buffers, and disc-wide:
| | exact anchors | unclaimed | resources decoded | shared inconsistent |
|---|---|---|---|---|
| greedy, cap 0.28 (before) | 29 | 12 | 5 480 | 125 |
| **distinct, cap 0.28 (now)** | **40** | **4** | 5 480 | **46** |
| distinct, cap 0.42 | 45 | 0 | 6 069 | 62 |
Nothing decodes that did not decode before, cross-container inconsistency drops
by **63 %**, and 11 more of the ship's drawn buffers get exactly the right
resource. The cap stays at its shipped 0.28 — that is a separate change with its
own evidence (section 9), and this one is worth being able to revert alone.
**One convention changed, and it is the point of the fix.** With the twins
sharing a buffer, the reflection had to be synthesised downstream:
`ship::apply_twin_mirrors` flipped one hull, and `correlate` baked an X-flip into
`e106_bdy_02`'s captured matrix (`diag(-1,1,1)`). Now each twin decodes to its
own, already-mirrored buffer, so **the mirror lives in the data** and both
placements are proper rotations. Re-emitting the block from the capture confirms
it independently (`1 0 0 0 1 0 0 0 1 264.04343 …`). The embedded placement row
and the two assertions that encoded the old convention were updated, each with
the reason in place; the full suite including the disc- and ISO-gated ship tests
is green.
Not settled: `e106_brg_01_b_02``e106_brg_01_l` (51 verts). A second 51-vertex
`vbase` exists in the logs but is **not** from this container, and the container
holds three near-identical 51-vertex runs, so the pair has no oracle yet.