# C5a contract — legacy deletion sweep + carried parity tests (pinned 2026-08-05) Pinned at HEAD **`392c1e22`** (branch `claude/acdream-physics-divergence-5aa784`), i.e. AFTER #319 landed. Every symbol, caller census, and line number below was **re-verified against this HEAD by grep/read**, not inherited from the C5 scoping (`2026-08-05-c5-scoping.md`, written at `52175aa1`) — §9 lists every place the scoping's picture moved. Baseline: complete Release suite **11,112 passed / 4 skipped / 0 failed**, measured at `392c1e22` (the #319 commit message records the measurement; re-measure at implementation start, never inherit — process rule (c)). **Scope, stated negatively first:** - **NOT #275.** The steady-state inbound-Position merge (`InboundPhysicsStateController.TryApplyPosition`, the simple overload) and `RuntimeEntityObjectLifetime`'s wire-derived `FullCellId` refresh (the `refreshPosition: acceptedPosition` call, **now at `:1926`** post-#319) are the C5b behaviour change with its own contract. C5a must not modify either file's executable code (one test-file doc-comment correction is the only permitted touch near this surface, §1 D7). - **NOT the probe strip.** All six `ACDREAM_PROBE_*` temporary flags stay (C5c); they are env-gated and inert to everything here. - **NOT AP-131, NOT AD-60's legacy half, NOT AP-145's seam** (except the pre-authorized red branch in §5.1). Those rows stay in the register untouched. **Scope, positively:** the six deletion groups in §1 (~490 production lines), the seven test-caller dispositions in §3, retirement of register rows **AP-1** and **AD-1** in the same commit as the deletions, and the two carried parity tests in §5 (#318 composition; route-2 B2). --- ## 1. Deletion inventory — re-verified at `392c1e22` by symbol Caller censuses below are exhaustive over `src/` (all `*.cs`). Method: for `Resolve`, every `.Resolve(` receiver in `src/` was enumerated and typed — 38 distinct receiver/site classes, **none** a `PhysicsEngine` (see the grep-hygiene note in §3.8: two of them are #319's NEW `ParentAttachmentState.Resolve`, a name collision that did not exist when the scoping ran its census). For the others, direct symbol grep over `src/` and `tests/`. | # | Symbol | Location at HEAD | Production callers | Test callers | ~Lines | |---|---|---|---|---|---| | D1 | `PhysicsEngine.Resolve(Vector3, uint, Vector3, float)` | `src/AcDream.Core/Physics/PhysicsEngine.cs:1863`–`~2200` (body ends before `ResolveWithTransition`'s xmldoc; the live method at `:2223` is a **different member** and stays) | **ZERO** | `PhysicsEngineTests.cs` ×12 (`:41,:48,:66,:88,:111,:150,:186,:211,:391,:434,:446,:460`); `Issue133DungeonTeleportPrefixTests.cs:58` | ~360 | | D2 | `PhysicsEngine.HasCellSurface` | `PhysicsEngine.cs:1767`–`~1789` | only `Resolve` itself (`:1887`) — deletes with D1 | none | ~23 | | D3 | `PhysicsEngine.ResolvePlacement` | `PhysicsEngine.cs:2748`–`~2815` | **ZERO** (sole non-test mention is the already-recorded retirement comment at `HeadlessSessionWorldProjection.cs:794`) | `InitialPlacementOverlapTests.cs:42`; `TransitionScratchDifferentialTests.cs:185,:194,:208,:217` | ~70 | | D4 | `PlayerMovementController.SetPosition` (both overloads) | `src/AcDream.Runtime/Gameplay/PlayerMovementController.cs:1746,:1760` | **ZERO** — every `.SetPosition(` in `src/` outside `PhysicsEngine.cs` is `WorldEntity.SetPosition` (receivers `entity.`/`child.`) or Core `PhysicsEngine.SetPosition` via `_physics.Engine.` from `RuntimeSetPositionState` (`:2028,:3125,:4789`), the canonical path | 19 test files, ~80 sites (44 in `PlayerMovementControllerTests.cs` alone) — **fixture setup**, not subject (§3.5) | ~30 gross; ~15 net after the retained seed (§3.5) | | D5 | `PlayerMovementController.CommitPreparedPosition` | `PlayerMovementController.cs:1789` | **ZERO** — production replacement is `ArmConstraintLeashAtCommittedPlacement` (`:1815`), called from `RuntimeLocalPlayerPhysicsPublicationState.cs:774`; `PreparePositionForCommit` (`:1776`) remains production via `RuntimeLocalPlayerPhysicsPublicationState.cs:219` | `PlayerMovementPlacementTransactionTests.cs:42`; `PlayerMovementControllerTests.cs:1158`; `RuntimeLocalPlayerPhysicsPublicationStateTests.cs:3007` | ~25 | | D6 | `RuntimeSetPositionState.BeginAcceptedPlacement` / `BeginAuthoredPlacement` | `src/AcDream.Runtime/Physics/RuntimeSetPositionState.cs:1321,:1333` | **ZERO** — pure pass-throughs to `BeginAcceptedPlacementCore`; production reaches the core via `Apply` (`:1304`) and the authored sequence | **39 sites across 9 Runtime test files** (scoping said ~40/10; re-censused) | **0 — KEEP as documented test seam** (§3.7) | | D7 | Doc hygiene | stale `BlipPosition`/`PlayerMovementController.SetPosition` doc refs at `src/AcDream.Core/Physics/Motion/ConstraintManager.cs:25` (note: the scoping's path lacked `Motion/`) and `src/AcDream.Core/Physics/PhysicsBody.cs:442`; the stale `TryApplyPickup (:1116)` citation in `RuntimeAcceptedPositionDriveControllerTests.cs` (~`:221` region; the method lives in `RuntimeEntityObjectLifetime`, currently ~`:1258+`) — **cite by symbol, not line**, in the correction | — | — | ~20 comment lines | Net production deletion: **~490 lines** (the scoping's ~540 minus D6's kept ~25 and D4's retained seed). All deletions are compile-loud. **Confirmed unchanged from the scoping's §1c (NOT deletable, re-spot-checked):** `ILocalPlayerTeleportPlacement`/`LocalPlayerTeleportPlacement.Place` (live post-commit presentation suffix, `LocalPlayerTeleportController.cs:243` still calls `entity.SetPosition(controller.Position)` inside it); `PlayerMovementController.SetPositionCore` (`:1845`, production via `PreparePositionForCommit`); the route-4 leftovers; AP-135's bookkeeping; `RuntimeLiveEntitySessionController.cs:141`'s pre-flip path (its file WAS touched by #319, but the C4/C5-revisit comment's unblock condition is still unmet). --- ## 2. The survivor hazard — TWO production members inside the deletion region, not one The scoping named one. Re-verification at HEAD finds **two**: 1. **`IsSpawnCellReady` (`PhysicsEngine.cs:1807`)** — production callers `RuntimeSetPositionState.cs:2169,:4378` and `SessionPlayerComposition.cs:374`. Sits between `HasCellSurface` (delete) and `Resolve` (delete). 2. **`AdjustPosition` (`PhysicsEngine.cs:1813`)** — **the scoping never dispositioned it.** It is production: `PhysicsCameraCollisionProbe.cs:38,:100` (the camera collision probe), plus six-plus test files (`PhysicsEngineAdjustPositionTests`, the camera replay suites, `Issue177StairDescentCameraFloodTests`, ...). It sits between `IsSpawnCellReady` and `Resolve` — dead centre of the physical block. **Pinned survival rule:** the deletion is **member-wise, never region-wise**. Delete exactly the bodies of `HasCellSurface`, `Resolve`, and `ResolvePlacement`; `IsSpawnCellReady` (`:1807`–`:1811`) and `AdjustPosition` (`:1813`–`:1861`) remain byte-identical in executable code. **Xmldoc fallout (same commit):** `IsSpawnCellReady`'s summary contains `` (in the `:1791`–`:1806` block) and `HasCellSurface`'s summary names "the Resolve safety net"; the second dies with its method, the first must be rewritten (the "loud outdoor-demote safety net" sentence describes machinery this commit deletes — rewrite the paragraph to describe the canonical `SetPosition` reality, do not leave a cref to a deleted symbol). Sweep `PhysicsEngine.cs` for any other `cref="Resolve"`/`cref="ResolvePlacement"` after the deletion; the build must be warning-clean on missing crefs. --- ## 3. The seven test-only-caller dispositions — re-verified, each carried forward Framing (from the scoping, still correct): deleting a method whose callers are tests is compile-loud. The silent hazard is the **disposition of the tests afterward** — deleting a test that pinned MOVED behaviour loses the pin with a green build. Each case below is a binding disposition; any deviation must be argued in the commit message. ### 3.1 `PhysicsEngine.Resolve` unit tests — behaviour GONE → DELETE, after a one-pass audit `PhysicsEngineTests.cs` (565 lines, 12 `engine.Resolve(` sites). The outdoor-demote / legacy floor-snap / terrain-lift semantics die with the method; canonical replacements have their own suites (`PhysicsSetPositionTests`, `RuntimeSetPositionStateTests`). **Audit before deleting:** any individual assertion that actually pins canonical-owned behaviour — specifically `AdjustPosition` semantics, which SURVIVE — is re-pointed at `AdjustPosition` directly (note `PhysicsEngineAdjustPositionTests.cs` already exists; a re-point may land there). The audit's outcome (N assertions re-pointed, M deleted) goes in the commit message. ### 3.2 `Issue133DungeonTeleportPrefixTests` — behaviour MOVED → RE-POINT (named-bug regression pin) Verified at HEAD: the defect mechanism this test pins — the `lbPrefix` resident-landblock scan that re-stamped a validated dungeon claim with a neighbour's prefix — lives **entirely inside `Resolve`'s body** (`PhysicsEngine.cs:1928,:1937,:1984-1995,:2193`). The canonical `PhysicsSetPosition` path has **no lbPrefix scan** — the defect class cannot recur there by construction. That is precisely why the pin must be **re-pointed, not deleted**: #133 is a closed named bug, and the invariant (a validated dungeon claim's landblock prefix is authoritative; a committed cell never gets re-stamped from a neighbouring resident block) must stay assertable against whatever path owns placement now. **Re-point spec:** drive a teleport-classified canonical placement (`RuntimeSetPositionState`, or Core `PhysicsEngine.SetPosition` if the fixture cost is lower) with the test's exact geometry — dungeon claim `0x00070143`, dungeon block world-offset so its local Y is negative, resident neighbour block at origin containing the same XY — and assert the committed cell keeps the `0x0007` prefix. Alternative accepted by this contract: PROVE an existing canonical test already pins prefix authority for an off-bounds dungeon claim and record the proof (test name + assertion) in the deleting commit. Silent deletion is a contract violation. ### 3.3 `InitialPlacementOverlapTests` — behaviour MOVED → VERIFY-THEN-DELETE The ring-search half of enter-world placement is ported inside canonical `SetPosition` (`TransitionTypes.cs:1596` `FindPlacementPosition`, retail 0x0050C170; `PhysicsSetPositionTests.cs` header cites it and has placement-probe scenarios, e.g. the `placementPasses >= 2` retry arm at `:1152-1194`). **The audit criterion:** confirm `PhysicsSetPositionTests` covers the **other-entity-occupancy** ring search this test pins (a relogging player overlapping a registered creature sphere searches outward to the nearest clear ring) — occupancy-driven, not merely BSP-failure-driven. If covered: delete, citing the covering test by name. If not: re-point this test's scenario through canonical `SetPosition` with a placement class that reaches `FindPlacementPosition` (~50–100 lines), then delete the `ResolvePlacement` call. ### 3.4 `TransitionScratchDifferentialTests` — differential arm → RE-POINT OR DROP EXPLICITLY Verified at HEAD: the spec-based sequence arms (`ResolveSpec.Resolve` at `:618`) call `ResolveWithTransition` — **untouched by this slice**. Only `ReusedScratch_MatchesFreshPlacementSearch` (`:180`–`:227`, four `ResolvePlacement` sites) is affected. It is a Slice-I zero-alloc scratch-reuse differential over the placement search (including the hostile-identity leak check). **Disposition:** re-point the arm at the canonical entry that reaches `FindPlacementPos` (Core `SetPosition` with the appropriate placement class), preserving both the bitwise fresh-vs-reused comparison and the second-identity leak check. If re-pointing is disproportionate, the arm may be dropped ONLY with an explicit commit-message decision naming what coverage the I-slice differential loses — never silently. ### 3.5 `PlayerMovementController.SetPosition` fixture usage — NEITHER gone nor moved → RETAINED SEED + mechanical re-point Census at HEAD: **19 test files** reference `PlayerMovementController` and call `.SetPosition(`; ~80 sites total; 44 in `PlayerMovementControllerTests.cs`, 8 in `LocalPlayerTeleportControllerTests.cs`, 5 in `HeadlessSessionHostTests.cs`, the rest 1–4 each. (Per-site care: a file can reference the controller and still call `WorldEntity.SetPosition` — type each site during the re-point, don't regex-replace blind.) **Pinned design (the scoping's "cheaper and honest" option, adopted):** keep **ONE** internal, explicitly-named test seed on the controller — rename the 3-arg overload to `SeedPlacementForTest(Vector3 pos, uint cellId, Vector3 cellLocal)` (internal; xmldoc states it exists ONLY to seed fixtures and that production placement flows through `PreparePositionForCommit` → `ArmConstraintLeashAtCommittedPlacement`), delete the 2-arg overload, and mechanically re-point all ~80 sites. Semantics are reproduced by construction: the seed calls the SAME `SetPositionCore` (which stays production), so the grounded, zero-velocity start (the AD-61 force-seed) that dozens of movement tests assume is unchanged. This is the one production-file signature change in the slice; its body is untouched. ### 3.6 `CommitPreparedPosition` tests — behaviour MOVED → RE-POINT at the arm/commit replacement Three sites, each audited individually: - `PlayerMovementPlacementTransactionTests.cs:42` (100-line file): the prepared-position transaction assertions run against the production pair (`PreparePositionForCommit` + `ArmConstraintLeashAtCommittedPlacement`) — rewrite the test against that pair, or delete it if `RuntimeLocalPlayerPhysicsPublicationStateTests` provably covers the same transaction shape (cite which test). - `PlayerMovementControllerTests.cs:1158` and `RuntimeLocalPlayerPhysicsPublicationStateTests.cs:3007` both assert `Throws` on the uncommitted/displaced state. Audit whether the replacement arm carries an equivalent guard; if yes, re-point the throw assertion at it; if the guard died with the method, delete the assertion WITH a commit-message note (guard semantics gone, not overlooked). ### 3.7 `BeginAcceptedPlacement`/`BeginAuthoredPlacement` — NEITHER → KEEP AS DOCUMENTED SEAM 39 sites across 9 Runtime test files at HEAD. The wrappers are pure pass-throughs to the production core (`BeginAcceptedPlacementCore`); deleting them buys zero behaviour and costs broad mechanical churn across the Runtime suite. **Disposition: keep, with an xmldoc sentence on each wrapper naming it a test seam** (so a future sweep does not re-litigate this). This is a recorded deliberate exception to "delete every superseded legacy path": the wrappers are not a legacy PATH — the core they call IS the canonical path. ### 3.8 Landmines and grep hygiene - **The #316-preserving pair** (`LiveEntityNetworkOnPositionCollapseMatrixTests.cs:131,:180`) pins a defect **preserved verbatim**. C5a must not touch it; it inverts only with #316's measured fix (C5-gate session / later). - **#319 introduced `ParentAttachmentState.Resolve`** (`ParentAttachmentState.cs:432`), called at `EquippedChildRenderController.cs:920` and `RuntimeLiveEntitySessionController.cs:390`. A mechanical grep for `.Resolve(` now hits relation resolution — neither site is `PhysicsEngine`. Any "prove zero callers" re-run during implementation must type receivers, not count matches. - The affected-file overlap between #319 and this slice is **empty**: #319 touched `EquippedChildRenderController`, `LiveEntityHydrationController`, `LiveEntityPresentationController`, `ParentAttachmentState`, `RuntimeEntityObjectLifetime`, `RuntimeLiveEntitySessionController` — none contains a C5a deletion target. Verified. --- ## 4. Register retirements — AP-1 and AD-1, with the code evidence; four rows explicitly untouchable A row retires because the code proves its condition met. Both retirements ride **in the same commit as the D1–D5 deletions** (register rule 1). ### AP-1 — RETIRE. Evidence at `392c1e22`: Row text: "Production zero-delta routes deliberately remain on the legacy resolver until 4B2..." — **false at HEAD**: 1. The "legacy resolver" is `PhysicsEngine.Resolve`/`ResolvePlacement`. The exhaustive receiver census (§1) shows **zero** `PhysicsEngine.Resolve` or `.ResolvePlacement` call sites in `src/`. 2. Every production placement writer reaches Core `PhysicsEngine.SetPosition` **only** through `RuntimeSetPositionState` (`:2028,:3125,:4789` — the only three `_physics.Engine.SetPosition` sites in `src/`). 3. The row's named prerequisites (authored mover, rebucketing, prefix-quiescence, body publication, atomic route cutover) landed across C0–C4; the local controller's body adoption landed at C3c. 4. Deleting D1–D5 makes the retirement **structural**: the resolver-shaped entry points cease to exist, so no future caller can re-open the row's condition. The narrower survivors (#276 settle-cell discard, AD-61 force-seed, AD-62 non-commit outcomes) are separately filed rows/issues and do not block AP-1's own condition — deleting AP-1 does not orphan them. ### AD-1 — RETIRE. Evidence at `392c1e22`: Row text: "Production authoritative placement still routes through the legacy recoverable outdoor demote and outdoor-restore `max(terrainZ, z)` lift" — **false at HEAD**: that code is `Resolve`'s body (demote at `PhysicsEngine.cs:~1890-1910`, the outdoor `max(terrain, z)` lift inside the snap block ~`:2160-2175`) and `Resolve` has zero production callers. The lost-cell stand-in the row describes is unreachable from production. Deleting D1/D2 removes the divergent mechanism outright. ### Must NOT be touched (each blocked on work outside this slice): - **AP-131** — retires only with **#275** (C5b): the legacy `TryApplyPosition` unconditional `installPlacementFrame: true, clearParent: true` is still the ONLY steady-state production Position merge at HEAD. - **AD-60's legacy half** — same gate (#275): the `RefreshSnapshot(..., refreshPosition: acceptedPosition)` site — **`:1926` at HEAD** (the scoping's `:1918` and the register's `:1338` are both stale; cite the symbol) — still derives `FullCellId` from bare wire acceptance. - **AP-145** — retires with **#318's fix**, never with its test. The §5.1 composition test makes the asymmetry falsifiable; only the pre-authorized red branch may touch the seam, and then AP-145 retires in THAT commit. - **AD-61 / AD-62 / AP-135 / AP-141–146** — all carry their own retirement conditions; none is met by anything in this slice. (AP-146 and the AP-132 amendment are #319's, three days old — do not disturb.) --- ## 5. The two carried parity tests Both are test-only against HEAD's production code, land BEFORE the deletion commit (they are independent of it and de-risk the slice's review), and both follow process rule (e): sabotage-verified, with the WHICH-assertion-fails check, both directions for dual-layer assertions. ### 5.1 #318 composition test (~150–300 lines, App.Tests) Drive a real portal arrival through the canonical drive controller + the **REAL** `RuntimePlacementPresentationSink` + the **REAL** `PhysicsEngine` (fixture patterns exist: `RuntimePlacementPresentationSinkTests.cs`, `RuntimeFirstEntryHostIntegrationTests.cs`). The discriminating assertion: > **`PhysicsEngine.ShadowObjects` (`PhysicsEngine.cs:147`) holds a row at the > destination cell/position** — NEVER merely `LocalPlayerShadowState`'s dedup > cache. AP-145's bypass (`RuntimePlacementPresentationSink.cs:243` > `_localPlayerShadow.Set(...)` skipping `LocalPlayerShadowSynchronizer.SyncPose`'s > publish) both skips the publish AND pre-seeds `SyncPose`'s dedup — a > cache-only assertion is satisfied by the bug. Plus the T8 write-ordering assertion from route 3 §8. Sabotage: perturb `TryPublishPlace` to the cache-only shape and confirm the `ShadowObjects` assertion (not an incidental one) fails; separately confirm a cache-only assertion would pass under the same sabotage — proving the discriminator discriminates. **Pre-authorized red branch:** this test may legitimately FAIL at HEAD — the composition drives placement with no subsequent movement tick, which is exactly the window AP-145 says is unpublished. If red: **C5a's deletion work does not absorb the fix.** The seam fix (routing the placement's shadow update through the real publish) is a production behaviour change on a narrow, low-frequency path; it lands as its **own reviewed commit** together with the now-green test, retires **AP-145**, and closes **#318** — and the composition test itself is its designed gate (the C4 handoff explicitly ruled the connected route out as #318 coverage). If green: land as-is; #318 closes; AP-145's row is then re-argued (its "why not observed" column may become its retirement argument) — but only with the green evidence cited. ### 5.2 Route-2 B2 parity test (~100–200 lines, App.Tests) The campaign plan's recorded acceptance gap (plan §C4 route 2, recorded unmet since 2026-08-03): an App-layer test driving an **accepted ForcePosition end to end** through `RuntimePlacementPresentationSink` / `TryApplyRuntimePlacementPlace` and asserting **the render entity's position/cell came from the committed placement receipt** — closing the "canonical body moves, render entity stays put" silent seam. Expected green at HEAD (route 2 landed; the seam is merely uncovered). If red, the same stop-and-report protocol as 5.1: a red parity test is a found defect, not a test problem; it gets its own investigation before any deletion lands. Sabotage: sever the receipt→render write and confirm the position/cell assertion is the one that fails. --- ## 6. What must REMAIN true — the slice's invariants 1. **Zero production behaviour change.** The production diff consists of: member deletions with zero callers (D1–D5), comment/xmldoc edits (D7, §2), and exactly one signature change with an untouched body (§3.5's seed rename). No executable production statement is added or modified — **except** in the pre-authorized 5.1 red-branch commit, which is its own reviewed landing with its own register action. 2. **The two survivors survive.** `IsSpawnCellReady` and `AdjustPosition` keep their exact executable bodies and all production callers (`RuntimeSetPositionState.cs:2169,:4378`; `SessionPlayerComposition.cs:374`; `PhysicsCameraCollisionProbe.cs:38,:100`). 3. **Every deleted symbol's absence is proven** by the compiler (all deletions are compile-loud) AND every test caller has an explicit §3 disposition executed in the same commit — no test deleted whose pinned behaviour moved without its re-point landing alongside. 4. **AP-1 and AD-1 retire in the SAME commit as the D1–D5 deletions** — never before (the code proof is the deletion), never after (register rule 1). 5. **The DO-NOT-TOUCH set holds:** AP-131, AD-60, AP-145 (modulo 5.1 red branch), AD-61/62, AP-135, AP-141–146; the #275 surface files' executable code; the six probe flags; the #316-preserving test pair. 6. **No skips.** The suite ends at 0 failed with the same 4 skips as baseline — a new skip is a contract violation (process rule (d)). 7. **Counts are measured and reconciled.** The final suite total will move (deleted legacy tests down, re-points and two parity tests up); the commit message reconciles the net against baseline 11,112 explicitly (N deleted, M added, expected total), never hand-waves it. --- ## 7. Gates - **Complete Release suite** (`dotnet test AcDream.slnx -c Release -m:1` with `ACDREAM_PAK_PATH` set), baseline **11,112 passed / 4 skipped / 0 failed** at `392c1e22` — re-measured at slice start AND at each commit. Known flakes, never conflated (they have been conflated twice): **#302** (`PortalProjectionTests.ClipToRegion_FrameOwnedStore_…`, GC-allocation, App.Tests — the `WarmedSteadyContactRefreshDoesNotAllocate` look-alike is this class) and **#308** (`NakEmissionTests.LossSoak_…`, wall-clock, Core.Net.Tests, full-suite load only). - **NO connected gate for C5a — argued, not assumed.** Process rule (g): a gate must be able to see the defect it gates. C5a's reachable defect classes are (i) a compile break — seen by the build; (ii) silent coverage loss — seen only by §3's dispositions and the review, invisible to any live session; (iii) a behavioural regression — **structurally excluded** by invariant 1: the production binary's reachable code is byte-equivalent, so a connected session would exercise identical behaviour and measure nothing. Precedents: route 5 recorded "no live gate can exist" rather than inventing one; route 6 was a zero-production-line closure. The 5.1 red-branch commit, if taken, ALSO needs no connected gate: #318's evidence channel is the composition test **by design** — the C4 handoff explicitly refused to score the connected route against it. - **The review IS the coverage gate.** One dual review over the combined slice diff (deletions + dispositions + parity tests), reviewers on Opus per the standing audit rule, with §3's table as the review checklist: for each of the seven cases, the reviewer confirms the disposition was executed as pinned or the deviation argued. --- ## 8. Size, commit plan, and the split call Calibration: campaign landings ran ~127 (route 7) to ~418 (route 3) to ~500 (4b-2) production lines each under full discipline. | Piece | Production lines | Test lines | Risk | |---|---|---|---| | D1–D5+D7 deletions + §2 xmldoc | ~490 deleted, ~0 added | ~1,500–2,000 deleted/re-pointed across ~25 files | Low — compile-loud; the §3 dispositions are the judgment work | | §5.1 #318 composition test | 0 (green) / ~10–40 (red branch, own commit) | ~150–300 | Low; red branch is a decision point, pre-planned | | §5.2 route-2 B2 test | 0 | ~100–200 | Low | **Call: C5a HOLDS as one slice, in two (possibly three) ordered commits under this single contract:** 1. **Commit 1 — the two parity tests** (test-only). Lands first: independent of the deletions, de-risks review, and settles 5.1's green/red question before the sweep. If 5.1 is red, its fix is **commit 1b** (own review round, retires AP-145, closes #318) before proceeding. 2. **Commit 2 — the deletion sweep**: D1–D5, D7, §2 xmldoc, all §3 dispositions, AP-1 + AD-1 row deletions. One diff, reviewable as one unit. The ~490-line figure is at the top of the campaign's calibration band, but a deletion of caller-free code is a different risk class from route 3's ~418 changed lines — the compiler proves most of it. What justifies keeping it whole rather than splitting D1/D2/D3 (Core) from D4/D5 (Runtime): AP-1's retirement evidence spans BOTH groups ("the last resolver-shaped entry points" includes D4/D5), so splitting would either retire AP-1 on a half-proof or leave the register straddling two commits — both worse than one larger reviewable deletion. Do NOT fold in: #276's remainder, #317's audit, any probe change (including the gate-4 `cause=` label improvement — C5c), or any #275-adjacent edit. --- ## 9. What moved between the scoping (`09911821`, at `52175aa1`) and this contract (`392c1e22`) 1. **`AdjustPosition` is a second production survivor inside the deletion region** (`PhysicsCameraCollisionProbe.cs:38,:100`) — the scoping's hazard note named only `IsSpawnCellReady`. A region-wise delete would have taken the camera collision probe's cell resolver with it. §2 pins member-wise deletion. 2. **#319 created a `.Resolve(` name collision**: `ParentAttachmentState.Resolve` (`:432`), called from two files. The scoping's census predates it. Callers must be typed, not counted (§3.8). 3. **AD-60's legacy-half site moved to `RuntimeEntityObjectLifetime.cs:1926`** (scoping said `:1918`; the register row still says `:1338`). C5a doesn't touch it, but C5b's contract must cite by symbol. 4. **Begin* wrapper census: 39 sites / 9 files** (scoping: ~40 / 10). Immaterial to the disposition. 5. **The scoping's D7 path `ConstraintManager.cs` is actually `Motion/ConstraintManager.cs`** (`src/AcDream.Core/Physics/Motion/`). 6. **Everything else in the scoping's §1a/§1c/§2/§3 holds exactly at `392c1e22`**: zero production callers re-proven for all six groups; #319 added no caller to any deletable symbol; the #319-touched file set is disjoint from every deletion target; the seven dispositions carry forward unchanged in substance. 7. **New since the scoping, absorbed here:** gate 4 closed 2026-08-05 as a probe-label artifact (`af828a8a`) — the cell-less falsification is no longer C5-gate-session work; and route 7's gate criterion was corrected to the positive child-cell-equals-parent assertion (`2687d893`), whose still-owed connected run belongs to the C4/#319 ledger, not to C5a.