Tier 3 matched a part to its hardpoint by trailing index, so `e105_brg`
compared "01" == "" against GN_Bridge_01 and fell through silently. The runtime
capture is what exposed it: the game draws the bridge and places it at
[0, 70, -1850] rel e105_bdy_01, and assemble_ship emitted nothing there.
With no index to match on, take the lowest-numbered frame of the category.
Diffing assemble_ship part counts across every container: 34 (stage, ship)
entries gain parts — e102 +2 (bridge and engine), e104 +1, e105 +1, Stages
02-29. ship_audit is unchanged, so nothing regressed, and the capture now agrees
to dT 0.03 / dR 0.000.
Also fixes the diff itself: correlate_frames compared static against a rotation
sampled from the first block, which can belong to another INSTANCE of the class.
Scoped to the position-agreeing cluster, e105_eng_01 goes 1.711 -> 0.000 and
both e106 nacelles to 0.000. The one remaining rotation delta (e106_wep_02_01,
0.134) is a turret whose rotation varies by 0.182 between blocks that agree on
its position — the runtime disagrees with itself more than with the assembler.
The new rotVar column makes that distinction visible.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A capture at controlled range (ship_capture_close.sh: lock a capital ship, close
on it, F10 per range band) finally draws capital-ship hulls at full detail. Two
correctness fixes were needed before the numbers meant anything:
* one F10 log is ~14 frames with no delimiter, and WV_ref^-1 . WV_p only cancels
the camera within one frame — segment_frames splits on vertex-buffer
recurrence, and correlate_frames cross-checks the blocks against each other
instead of trusting a single shot;
* aggregate by consensus, not median: a stage holds several ships of one class
sharing vertex buffers, so a block can mix two instances.
Result: f105, e105 and e106 reproduce assemble_ship to <=0.43 units in
translation and 0.000 in rotation for every part that does not move. The e106
rules generalise, and the viewer bug report now points at the viewer. Narrow
leftovers: e105_brg is missing from assemble_ship, e105_eng_01 rotation differs
by 1.711.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Inverting the capture↔part question (invert_capture over one container,
vcount_index over all 166) identifies every large draw in the 2026-07-31
capture: the player's own DeltaSaber (10891 verts), its weapon packs, the
backdrop and particles. Of f101/e105/e106 only 1-3 of 15-37 resources have a
drawn vcount, each a 44-225-vertex far-LOD/effect piece whose count collides
with dozens of unrelated resources.
So the zero-correlation was not an LOD-list gap, not over-strict position
validation and not a different draw path: the ships were too far away to be
drawn. approach_capture.py flies at a locked capital ship and presses F10 per
range band, stamping each capture with its distance.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Working the BACKLOG item "capital ships assemble wrong in the viewer".
- ship_audit over all 22 stage containers: only ONE outlier ship
(f002_bdy_05, Stage_S03/S27, dist 6540 vs cluster spread 1071), so static
assembly is not grossly broken class-wide. Recurring MULTIKEY joint tracks on
f104/f105/f106/e102 are the standing hypothesis for class-specific error —
e106, the one validated ship, has none.
- new tools/re-capture/ship_capture_session.sh: one blocking session that boots
Stage 02 and fires N F10 ship-captures with screenshots. Boot to in-flight was
24 s; 3 of 5 presses produced logs (2964/3111/3668 draws).
- NEGATIVE, unexplained: correlate_capture matched ZERO parts for f101/f105/
f106/e105. Documented with the collected facts and the next step (invert the
match: largest capture vcounts -> which decoded part has that count).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>