diff --git a/docs/research/2026-08-07-s6-perfectclip-containment-contract.md b/docs/research/2026-08-07-s6-perfectclip-containment-contract.md new file mode 100644 index 00000000..c928ef45 --- /dev/null +++ b/docs/research/2026-08-07-s6-perfectclip-containment-contract.md @@ -0,0 +1,66 @@ +# S6 contract (Campaign S) — contain the undecodable PerfectClip TOI tails (AP-83 / AP-91) + +**Date:** 2026-08-07. **Implementer:** one Sonnet agent, after S4b lands. +**Review:** one Opus pass (small slice). **No visual gate** — fully automated. + +## What this is, and is not + +AP-83 and AP-91 record that the PerfectClip time-of-impact tails in +`CylCollideWithPoint` and `SphereCollideWithPoint`/`FindSphereTimeOfCollision` +(TransitionTypes.cs) were decoded via ACE because the retail x87 sequences do +not decompile. **There is no retail text to port — this slice does NOT "fix" +them.** The deliverable is proof about reachability plus a loud guard, so the +rows become auditable instead of aspirational (the AP-22 resolution shape). + +## Premise correction, pinned at scoping — the rows' "no mover sets +PerfectClip" is FALSE as stated + +`PhysicsCameraCollisionProbe.cs:69` sets `ObjectInfoState.PerfectClip` on the +CAMERA mover (faithful to retail's camera flags). So containment must be +proven as: **the camera's resolve can never reach the Cyl/Sphere PerfectClip +TOI tails.** Candidate arguments to verify (do not assume any): +1. The viewer exemption block in `FindObjCollisions`/`CollisionExemption` + (viewer-vs-creature skip, `CollisionExemption.cs:83-85` region) — does it + skip ALL shadow objects for a viewer mover, or only creatures? A static + prop with CylSpheres in the camera's sweep would reach the tail if not. +2. Whether the camera resolve enumerates shadow objects at all (retail's + `update_viewer` sweep may be environment-only — check our port's call + shape at the camera probe's ResolveWithTransition arguments). +If BOTH arguments fail — the camera genuinely can reach a Cyl/Sphere TOI +tail — that is a FINDING, not a failure: the ACE-derived math is then LIVE +production code for the camera, and the rows get rewritten to say so with +the camera named as the reachable population (severity: camera-feel only). + +## Deliverables + +1. **Reachability proof or refutation**, written into a short doc: for each + of the two tails, the exact call chain from every PerfectClip-setting + mover (grep-proof of the full setter population first — today it is the + camera probe alone, verify), and where each chain is cut (file:line), or + not. +2. **The loud guard:** at the head of each TOI tail, a debug-only assertion + (or diagnostics counter + one-shot log, matching house style for + invariants) that fires if the tail executes with a mover whose reachability + was proven impossible — so a future flag change cannot silently start + executing ACE-derived math nobody re-verified. If the camera IS reachable, + the guard instead records the tail as camera-live (counter, not assert). +3. **Tests:** one per tail driving the production resolve with a + PerfectClip mover against a Cyl/Sphere-shaped shadow entity, asserting + whichever reachability the proof established (reached → the guard counter + increments and the ACE-derived result is pinned as a golden; unreached → + the exemption cuts it and the guard stays silent). Sabotage: disable the + exemption that cuts the chain and watch the reachability flip. +4. Register rewrite text for AP-83/AP-91 handed to the session lead + (rows stay ACTIVE either way — the math remains ACE-derived — but their + population claim becomes measured). + +## Scope — OUT + +Any change to the TOI math itself. The camera's flag set (retail-faithful). +Register/ISSUES edits (session lead). + +## Acceptance + +Scoped build/test green (Core + Core.Tests; clean-room for the verdict run); +sabotage reported verbatim; nothing committed. Absolute paths, no subagents, +contradictions → STOP.