Verified by symbol at HEAD 52175aa1, behind two exhaustive caller censuses
(legacy placement writers; the probe family).
DELETION INVENTORY: 6 deletable symbol groups (~540 production lines), 2 more
deletable only via #275, and 5 that the plan or handoff names as deletable but
are NOT. Deletable now, all with zero production callers: PhysicsEngine.Resolve
(~360 lines — this IS AD-1's legacy demote/lift body) plus its private
HasCellSurface; PhysicsEngine.ResolvePlacement; PlayerMovementController
.SetPosition (both overloads); CommitPreparedPosition; the BeginAcceptedPlacement
/BeginAuthoredPlacement test wrappers. Hazard recorded: production
IsSpawnCellReady sits physically inside the Resolve block.
THE PLAN'S FRAMING IS WRONG FOR HALF THE ROWS. AP-1 and AD-1 are provably
retirable in the deletion commit — both rows' "production still routes through
the legacy resolver" sentences are already false at HEAD. But AP-131 and
AD-60's legacy half are blocked on #275, which is a BEHAVIOUR CHANGE
(classify-then-merge on every steady-state Position, retail Gate A, wire-cell
withhold across a 45+ site residency-predicate blast radius) — not a deletion.
"C5 deletes the paths and the rows retire" holds for two rows and not the
other two.
SEVEN TEST-ONLY-CALLER CASES, each with a disposition, because this is where a
deletion slice silently removes coverage: Resolve's unit tests (behaviour gone
— delete); Issue133DungeonTeleportPrefixTests (behaviour MOVED — re-point, it
is a named-bug regression pin); InitialPlacementOverlapTests and
TransitionScratchDifferentialTests (verify-then-delete / re-point the
differential arm); ~19 files using PlayerMovementController.SetPosition as
fixture setup (mechanical re-point); CommitPreparedPosition's tests (re-point
at the leash-arm replacement); the Begin* wrappers' ~40 sites (keep as a seam).
Also flagged: the #316-preserving test pins a defect verbatim and inverts by
design once measured.
THE CELL-LESS TRIGGER, ESTABLISHED BY READING rather than deferred to a live
session: pickup-then-drop. TryApplyPickup leaves an ACTIVE cell-0 record, and
ACE's drop sends that guid a bare UpdatePosition (Player_Inventory.cs:1443)
with no client-side delete. What remains unknown is only whether a CreateObject
from NotifyPlayers (Landblock.cs:900) precedes it on the ordered stream, which
depends on when ACE populates the fresh item's known-players set — a two-minute
probe run settles it, with route 5's "the gate cannot exist, record that" as
the honest fallback.
SEQUENCING: run the owed gates FIRST as one cheap user session on the current
binary (route-7 thickening, the cell-less falsification, #316's measurement),
then C5a (deletions + #318 + route-2's B2 parity test + retire AP-1/AD-1), then
C5b (#275 + AP-131/AD-60, own contract and dual review), then C5c (closeout
gates after #280 per the plan's own ordering, the ~1,340-line probe strip, the
ledger). The probe strip goes LAST because the owed gates depend on the probes,
with a REMOTE_LANDING carve-out if #316 stays unmeasured.
Seven false or stale plan claims found and listed, including AP-1/AD-1's own
row texts, ILocalPlayerTeleportPlacement being called deletable when it is a
live post-commit suffix, and the 4b "to delete" list being overtaken — the
pre-op ConstrainTo and duplicate constants are already gone and the remainder
is now canonical post-collapse.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
30 KiB
C5 scoping — legacy deletion + closeout gates (2026-08-05)
Scoped at HEAD 52175aa1 (branch claude/acdream-physics-divergence-5aa784,
identical to main — C4 merged and pushed today). Every claim below was
verified by symbol at this HEAD, not inherited from a planning document;
where a planning document turned out wrong, §8 says so explicitly. Inputs:
the C4 closeout handoff (2026-08-05-c4-closeout-handoff.md), the campaign
plan (2026-08-02-placement-cutover.md), register rows AP-1 / AD-1 / AP-131 /
AD-60 / AP-141..145, and two exhaustive caller censuses run against this
worktree (legacy placement writers; the temporary probe family).
One-paragraph verdict: C5 is three different kinds of work wearing one slice name. (1) A deletion sweep that is smaller than the plan implies — most of the big deletions already landed inside C4's routes; what is left is ~500 production lines, all with test-only callers, plus large mechanical test churn. (2) #275, which is NOT a deletion: it is a behaviour change on the steady-state inbound-Position merge (the hottest wire path), and it is the only thing that can retire AP-131 and AD-60's legacy half. (3) The closeout gates + probe strip + ledger. These must not ride in one landing; the split is drawn in §7.
1. The deletion inventory, verified at HEAD by symbol
1a. Deletable now — zero production callers, test callers only
Every entry below was grepped across all of src/; the caller lists are
exhaustive at 52175aa1.
| # | Symbol | Where | Production callers | Test callers | ~Lines |
|---|---|---|---|---|---|
| D1 | PhysicsEngine.Resolve |
src/AcDream.Core/Physics/PhysicsEngine.cs:1863-2222 |
ZERO (the live per-tick method is ResolveWithTransition, a different member) |
tests/AcDream.Core.Tests/Physics/PhysicsEngineTests.cs (12 sites) + Issue133DungeonTeleportPrefixTests.cs:58 |
~360 |
| D2 | PhysicsEngine.HasCellSurface |
PhysicsEngine.cs:1767-1783 |
only Resolve itself (:1887) — deletes with D1 |
none | ~17 |
| D3 | PhysicsEngine.ResolvePlacement |
PhysicsEngine.cs:2748-~2810 |
ZERO (its retirement is already recorded as done in HeadlessSessionWorldProjection.cs:794) |
InitialPlacementOverlapTests.cs:42; TransitionScratchDifferentialTests.cs:185,194,208,217 |
~65 |
| D4 | PlayerMovementController.SetPosition (both overloads) |
src/AcDream.Runtime/Gameplay/PlayerMovementController.cs:1746,1760 |
ZERO (only stale doc-comment mentions at ConstraintManager.cs:25, PhysicsBody.cs:442 — both also still name the long-deleted BlipPosition) |
~19 test files, used as fixture setup, not as subject (see §3) | ~30 |
| D5 | PlayerMovementController.CommitPreparedPosition |
PlayerMovementController.cs:1789 |
ZERO (production replacement is ArmConstraintLeashAtCommittedPlacement:1815, called from RuntimeLocalPlayerPhysicsPublicationState.cs:774) |
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, which production reaches via Apply (:1304) and the authored sequence (:1466) |
~40 call sites across 10 Runtime test files | ~25 |
| D7 | Doc hygiene | tombstone comment LiveEntityNetworkUpdateController.cs:2469-2478; stale BlipPosition refs above; stale TryApplyPickup (:1116) citation in RuntimeAcceptedPositionDriveControllerTests.cs:221 (the method is now at RuntimeEntityObjectLifetime.cs:1258) |
— | — | ~20 |
Deletion hazard inside D1/D2's block: IsSpawnCellReady
(PhysicsEngine.cs:1807) sits physically BETWEEN HasCellSurface and
Resolve and is production (RuntimeSetPositionState.cs:2169,4378;
SessionPlayerComposition.cs:374). A region-wise delete takes it by accident.
Production-line total for 1a: ~540 lines, all compile-loud (see §3 for why that matters).
1b. Deleted only BY #275 — cannot be deleted standalone
These two sites are the code bodies of AP-131 and AD-60's legacy half. They have a live production caller — the steady-state Position merge — so deleting them is not a sweep item; it is the #275 behaviour change (§2).
InboundPhysicsStateController.TryApplyPosition(the simple overload,src/AcDream.Runtime/Entities/InboundPhysicsStateController.cs:610, which hardcodesinstallPlacementFrame: true, clearParent: trueat:662-663). Production path at HEAD:LiveEntityInboundAuthorityGate.cs:161→LiveEntityRuntime.cs:2550→RuntimeEntityObjectLifetime.TryApplyPosition:1781→RuntimeEntityDirectory.cs:654→ this overload. The route-flag-threaded overload (:681) already exists and is what the continuation executor uses (RuntimeInitialCreateContinuationExecutor.cs:1991-1992).RuntimeEntityObjectLifetime.cs:1918—RefreshSnapshot(canonical, snapshot, refreshPosition: acceptedPosition): the wire-acceptance-derivedFullCellIdwrite AD-60 names as "part of the AP-1 divergence this campaign is removing". The executor's equivalent already withholds it (refreshPosition: false, executor:1996).
1c. Named by the plan/handoff as sweep material but NOT deletable — with reasons
This is where the plan is most wrong at HEAD. Five items:
ILocalPlayerTeleportPlacement/LocalPlayerTeleportPlacement.Place(src/AcDream.App/Streaming/LocalPlayerTeleportController.cs:176,207-284). The handoff lists it as a "sweep candidate (now a thin acknowledge seam)". It IS thin, but it is live production: route 3 kept it as the post-commit presentation suffix (target-watcherNotifyTeleported, camera reset, spatial reconcile) and the A10 review fix explicitly decided its redundantWorldEntitypose writes are "kept because they cost nothing". Disposition: no deletion. Optional zero-risk simplification (inline the interface) is not worth review cost; recommend leaving it and striking it from the sweep list.PlayerMovementController.SetPositionCore(:1845-1920) — STILL PRODUCTION viaPreparePositionForCommit(:1782) ←RuntimeLocalPlayerPhysicsPublicationState.cs:219(the first-entry publication candidate build). The AD-61 force-seed (Contact|OnWalkable|Activeat:1860-1863) is still inside it — filed, argued inert (overwritten by the faithful activation commit + settle), and not a C5 retirement target. Note the tension the census surfaced: the route-3 comment atPlayerMovementController.cs:1975-1985repudiates this exact overwrite for the teleport path while first-entry still runs it — that is AD-61's documented state, not new debt.- The route-4 leftovers the 4b plan listed as "4b's to delete" — the plan
text is overtaken. At HEAD: the pre-operation unconditional
ConstrainTois already deleted (tombstone atLiveEntityNetworkUpdateController.cs:2469-2478; the only arming site is the post-operation one at:2853); the duplicate96f/4fconstants are already deleted (zero hits in the file); the!update.IsGroundedearly return (:2622-2627) is no longer a player-arm carve-out — since the OnPosition collapse it is the guid-blind D2 wire-airborne return-0 shape (retailMoveOrTeleport @0x0051636D), i.e. canonical, not legacy; andApplyRemoteContactRouting(:1175-1348) is the canonical five-arm post-collapse routing with exactly one production caller. None of these is C5 deletion material. - AP-135's bookkeeping (
RemoteMotion.CellIdwriters at:1392,:1622;LastServerPos/LastServerPosTimeat:1393-1394,:2895-2896,:786) — deliberately retained per the row's own retirement condition (retires with the free-fall sweep gate, which C5 does not touch). Keep. RuntimeLiveEntitySessionController.cs:141— the content-less headless host's pre-flip directRegisterEntitypath, the one forward-looking "C4/C5 revisit" comment in all ofsrc/. Its stated unblock condition ("once the direct-host conductor drive no longer requires prepared content") is not met at HEAD. Carry, do not delete.
Also checked and confirmed already-deleted (comment references only):
RemoteTeleportController, RemoteTeleportPlacement,
LocalForcePositionTransaction, HeadlessSessionWorldProjection.BlipLocalPlayer,
ResynchronizeLocalPlayerForPortalArrival, LocalPlayerTeleportPlacement's
old duplicate Place authority, the ClassifyLeaveWorld family,
BlipPosition. LiveEntityRuntime has no legacy CreateObject position
seed; HeadlessSessionWorldProjection has no remaining direct placement
writer; PhysicsEngine.SetPosition (Core) is called only from
RuntimeSetPositionState (:2028,:3125,:4789) in production. PhysicsBody.SnapToCell's
eleven src callers are three canonical-owner sites, two per-tick simulation
sites, and five projectile/static/first-entry body seeds that are live by
design (AP-141 pinned the projectile no-machinery decision) — none deletable.
2. Register rows: provable retirements vs blocked
| Row | Verdict | Evidence |
|---|---|---|
| AD-1 | RETIRABLE in the deletion commit. Its divergence sentence — "Production authoritative placement still routes through the legacy recoverable outdoor demote and outdoor-restore max(terrainZ, z) lift" — is already false at HEAD: that code is PhysicsEngine.Resolve (:1863-2222; demote at :1906, lift at :2168-2173) and it has zero production callers. Its listed prerequisites (authored-mover, rebucketing, prefix-quiescence, body-publication, route cutover) all landed C0–C4. Deleting D1/D2 makes the retirement structural rather than merely observational. |
census §2; PhysicsEngine.cs:1863 |
| AP-1 | RETIRABLE in the deletion commit. "Production zero-delta routes deliberately remain on the legacy resolver until 4B2" is stale: every production placement writer now reaches Core SetPosition only through RuntimeSetPositionState; the local controller's body adoption / sealed setter landed at C3c; deleting D1/D3/D4/D5 removes the last resolver-shaped entry points (all already caller-free). 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. |
census §§2,3,4,7 |
| AP-131 | BLOCKED — retires only with #275, which is a behaviour change, not a deletion. The legacy caller AP-131 says "is deleted at the production cutover" is still the ONLY steady-state production Position merge at HEAD (chain in §1b), still passing unconditional true/true. Retiring it means computing the classified ApplyPlacementFrameBeforeRouting / UnparentBeforeRouting flags (plus retail's FORCE_POSITION Gate A skip) BEFORE the merge on the steady-state path, exactly as the executor already does for residence-pending entities. That changes what every ordinary inbound Position does to animated and parented entities — retail-correcting, but a live-path behaviour change requiring the full contract + dual-review discipline. |
InboundPhysicsStateController.cs:662-663; executor :1991-1992 |
| AD-60 legacy half | BLOCKED — same gate, #275. RuntimeEntityObjectLifetime.cs:1918 still derives FullCellId from bare wire acceptance on every accepted steady-state Position (the 4b-3 D1 comment at :1886-1899 states it plainly). Withholding it (executor's refreshPosition: false rule) moves residency changes onto placement/simulation commits only — the retail rule — but FullCellId is the residency predicate at 45+ sites (AP-142's own count), so the blast radius is real and this must not be smuggled into a sweep. |
RuntimeEntityObjectLifetime.cs:1915-1918 |
Rows adjacent but NOT C5 targets: AD-61 (force-seed, deliberate), AD-62 (non-commit force outcomes), AP-135 (retained bookkeeping), AP-141–145 (all filed with their own conditions; AP-145 retires with #318's fix, not its test — the test only makes the asymmetry assertable).
3. THE DANGEROUS CASE — every test-only-caller path, with disposition
First a sharpening the scoping question deserves: deleting a method whose callers are tests is compile-loud (the test project breaks), same as a production caller. The genuinely silent case is the disposition of the tests afterward: deleting a test that pinned behaviour which MOVED (instead of re-pointing it) is the silent coverage loss. Per item:
| Path | Test callers | Behaviour gone or moved? | Disposition |
|---|---|---|---|
PhysicsEngine.Resolve |
PhysicsEngineTests.cs ×12 |
Gone — the outdoor-demote/floor-snap/terrain-lift semantics are legacy-only; the canonical replacements have their own suites (PhysicsSetPositionTests, RuntimeSetPositionStateTests) |
Delete tests with the path, after a one-pass audit that no individual assertion pins something canonical-owned (e.g. AdjustPosition behaviour, which survives — tests touching it re-point at AdjustPosition directly) |
PhysicsEngine.Resolve |
Issue133DungeonTeleportPrefixTests.cs:58 |
Moved — #133's invariant (landblock-prefix correctness on dungeon teleport claims) is now the canonical portal/teleport placement's job | Re-point at the canonical path (drive a teleport-classified RuntimeSetPositionState placement with a prefixed dungeon claim and assert the committed cell), or prove an existing canonical test already pins it and record that in the deleting commit. Do NOT silently delete — this is a regression pin for a named historical bug |
PhysicsEngine.ResolvePlacement |
InitialPlacementOverlapTests.cs:42 |
Moved — placement-ring occupancy search is ported inside canonical SetPosition (find_placement_position, covered by PhysicsSetPositionTests) |
Verify-then-delete: confirm PhysicsSetPositionTests covers the occupied-spawn ring-search case this test pins; if not, re-point it at Transition.FindPlacementPos via the canonical entry before deleting |
PhysicsEngine.ResolvePlacement |
TransitionScratchDifferentialTests.cs:185-217 |
Moved — these are Slice-I zero-alloc differential arms | Re-point or drop the arm explicitly: if ResolvePlacement was one of the differential's measured entry points, replace with the surviving canonical entry; a silent drop would shrink the I-slice differential's coverage without anyone deciding it |
PlayerMovementController.SetPosition |
~19 test files (~45 sites in PlayerMovementControllerTests alone) |
Neither — these tests USE it as fixture setup (position the player), they do not test it | Mechanical re-point through one shared test helper that drives the production seeding path (publication PreparePositionForCommit → activation), or — cheaper and honest — keep ONE explicitly-named internal test-seed method with a doc comment stating it exists for fixtures only. Either way the fixture semantics (grounded start via the force-seed) must be reproduced deliberately, since dozens of movement tests assume a grounded, zero-velocity start |
PlayerMovementController.CommitPreparedPosition |
3 sites | Moved — replaced by ArmConstraintLeashAtCommittedPlacement |
Re-point: the prepared-position transaction assertions should run against the production arm/commit pair; RuntimeLocalPlayerPhysicsPublicationStateTests:3007 likely already half-covers it — audit before deciding delete-vs-rewrite per test |
BeginAcceptedPlacement/BeginAuthoredPlacement wrappers |
~40 sites, 10 files | Neither — the CORE (BeginAcceptedPlacementCore) is production; the wrappers are test conveniences |
Two defensible calls: (a) keep the wrappers, documented as test seams (zero churn, zero coverage change); (b) delete and mechanically re-point every site at Apply/the authored sequence. The ~40-site churn buys nothing behavioural; recommend (a) unless the campaign wants the sweep to be absolute — in which case budget the churn (it is mechanical but touches the Runtime suite broadly) |
InboundPhysicsStateController.TryApplyPosition (true/true overload) — #275's deletion |
its unit tests assert the UNCONDITIONAL flags | Deliberately changed — the old assertions describe the divergence being removed | Rewrite, never delete-only: each unconditional-flag assertion becomes a classified-flag assertion (animated entity keeps its placement frame; ForcePosition on a parented entity does NOT unparent — retail Gate A), sabotage-verified both directions per process rule (e) |
One more test-shaped landmine, inherited not created: the #316-preserving
pair (LandingPacket_PlayerGuid_QueueClearedNoShadowPublish_316Preserved /
..._CreatureGuid_ShadowPublishedQueueNotCleared) pins a defect preserved
verbatim. If C5's connected session measures #316 and the fix lands, that
test inverts by design — do not "fix" the test without the measurement.
4. The C4 inheritance, sized
| Item | What it is | Size / shape |
|---|---|---|
| #318 composition test | Drive a real portal arrival through the canonical drive controller + REAL RuntimePlacementPresentationSink + REAL PhysicsEngine; assert PhysicsEngine.ShadowObjects holds a row at the destination (never just LocalPlayerShadowState's dedup cache — AP-145's TryPublishPlace → .Set() bypass both skips the publish AND pre-seeds SyncPose's dedup so the next tick can skip too; a cache-only assertion is satisfied by the bug) plus the T8 write ordering |
Test-only, ~150–300 lines, App.Tests. The wiring cost is composition (real sink + real engine in one fixture), not assertion count. Retires nothing by itself; it makes AP-145 falsifiable |
| AP-145 asymmetry | The cache-without-publish seam itself | NOT a C5 fix unless the composition test proves a live miss; the row argues why it self-heals in practice. Land the test first, decide after |
| Route-2 B2 parity test | The plan's recorded acceptance gap (plan §C4 route 2): no test drives an accepted ForcePosition end-to-end through the presentation sink and asserts the render entity moved from the committed receipt | ~100–200 test lines. Flag: this deliverable is in the PLAN but absent from the handoff's "What C5 inherits" list — carry it explicitly so it doesn't fall between documents |
| #276 remainder | SpawnPlacementSettler.TrySettle discards settle.CellId |
~30–80 production lines + a conformance test; NOT named a C5 deliverable by the plan — carry unless cheap to fold; does not block AP-1 (separately filed) |
| #277 | far-Create service-window conversion | Trigger-conditioned (no radius changed); zero C5 work |
| #313 | DeclareValid selection transfer |
Selection UX, outside placement; carry |
| #316 | player-arm landing never publishes the shadow — measure before fixing; the named instrument is ACDREAM_PROBE_REMOTE_LANDING |
The measurement is a two-client landing observation — fold it into the early gate session (§5); the fix (if the #184 class) is its own later commit |
| #317 | velocity-chain retail audit | Research-only (decomp), no code; carry unless the session has slack |
| #309 narrow half | GotoLostCell hidden-until-reenter_visibility |
Carried, re-scope before running; not C5 |
| #280 | portal destination prefetch | Its own slice with its own visual gate. Ordering note the handoff does not restate: the campaign plan's numbered order (items 3→4→5) puts #280 BEFORE C5's final-binary soak/matrix — sensible, since #280 changes reveal behaviour the matrix would exercise. C5's implementation slices are independent of it and can proceed; the final closeout gates should run after #280 lands, or the matrix will need re-running |
| Probe strip | six TEMPORARY flags | ~1,340 lines total: REMOTE_SLIDE ~700, REMOTE_LANDING ~300, LOCAL_TELEPORT ~215, REMOTE_TELEPORT ~50, PARK ~41, CHILD_CELL ~33. All env-only (no DebugPanel mirrors), zero test references — the strip is test-free. Hazards recorded by the census: keep ParseHexIdList (shared with permanent ACDREAM_DUMP_*), keep the DISTINCT older ACDREAM_PROBE_TELEPORT/LogTeleport block that sits adjacent to LogLocalTeleportArrival (two flags, documented distinct at RuntimeAcceptedPositionDriveController.cs:769-770), keep the probe-aliased production members (BodySnapThreshold, InterpolationManager queue state, bodyOnWalkableAtTickStart), and trim ResetForTest line-wise, not wholesale |
5. Gate sequencing — and the cell-less trigger, answered by reading
State at HEAD: three of C4's four gates were run and user-passed on
2026-08-05 (route 3 unambiguous incl. the autorun-cancel line; route 6 visual;
route 7 pass but THIN — one cause=propagate). Owed: (a) route 7 thickening
(several equipped landblock crossings, expect double-digit propagate), and
(b) gate 4, cause=cellless, whose recorded recipe route 7 invalidated.
The cell-less trigger — what reading establishes
The classifier's cell-less arm needs PreMergeCommittedCellId == 0, which
requires an ACTIVE canonical record whose FullCellId is 0 at merge time
(RuntimeEntityObjectLifetime.TryApplyPosition:1898 — a fully-withdrawn
record yields null, "no opinion", not 0). The production population of such
records exists and is well-defined:
- Post-pickup items:
TryApplyPickup(:1258) commitsSetFullCell(canonical, 0u, 0u)at:1314and leaves the record ACTIVE (withdrawn presentation, suspended clock, but in the directory). - Children zeroed by
WithdrawCommittedChildrenToCelllesson parent delete — but ACE deletes tracked equipment alongside its wielder (Player_Tracking.cs:108-112), so these tombstone rather than linger. - Unwield — no longer cell-less (route 7 D1/D2: committed child carries the parent's cell), which is exactly why the old recipe died.
The one ACE message that delivers a bare UpdatePosition to population (1):
dropping the item. HandleActionDropItem
(references/ACE/.../Player_Inventory.cs:1437-1443) sends the dropper
GameMessageUpdatePosition(item) directly after TryDropItem — and for
RemoveFromInventoryAction.DropItem no client-side delete precedes it (no
InventoryRemoveObject, no DeleteObject; :222-247), so the client-side
record is still the active cell-0 one from the pickup.
The deciding nuance, which reading could not fully settle: inside
TryDropItem, Landblock.AddWorldObjectInternal calls wo.NotifyPlayers()
(Landblock.cs:900) which sends CreateObject to every player in the item's
freshly-created PhysicsObj.ObjMaint known-players set — all enqueued on the
same ordered reliable stream BEFORE the UpdatePosition at :1443. If the
dropper is in that set at that instant (populated synchronously during
AddPhysicsObj), the Create precedes the Position, the Position lands in the
initial-create residence branch, and it classifies against the Create's own
resolved cell — not cell-less. If known-player registration is deferred to
the player's next visibility tick, the UpdatePosition arrives first and
IS the live cell-less trigger.
Recommendation: a bounded two-minute falsification run, not an open
investigation: with ACDREAM_PROBE_REMOTE_TELEPORT=1, pick up a ground item,
drop it, repeat a few times (outdoors + once indoors), and read the
[remote-teleport] lines. Either cause=cellless appears (gate 4 closes with
a recorded recipe: pickup-then-drop), or it provably takes the Create path —
in which case record the cell-less arm as synthetic-fixture-covered by
design with no reachable live trigger against ACE, exactly the route-5
precedent ("when a gate cannot exist, record that, never a substitute"),
process rule (g). Do not leave gate 4 on file as pending indefinitely.
Sequencing
Run the owed gates FIRST, before any C5 implementation, as one cheap user session on the current binary: route-7 thickening (PROBE_CHILD_CELL) + the cell-less falsification (PROBE_REMOTE_TELEPORT) + #316's measurement (PROBE_REMOTE_LANDING; a second client jumping/landing while observed). Rationale: (a) C4's ledger closes on evidence from the binary family its routes were gated on; (b) if thickening or the cell-less run surfaces a defect, C5's deletion inventory could change; (c) all three consume probes the strip will later delete. C5 absorbs the bookkeeping of these gates (ledger updates), not their execution debt.
6. Probe-strip ordering
The strip is last — after every connected gate in this campaign has consumed its probe evidence, as its own commit:
- Owed-gate session (§5) consumes CHILD_CELL, REMOTE_TELEPORT, REMOTE_LANDING.
- C5 implementation slices land (deletions, #275, tests) — probes untouched; they are env-gated and production-inert.
- C5 closeout gates run on the final implementation binary — the lifecycle/reconnect route re-exercises portals, so LOCAL_TELEPORT evidence remains readable if anything regresses; keep the probes through this.
- Strip commit (~1,340 lines, hazards per §4), then full Release suite + one short lifecycle route as the strip's own gate. The strip is behaviour-neutral by construction (env-gated emission only), so the final-binary soak from step 3 remains valid evidence; the post-strip re-run is the cheap proof of neutrality.
Conditional carve-out: if #316's measurement does NOT happen in the §5
session, ACDREAM_PROBE_REMOTE_LANDING must be excluded from the strip
(it is the issue's named instrument) and the family stripped five-wide with a
note — do not let a hygiene pass delete an open issue's measurement apparatus.
7. Size and split recommendation
Calibration: this campaign's landings ran ~127–~500 production lines each (4a 364, 4b-2 350–500, 4b-3 ~250, r5 ~131, r7 ~127, r3 ~418), each with full contract/dual-review discipline.
| Piece | Production lines | Test lines | Risk |
|---|---|---|---|
| Deletion sweep (§1a) | ~540 deleted | ~25 files touched; ~1,500–2,000 test lines deleted/re-pointed | Low (all compile-loud), but the §3 dispositions are judgment work |
| #275 unification (§1b/§2) | ~150–400 changed on the hottest inbound path | ~300–600 rewritten/added | High — behaviour change on every steady-state Position; 45+ residency-predicate blast radius for the AD-60 half |
| #318 + route-2 B2 tests | 0 | ~250–500 | Low |
| Probe strip | ~1,340 deleted | 0 | Low, hazard-listed |
| Gates + ledger/docs | 0 | 0 | User time |
Combined this is far past the ~500-line calibration, and #275 is a different RISK CLASS from everything else. Split into three landings plus the pre-session:
- C5-gate session (first, user-run): route-7 thickening + cell-less falsification + #316 measurement. Closes C4's ledger.
- C5a — deletion sweep + tests: §1a deletions, §3 dispositions, #318 composition test, route-2 B2 parity test, retire AP-1 and AD-1 in the same commit as the deletions (register rule 1). Deletion-only + test-only; reviewable as one diff.
- C5b — #275: pinned contract (the executor's classify-then-merge order is the template; retail Gate A is the FORCE_POSITION skip), single implementer, dual reviews, sabotage-verified flag tests both directions. Retires AP-131 and AD-60's legacy half in its own commit. This slice is where process finding (a) — "verify the load-bearing premise in code at implementation start" — applies to the classifier-flag semantics before building on them.
- C5c — closeout: final-binary complete suite, lifecycle/reconnect route, canonical nine-stop soak, two-client observation, user visual matrix (sequenced after #280 per the plan's own ordering, §4), then the probe strip + its neutrality gate, then register/roadmap/milestones/memory + the successor handoff, close #275, close the campaign ledger.
8. Plan claims found false or stale at HEAD (the seventh-stale-doc guard)
- Campaign plan / handoff framing that C5's register retirements are a deletion product: AP-131 and AD-60's legacy half cannot retire by deletion — they require #275, a live-path behaviour change (the plan does name "close #275", so this is a framing error, not a missing item — but a session that read only "delete every superseded legacy path" would ship the sweep and wrongly retire the rows).
- AD-1's and AP-1's own row texts are stale in the conservative
direction: the "production still routes through the legacy resolver"
sentences are already false at HEAD (
PhysicsEngine.Resolve/ResolvePlacementhave zero production callers). They over-claim a divergence, not a completed port — retire with the deletion commit. - The handoff's sweep candidate
ILocalPlayerTeleportPlacementis not deletable — it is the live post-commit presentation suffix with a production caller (§1c item 1). - The 4b plan's "every legacy fallback 4a left is 4b's to delete" list is
overtaken: at HEAD the pre-op
ConstrainToand duplicate constants are already gone, and the!IsGroundedreturn +ApplyRemoteContactRoutingare the canonical post-collapse retail shapes, not deletable debt (§1c item 3). - Stale line citations: the handoff's
TryApplyPickup (:1116)(now:1258; the same stale:1116lives on inRuntimeAcceptedPositionDriveControllerTests.cs:221's doc comment);ConstraintManager.cs:25andPhysicsBody.cs:442still document the deletedBlipPosition/SetPositionpair. - The handoff's "What C5 inherits" list omits the route-2 B2 parity test that the campaign plan itself records as "carry it into C5's parity tests" — carried here (§4).
- The cell-less trigger is no longer "UNESTABLISHED needing its own
investigation" in the open-ended sense: reading pins the candidate
population, the single candidate wire path (pickup-then-drop,
Player_Inventory.cs:1443), and the one ACE ordering fact a two-minute probe run settles (§5). The honest outcomes are a recorded recipe or a recorded cannot-exist — not a standing investigation.