# Handoff — capital-ship placement: static assembly EXACT (2026-07-26)

Branch `feature/ipfb-idxd-parser`, commits `c6ca5ce..ea32e77`. Canary fork
branch `capture-ship-placement`, tip `877163792`.

## Outcome

**Capital ships assemble exactly from the ISO alone — no captures needed.**
Runtime captures served as the oracle that cracked the static encoding and now
remain as verification tooling only.

## The two format discoveries (docs/re/ship-placement-runtime-capture.md)

1. **Node-TRS off-by-one** (`mesh.rs::read_trs9`): an XBG7 scene-graph node's
   joint table holds NINE keyframe channels `[TX TY TZ RY RX RZ SX SY SZ]`
   behind EIGHT pointer slots shifted one track forward — channel k+1 =
   `f64@(ptr[k]+8)`, channel 0 (TX) = `f64@(ptr[0]−0x48)`. The old read never
   saw TX (why hulls stacked on the centreline) and misassigned TY/RY.
2. **Euler order** (`mesh.rs::node_rotation`): `Ry(ch3)·Rx(ch4)·Rz(ch5)`,
   angles direct — pinned by decomposing the captured engine-nacelle rotation
   `Rx(−15°)·Rz(30°)` element-for-element.

## assemble_ship (ship.rs) — fully static, capture-validated

- Every composite-node instance (alias duplicates collapsed), including
  cross-id turret mounts (`rou_e303_wep_01_root` ×2 on e106; e108 places 7).
- Engine cluster rig `e_rou_<id>_eng` mounts at `GN_Engine_01`
  (two mirrored nacelles + centre engine).
- `brg`/`sld` at their exact GN frames (frames were always exact).
- Shared-geometry ±TX twins: the instance whose offset opposes the geometry's
  dominant side draws X-reflected (viewer reverses winding on det<0).
- `exhaust_frames()`: the `GN_Jet`/`GN_SJet` frames — the game renders its
  engine-exhaust FX there; the viewer draws marker cones at them (the engine
  GEOMETRY is recessed in the hull by design; without the FX ships read
  engine-less — that was the "engines inside the hull" report).

## Validation chain (all green)

- `ship::tests::static_assembly_matches_runtime_capture` (SYLPHEED_ISO): static
  == the baked e106 capture, all 8 parts, T<1.0 R<0.02, nacelles ×2, turrets
  ×2, starboard mirror.
- `examples/capture_verify.rs` over the user's 5 multi-angle snapshots
  (43 e106 instances): dominant clusters match static to ~1 unit on every part
  incl. both nacelles. Run:
  `cargo run --release --example capture_verify -- <Stage.xpr> e106 <logs…>`
- Offline audit (`examples/ship_audit.rs`) across all stages: no outliers among
  composite ships; composite-less families (fighter morph sets, turret/prop
  parts) are filtered from the viewer's Ships catalog.
- 81 formats-lib + all disc tests; viewer builds.

## Canary instrumentation (branch `capture-ship-placement`)

F10 → `xenia_ship_capture_NN.log` per press (multi-angle in one run), de-duped
by (vertex-buffer, c0..c2 WVP hash) so every instance of every part is
recorded. Launch:
```
cd xenia-canary/build/bin/Linux/Release
./xenia_canary "<…/Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja).iso>"
```

## Open / next

- Verify remaining capital ships against the existing 5 snapshots (they contain
  every on-screen ship): e105 (its engine block assembles dorsally — the one
  placement to confirm), f105/f106/f101, e102. Same capture_verify invocation
  with the other ship id.
- AA-gun models at `GN_AAGun*` frames need the Vessel recipe binding.
- SJet (maneuvering-vernier) marker orientation is approximate; main aft plumes
  verified.
- `_mov` node animation keys (hull-opening sequences) — rest pose rendered now.
- Viewer GUI verification by the user (exhaust cones, catalog cleanup).
