# C4 route 5 — projectile authoritative placement: pinned contract (2026-08-04) **Scope:** make the post-residence accepted Position for a live projectile canonical — classify it through the shared route classifier, execute the placement dispositions through the one Runtime placement owner (`RuntimeRemotePlacementDriveController` / `RuntimeSetPositionState`), and delete the bespoke `ApplyAuthoritativePosition` authority that today short-circuits a missile packet before the classifier ever sees it. Pinned at HEAD **`30d3d114`**, clean tree, branch `claude/acdream-physics-divergence-5aa784`. **Line numbers in this contract are as-of `30d3d114` and WILL go stale; every citation also names the symbol — trust the symbol** (process rule 6; line ranges went stale twice within single review rounds during 4b-2/4b-3, and this route's own scoping doc is the third demonstration). Predecessor documents, binding where they still apply: - [`2026-08-04-c4-route-5-scoping.md`](2026-08-04-c4-route-5-scoping.md) — the research base. **Its file:line references predate the OnPosition collapse (`edc911b0`) and the #315 fix (`aaf0811f`) and are stale; §10 of this contract lists every claim the collapse invalidated or reshaped.** Its retail research (§2), prediction analysis (§4), and trap list (§7) survive and are folded in below, re-verified. - [`2026-08-04-onposition-collapse-contract.md`](2026-08-04-onposition-collapse-contract.md) — the unified remote tail this route dispatches AHEAD of (never into). Its §7 non-goal ("Route 5 will add its arm against the collapsed single path — that is the payoff, not the scope") is cashed out here. - [`2026-08-04-c4-route-4b-3-contract.md`](2026-08-04-c4-route-4b-3-contract.md) — its 13 "must REMAIN true" invariants and the D4 constraint-arm partition still bind; §5 below extends the partition with the projectile column. - The four 4b-3 review rounds ([retail](2026-08-04-c4-route-4b-3-retail-review.md) / [round 2](2026-08-04-c4-route-4b-3-retail-review-round2.md) / [architecture](2026-08-04-c4-route-4b-3-architecture-review.md) / [round 2](2026-08-04-c4-route-4b-3-architecture-review-round2.md)) — the recurring defect classes (a mapping written against one caller's reachable set; an invariant satisfied on one arm only; a register row asserting behaviour the code does not have; a mismapped retail action with the faithful port already in-tree; tests that assert only negatives) are each addressed by name below. - [`2026-08-04-session-handoff-c4-remaining.md`](2026-08-04-session-handoff-c4-remaining.md) — the six process rules apply verbatim. - [`docs/plans/2026-08-02-placement-cutover.md`](../plans/2026-08-02-placement-cutover.md) — C4 route list; route 5 is "projectile authoritative". **Sequencing:** 4b-2 (`7f1c1f5a`), 4b-3 (landed, gate passed), the collapse (`edc911b0`), and #315 (`aaf0811f`) are all in. The scoping's "route 5 lands after 4b-2, preferably after 4b-3" constraint is satisfied; route 5 is next. --- ## 0. Facts settled before this contract — do not re-litigate 1. **Route 5 is half shipped.** The Create half (`RuntimeInitialCreateResidenceState.Begin` decides `RuntimePositionEntityKind.Projectile` from `record.FinalPhysicsState & PhysicsStateFlags.Missile`, `:591-595`) and the residence-window Position half (`RuntimeInitialCreateContinuationExecutor.ApplyPositionAction:1874`, kind recovered via `EntityKindOf:2571-2581`, one shared `RuntimeAcceptedPositionRouteRequests.Build` at `:1914-1926`) are canonical. What remains is exactly one thing: the accepted Position arriving AFTER the residence window, short-circuited before the classifier. 2. **NO LIVE GATE IS POSSIBLE.** ACE never sends `UpdatePosition` for a missile. Re-verified at HEAD: `references/ACE/Source/ACE.Server/WorldObjects/WorldObject_Tick.cs:333-334` is `/*if (PhysicsObj.IsGrounded) SendUpdatePosition();*/`, inside the branch gated on `(PhysicsObj.State & PhysicsState.Missile) != 0` at `:265`. Projectile classes broadcast `GameMessageVectorUpdate` and `GameMessageSetState` on impact — never a Position. **This slice is test-gated only** (§8). No connected gate is invented; if the implementer finds evidence contradicting this, STOP and report — it changes the slice. 3. Route 5 had to land after 4b-2 because it widens `RuntimeRemotePlacementDriveController.OwnsPlacement`. Done; see §3. --- ## 1. Site inventory — re-located at `30d3d114` Every site verified by reading at HEAD, not inherited from the scoping. ### 1.1 The duplicate authority to delete (the same three sites; new lines) | # | site (symbol) | at HEAD | what it is | |---|---|---|---| | D1 | `LiveEntityNetworkUpdateController.OnPosition` — the projectile short-circuit (`_projectileController?.ApplyAuthoritativePosition(...) == true → return`) | `:2104-2125` (was `:1428-1448`) | Sits after `_movementTruthDiagnostics.OnServerEcho` (`:2103`) and BEFORE the remote classification (`earlyRemoteRoute`, `:2150-2158`), `TryApplyGenericRemoteRenderPose` (`:2160`), `RebucketLiveEntity` (`:2190`), and the whole `update.Guid != _playerServerGuid` RemoteMotion tail (`:2234` on). Carries the fabricated `acceptedSpawn.Physics?.Velocity ?? System.Numerics.Vector3.Zero` at `:2119-2120` (was `:1442-1443`). | | D2 | `ProjectileController.ApplyAuthoritativePosition` (two overloads + doc) | `:492-590` (unchanged) | Validation (the `return true` swallow on invalid payload at `:551-554`), `ExternalOwnerValid` closure, render-pose acknowledgement (`:583-586`), delegation to the Runtime updater. | | D3 | `RuntimeProjectilePhysicsUpdater.ApplyAuthoritativePosition` | `:301-424` (unchanged) | The real authority: `InvalidatePrediction` `:342`, `body.Orientation` `:345`, `body.SnapToCell` `:346`, `body.State = record.FinalPhysicsState` `:347`, the velocity commit `:348-358`, `CommitProjectileCell` `:370-381`, the presentation acknowledgement `:387`, the spatial/hidden `InWorld`/`Activate`/shadow-sync/suspend tail `:390-422`. | Raw total 244 lines; roughly 180 non-comment — the scoping's figure holds. ### 1.2 The Runtime surfaces route 5 builds against | site (symbol) | at HEAD | relevance | |---|---|---| | `RuntimeAuthoritativePositionRouteClassifier` — `RuntimePositionEntityKind.Projectile` | `:13`; `ValidEntityKind:535-538`; `OperationKind` switch `:564-575` (Projectile → `ProjectileAuthoritative` at `:572-573`) | The kind's ONLY behavioural effect in the classifier is the `OperationKind` mapping. `ClassifyAcceptedPosition` (`:308-478`): the single kind branch is `LocalPlayer` (`:349`); Projectile and Remote are byte-identical in disposition, flags, `StopInterpolating`, `TeleportHookPhase`, and `ConstrainPhase` — teleport/cell-less `:404-421`, `NoPositionOperation` `:430-448`, near-`Interpolate`/far-`SetPositionSimple` `:459-477`. Pinned by `RuntimeAuthoritativePositionRouteClassifierTests.ProjectilePosition_UsesRemoteMoveOrTeleportClassification` (`tests:418-436`). | | `RuntimeEntityObjectLifetime.ClassifyRemoteAcceptedPosition` | `:617-659`; **hardcodes `RuntimePositionEntityKind.Remote` at `:642`** (was `:622`) | The one production remote-Position classification entry; feeds D1's `PreMergeCommittedCellId` (`:634`). Trap T4's site. | | `RuntimeRemotePlacementDriveController.OwnsPlacement` | `:520-524` (was `:274-278`) | `OperationKind is RemoteAuthoritative && Disposition is SetPosition or SetPositionSimple && Teleport flag` — **excludes `ProjectileAuthoritative`**. The widening target. | | `RuntimeRemotePlacementDriveController.TryExecuteAcceptedRemotePosition` | `:619-667` | Kind-agnostic body: stale-pending self-heal, `CanAttemptDestination` pre-flight → `Refused`, `TryBeginExclusiveAuthoredPlacement(record, version, route.OperationKind)` → `SubmitAndResolve`. Gated only by `OwnsPlacement`. | | `RuntimeRemotePlacementDriveController.ApplyAcceptedRemoteFarSnap` / `ApplyAcceptedRemoteTeleport` | `:760-784` / `:821-843` | **Both REQUIRE a `RemoteMotion` parameter and THROW unless `OwnsFarSnap` / `OwnsTeleportPlacement` own the route.** Not usable for projectiles — see §2. `StoreAcceptedDestinationPose` (`:845` on) writes the CANONICAL body and is reusable. | | `RuntimeRemoteTeleportPosition.OwnsTeleportPlacement` | `:38-46` | **NEW since the scoping** (4b-3). Gates on `OperationKind: RemoteAuthoritative` — a projectile teleport-classified route is NOT owned. | | `RuntimeRemoteFarSnapPosition.OwnsFarSnap` / `ResolveArm` | `:85-95` / `:137-148` | **NEW since the scoping** (4b-2). Same `RemoteAuthoritative` gate; a projectile far route would resolve `UnroutedCatchUp` → `ApplyInterpolate` against a RemoteMotion that does not exist. | | `RuntimeRemoteSteadyStatePosition.TryArmConstraintAfterOperation` | `:240-259` | Requires `remote.Host` (an `EntityPhysicsHost`). A projectile has none. | | `RuntimeSetPositionState.TryBeginExclusiveAuthoredPlacement` / `TryPrepareAndSubmitAuthoredPlacement` | `:1817-1861` region | `operationKind` is a pass-through parameter; the placement pipeline is kind-agnostic. **Caveat for the implementer:** two internal operation constructors stamp `Kind = RemoteAuthoritative` outright (`:3833/:3866` — the window-departure park constructor; `:5338/:5350` — the legacy-direct withdrawal shape), and the direct-command gate at `:5445-5446` admits local kinds only. Proof obligation P3 (§6) covers these. | | `RuntimePhysicsState.CommitProjectileCell` | `:1376-1397` | NOT a bypass — routes into the shared `CommitCanonicalCell` with an exact-owner check including `PredictionAuthorityVersion`. The 2026-08-02 inventory's "ad hoc" label remains wrong (scoping already corrected this; re-verified). | | `RuntimeProjectile` | `RuntimeProjectile.cs` (whole file) | `{ Body, CollisionSphere, PredictionAuthorityVersion, InvalidatePrediction() }`. No Host, no PositionManager, no InterpolationManager, no MovementManager. `RuntimeEntityRecord.Projectile` is the canonical slot (J5.6). | | `RuntimeProjectilePhysicsUpdater` — quantum + Vector/State channels | `TryBegin`/`Complete` `:37-205`; `ApplyAuthoritativeVector` `:207-250`; `ApplyAuthoritativeState` `:252-299` | Out of scope (invariants 4/5). `InvalidatePrediction` is bumped at exactly `:241`, `:272`, `:342` — the sole cancellation mechanism for a split quantum (trap T3). | | First-entry admission | `RuntimeRemoteFirstEntryState.cs:311-314` | Admits `RemoteAuthoritative or ProjectileAuthoritative`. Untouched. | | Continuation-executor non-SetPosition gap | `RuntimeInitialCreateContinuationExecutor.cs:2019-2026` | `Interpolate`/`NoPositionOperation`/`AwaitFreshPosition` → typed trace + return ("Binding to the live interpolation owner is cutover work"). §3 D-P4 resolves the projectile half of that gap (no-op by policy); the REMOTE half stays open — do not touch. | ### 1.3 App-side context (dispatch site + presentation) | site (symbol) | at HEAD | relevance | |---|---|---| | `OnPosition` shared prologue | `:1891-2103` | Authority gate + merge (`TryAcceptPosition`, `:1902`) — so `AcceptedPhysicsTimestamps.PreMergeCommittedCellId` is already measured for missile packets; hydration recovery; `EnsureWorldOrigin`; world-pos translation; `MarkLiveOwnerPoseDirty` (`:2068`); `OnServerEcho` (`:2103`). All runs for missiles today and keeps running. | | `ProjectileController.CanAcceptPositionPayload` | `:102-126`, called unconditionally at `:1898-1901` (was `:1205-1208`) | The SHARED admission validator (returns true for non-projectiles); an invalid missile payload already fails the authority gate before the short-circuit. NOT a deletion target. | | Unified remote tail (post-collapse) | `:2234-2810` | One guid-blind path; two named guid survivors (TS-44 sticky `:2537-2546`; the #316-preserved player `AirborneSnap` interp-clear/shadow-skip `:2581-2632`, `:2795-2809`). **Route 5 must not touch any of it.** | | `RunRemoteArmTail` / cached #315 callbacks | `:1427-1463`, `_remoteArmCallbacks` backing methods `:1474-1492` | The allocation pattern to follow if the projectile arm needs any callback: cached delegates + scratch fields, never per-packet closures. | | `TryApplyGenericRemoteRenderPose` | `:1010-1025`, called `:2160` | Gate is `OwnsSteadyState`. The projectile arm dispatches BEFORE this call (§3 D-P6) — a missile packet takes no early wire-pose write today and must not start taking one. | | `ProjectileController.Tick` / `AdvanceQuantum` / `TryBeginQuantum` / `CompleteQuantum` / `IsCurrentQuantumIdentity` | `:640-766` / `:773-782` / `:784` / `:822-848` / `:850-859` | The per-quantum owner. Untouched. | | `LiveEntityAnimationScheduler` split quantum | `src/AcDream.App/Rendering/LiveEntityAnimationScheduler.cs:404-426` | `TryBeginQuantum` `:405-409` … `_animationHooks.Capture` … `CompleteQuantum` `:419-423`. The straddle window trap T3 protects. Untouched. | | `ProjectileController.TryBind` + create branch | `:133-330`; late-classification path `ApplyAuthoritativeState → TryBind` `:473-489`; projection-visible retry in `OnProjectionVisibilityChanged` `:860-897` | Still the live fallback for `initialResidenceActive == false` (`DatLiveEntityProjectionMaterializer.cs:848-865` — note: `src/AcDream.App/Rendering/`, not `World/`) and the mid-life Missile-bit flip. **NOT deleted here** (trap T8; C5's deletion pass owns it). | | `ProjectileController.HandlesMovement` | `:599-602` | The Missile-bit ownership predicate the kind discriminator must agree with (§3 D-P1). | --- ## 2. How the OnPosition collapse changed route 5's shape The scoping assumed route 5 would rewrite call sites inside two parallel player/NPC copies of the remote tail. The collapse (`edc911b0`) replaced them with **one unified, RemoteMotion-shaped path** plus two surviving named guid-conditionals. Consequences, stated precisely: 1. **Route 5 touches the unified tail NOT AT ALL.** The projectile arm dispatches from `OnPosition` at (approximately) the current short-circuit's site — after the shared prologue, BEFORE `TryApplyGenericRemoteRenderPose`, `RebucketLiveEntity`, and the `update.Guid != _playerServerGuid` block — and returns. A missile packet must never reach `GetOrCreateRemoteMotionRuntime`, `SeedRemoteSpawnPlacement`, `TryCommitAuthoritativeVelocity`, the sticky gate, `RunRemoteArmTail`, the arming site, the wire-cell adopt, or the remote entity-sync/shadow tail. The entire tail assumes a `RemoteMotion`; a projectile has none, and creating one is exactly the "second body or interpolation owner" the current short-circuit's comment exists to prevent. 2. **The "two copies to widen" work item is gone.** The scoping's §8 line item "App call-site rewrite in OnPosition … 40-70 lines" shrinks to ONE dispatch site. This is the collapse's payoff for route 5. 3. **Three ownership predicates now fence projectiles out, not one.** The scoping knew only `OwnsPlacement` (§5.2). Since then 4b-2/4b-3 added `OwnsFarSnap` and `OwnsTeleportPlacement`, both gated on `OperationKind: RemoteAuthoritative`, and both remote arm methods (`ApplyAcceptedRemoteFarSnap` / `ApplyAcceptedRemoteTeleport`) THROW on a non-owned route and REQUIRE a `RemoteMotion`. Consequence: **only `OwnsPlacement` is widened; the other two predicates and the two remote arm methods are deliberately NOT widened and NOT reused** — the projectile arm is a sibling seam over the shared `TryExecuteAcceptedRemotePosition` + `StoreAcceptedDestinationPose` core (§3 D-P2). The bright side: a mis-routed projectile packet now fails loudly (throwing guards) instead of silently taking a RemoteMotion arm. 4. **The two surviving guid-conditionals are off-limits.** TS-44's sticky gate and the #316-preserved player `AirborneSnap` interp-clear/shadow-publish skip are named, contract-protected asymmetries of the collapse. Route 5 has no business near either. 5. **#315's callback pattern binds new code.** The collapse's second commit cached the remote-arm callbacks; the projectile arm must not reintroduce per-packet closures on the packet path (the projectile hook reduction in D-P4 needs at most a method-group/cached delegate). --- ## 3. Design decisions — pinned, not open for redesign ### D-P1 — one per-packet kind discriminator, derived where the classification already runs (resolves trap T4) `RuntimeEntityObjectLifetime.ClassifyRemoteAcceptedPosition:642` stops hardcoding `RuntimePositionEntityKind.Remote` and derives the kind from the canonical record: ``` (canonical.FinalPhysicsState & PhysicsStateFlags.Missile) != 0 ? RuntimePositionEntityKind.Projectile : RuntimePositionEntityKind.Remote ``` This is the SAME data-driven predicate the Create half uses (`RuntimeInitialCreateResidenceState.cs:591-595`), the same one `EntityKindOf` recovers from the lease, and the same bit `ProjectileController.HandlesMovement` keys movement ownership on — data-driven, never display-name-gated (feedback_retail_dispatch_is_data_driven). The App dispatch in `OnPosition` branches on the SAME underlying fact: pinned, the App reads `route.OperationKind is ProjectileAuthoritative` off the returned route wherever a route exists, and for the null-classification case reads one `FinalPhysicsState & Missile` test on the same canonical record in the same packet — so the classifier's kind and the App's dispatch cannot disagree (a mis-tag is otherwise silent, because the dispositions are identical for the two kinds; only the ledger/owner would be wrong). The mid-life bit flip is thereby handled by construction: ACE clears Missile on impact (a State packet), and `ApplyAuthoritativeState → TryBind` is where an ordinary object becomes a missile. Whichever `FinalPhysicsState` the packet's merge left on the canonical record decides the packet's arm; the adopted-body case (a missile that also carries a `RemoteMotion`) follows the Missile bit exactly as `HandlesMovement` already does, and the untouched `RemoteMotion` is simply not written by that packet. Route-1 semantics are untouched: the residence/continuation callers already pass an explicit kind; only the remote PositionEvent entry changes its kind input. The classifier itself does not change at all. ### D-P2 — the projectile execution seam: one controller, shared core, no RemoteMotion New Runtime seam on the EXISTING `RuntimeRemotePlacementDriveController` (never a sibling controller, never a second pending map — trap T9), shape at the implementer's discretion but pinned in behaviour: `ApplyAcceptedProjectilePosition(RuntimeEntityRecord record, in RuntimeAuthoritativePositionRoute route)` (reads `record.Projectile` internally), which: 1. **Validates ownership** — the route's `OperationKind` is `ProjectileAuthoritative`; `record.Projectile` and `record.PhysicsBody` exist and agree (`ReferenceEquals(record.PhysicsBody, projectile.Body)` — the J5.6 canonical-body identity). Anything else: return `NotApplicable`-equivalent, write nothing. 2. **Dispatches on disposition:** - `SetPosition` (teleport / cell-less): run the projectile hook reduction (D-P4) BEFORE the placement, then `InvalidatePrediction()`, then `TryExecuteAcceptedRemotePosition(record, route)` (now `OwnsPlacement`-admitted, D-P3), then `StoreAcceptedDestinationPose` on the `StoresAcceptedDestination` partition — the partition itself is extended UNCHANGED (4b-3 invariant 1; do not re-litigate which statuses store). - `SetPositionSimple` (far): `InvalidatePrediction()` → `TryExecuteAcceptedRemotePosition` → store on the same partition. No interp clear (no queue exists; retail's own far-branch `StopInterpolating` is guarded on `position_manager != 0` @0x005163C9-@0x005163CB and a never-interpolated missile has none, so the skip is retail-faithful by consequence, not a divergence). - `Interpolate` (near, in contact): **no-op by pinned policy** — see D-P4. No body write, no prediction invalidation (nothing changed). - `NoPositionOperation` (airborne): no-op — retail's `return 0` @0x0051636D, faithful. No prediction invalidation. 3. **Invalidates prediction before ANY body write on this route** — the placement path and the store fallback both clobber the body retail-side of an in-flight split quantum (trap T3). One `InvalidatePrediction()` at the seam's placement dispatch (before Begin) covers both, mirroring today's `:342`-before-`SnapToCell` ordering. The no-op dispositions do NOT invalidate: the body is untouched, so a straddling quantum completing is correct, and the Vector/State channels' invalidate-on-write semantics stay coherent. 4. **Commits NO velocity** (D-P5). 5. **Arms NO constraint leash** (D-P4). The post-commit lifecycle tail — `InWorld`/`Activate`/shadow-sync on spatial+visible, suspend on spatial+hidden, deactivate+suspend on non-spatial (today's `RuntimeProjectilePhysicsUpdater.ApplyAuthoritativePosition:390-422`) — is preserved semantically on the committed/stored outcomes. Whether it lives in the new seam or stays a small retained method on the projectile updater is the implementer's choice; pinned is that it remains Runtime-owned (J5.6 boundary, invariant 6) and keyed on the same spatial/hidden facts. App keeps exactly what J5.6 assigns it: the presentation acknowledgement. `OnPosition`'s projectile dispatch (D-P6) projects the committed/stored snapshot into the render entity (`SetPosition`/`Rotation`/`ParentCellId` from the RESOLVED body) and `_rootPoses.UpdateRoot` — the same ack contract `ProjectileController.ApplyAuthoritativePosition:583-586` performs today. No `RebucketLiveEntity` on this arm (the canonical placement/cell commit is the cell authority, exactly as the per-quantum commit is today; adding the remote tail's bucket transaction here would be a new second writer). ### D-P3 — the `OwnsPlacement` widening, and every consequence `RuntimeRemotePlacementDriveController.OwnsPlacement:520-524` first clause widens to `route.OperationKind is RuntimeSetPositionOperationKind.RemoteAuthoritative or RuntimeSetPositionOperationKind.ProjectileAuthoritative` (+ doc update). Consequences, each pinned: - **`TryExecuteAcceptedRemotePosition` admits projectile routes.** The Teleport-flag conjunct keeps excluding Creates (the first-entry conductor owns every Create — unchanged; a projectile Create carries `InitialCreateFlags`, an accepted Position carries `0x1012`). - **Pending/acknowledgement ledgers are shared.** Projectile operations land in the same `_pending` / `_awaitingAcknowledgement` maps; `DetachRoute`'s cancel-then-clear teardown and `CountLivePending`'s self-heal cover them with zero new code. No parallel map, no sibling controller (T9). - **Parks/refusals behave exactly as the remote arms'** (4b-3 invariant 3 extended): `Refused` (pre-flight) and `Contention`/`RejectedPreparation` store the accepted destination; `DeferredCell` is cancelled synchronously with `restoreCancelledPark: true` — no park survives the controller; `RejectedByPlacement` does not store. The projectile body stays `InWorld`, clock active, spatially projected on every non-commit outcome. - **`OwnsFarSnap` and `OwnsTeleportPlacement` are NOT widened** (§2 item 3). Their throwing guards and the two RemoteMotion-shaped arm methods are untouched. State this in their docs only if a comment would otherwise mislead (process rule 6). - **The constraint arm:** see D-P4. The classifier's projectile routes carry `ConstrainPhase.AfterPositionOperation` (kind-blind, `:417`/`:473`); the projectile arm deliberately does not consume it. No change to the classifier; the deviation is recorded (D-P7). - **The interp queue:** nonexistent for projectiles; `StopInterpolating: !nearby` on the far route is inert and retail-faithfully so (D-P2). - **`CommittedHostAcknowledgementPending`:** a committed placement can enter `_awaitingAcknowledgement` (`:1062-1076`). Whether the graphical host's projection-acknowledgement chain retires a `ProjectileAuthoritative` commit identically is proof obligation P2 (§6) — verify, do not assume. ### D-P4 — retail's manager actions, reduced to what a missile has (resolves scoping §5.1; answers the constraint-arm question) **Retail's mechanical answer, verified in the decomp (§4): YES, retail would arm the leash for a missile.** `SmartBox::HandleReceivedPosition` @0x00453FD0 has NO kind test other than `arg2 != this->player` (@0x0045414D); every nonzero `MoveOrTeleport` return reaches `ConstrainTo` @0x00454272; and `CPhysicsObj::ConstrainTo` @0x00510520 calls `MakePositionManager` (@0x00510523) — creating the manager on demand for any object, missile included — after which `UpdateObjectInternal` ticks it (`PositionManager::UseTime` @0x005159A9-@0x005159B3). Likewise retail's near branch (`InterpolateTo` @0x005163AF, with `IsMovingTo` @0x0050EB10 returning 0 for a manager-less missile) would build interpolation machinery for it. **acdream pins the divergence instead of the machinery.** Building an `EntityPhysicsHost`/`PositionManager`/`InterpolationManager` chain for a ballistic body — for a packet ACE never sends — is the route-5b split the scoping warned against, and this contract REJECTS it. Pinned: - The projectile arm **never arms `ConstrainTo`** — on any disposition, any outcome. - The near-`Interpolate` disposition is a **no-op** (no queue to feed, no manager to create). - Both are recorded in ONE new register row (D-P7) citing @0x00454272, @0x00510523, @0x005163AF, and the ACE unreachability (`WorldObject_Tick.cs:333-334`). **The teleport hook, reduced.** Retail's teleport/cell-less branch runs `teleport_hook` @0x00514ED0 before the placement — six actions, each guarded on its manager existing. For a pure missile, five of six are structurally absent (`MovementManager`/`PositionManager`×3/`TargetManager` are null → retail no-ops through the guards). The sixth, `report_collision_end(this, 1)` @0x00514F31 → @0x00514620 (force-end-all with bidirectional notification), applies to ANY object with a collision table. **Pinned: the projectile teleport/cell-less arm runs the faithful force-end port — `RuntimeCollisionReportingState.LeaveWorld` (the exact seam the 4b-3 R2 fix validated against @0x00514620, round-2 retail review §2) — before the placement.** Omitting it would recreate R2's defect class with the faithful port sitting unused in-tree. The other five actions execute iff their owning component exists — for the adopted-body case (a missile that carries a `RemoteMotion`), the existing hook actions' per-manager guards already express retail's shape; the implementer wires this without per-packet closures (#315 pattern). For the ordinary arrow/bolt they are no-ops by the same guards retail uses. **Null / `Rejected*` classifications for a missile packet: swallow.** Write nothing, create nothing, return — never fall through to the remote tail (preserving trap T5's semantics: today an unhandleable projectile packet is swallowed, not re-routed). The remote `UnroutedCatchUp` policy is RemoteMotion-shaped and does not apply. This is an acdream-only state (retail rejects nothing here); it rides in the same register row. ### D-P5 — no velocity write from a Position packet (retires the zeroing defect) Retail's `MoveOrTeleport` declares `arg5 = AC1Legacy::Vector3 const*` and never references it in the decompiled body (@0x00516330-@0x00516438, re-verified for this contract); `HandleReceivedPosition` threads its `arg6` into it (@0x00454254) and does nothing else with it; `UnpackPositionEvent` @0x004542C0 performs no `set_velocity`. Velocity authority for a missile is the Vector channel (0xF74E / `ApplyAuthoritativeVector`), untouched here. **Pinned: the projectile arm consumes no velocity from the Position packet.** This deletes the `acceptedSpawn.Physics?.Velocity ?? Vector3.Zero` fabrication (`:2119-2120`) and the updater's conditional commit (`:348-358`), retiring the (never-filed) defect where a velocity-less Position packet zeroes an in-flight missile's velocity. Because "textually unreferenced" is strong-but-not-byte-confirmed (BN elision risk, scoping §9.2), **the implementer byte-verifies 0x00516330-0x00516438 for any `arg5` use before landing** (`tools/pdb-extract` PE byte-decode against the paired `refs/acclient.exe` — the `reference_pe_byte_decode.md` recipe). If a use is found: STOP and report — the velocity policy changes. ### D-P6 — the App dispatch site and ordering In `OnPosition`, the D1 short-circuit is replaced in place by: ``` classify (kind-aware, D-P1) // one call, both kinds — // replaces the :2150 remote-only call if the packet is a missile packet (D-P1's discriminator): dispatch the projectile arm (D-P2) and RETURN // before TryApplyGenericRemoteRenderPose, // before RebucketLiveEntity, // before the RemoteMotion tail else: the unified remote tail runs UNCHANGED // earlyRemoteRoute now comes from // the same classification call ``` Pinned facts of this shape: - The projectile arm takes **no early wire-pose write** (`TryApplyGenericRemoteRenderPose` is never reached — matching today, where the short-circuit precedes it) and **no `RebucketLiveEntity`**. Presentation advances from the RESOLVED body via the ack (D-P2), exactly as the per-quantum path does. - The shared prologue (authority gate/merge, hydration, world origin, `MarkLiveOwnerPoseDirty`, `OnServerEcho`) runs for missiles exactly as today — the dispatch sits at/after the current short-circuit's position. - The classification for a REMOTE packet is byte-identical to today's (`Remote` kind in → same route out); only its call site may merge with the projectile classification. Zero remote-classifier test changes is the regression tripwire (§8 stop condition). ### D-P7 — register and issue bookkeeping, in the implementation commit - **ONE new AP row** (projectile accepted-Position divergences): (a) near-`Interpolate` is a no-op where retail would `InterpolateTo` a manager-on-demand missile (@0x005163AF, @0x00510523); (b) the post-operation `ConstrainTo` @0x00454272 is never armed for a projectile (no PositionManager machinery exists for a ballistic body); (c) null/`Rejected*` missile packets are swallowed rather than caught up (no RemoteMotion); with the shared context that ACE never emits the packet (`WorldObject_Tick.cs:333-334` commented out inside the Missile branch) so every half is test-gated. Note in the row that the far branch's `StopInterpolating` skip is NOT part of the divergence — retail's own `position_manager != 0` guard @0x005163C9 skips it for a never-interpolated missile. - **No row deletion:** the velocity-zeroing defect being retired was never filed; record its retirement in the commit message (and this contract), not the register. - **Comment corrections (process rule 6):** the D1 site's comment block ("Missiles reconcile the same predicted PhysicsBody in place…", `:2104-2108`) dies with the short-circuit; `RuntimeProjectilePhysicsUpdater`'s class doc and any "Position correction" references are re-verified against the new seam; `RuntimeEntityObjectLifetime.ClassifyRemoteAcceptedPosition`'s doc gains the kind-derivation sentence. Grep for `ApplyAuthoritativePosition` across `src/` and `docs/architecture/` and re-point every survivor. - **ISSUES.md:** none closed by this slice (#315 already closed; #316 stays OPEN and untouched). --- ## 4. Retail ground truth — verified in `acclient_2013_pseudo_c.txt` for this contract; verify again yourself | claim | where verified | status | |---|---|---| | **Retail has NO projectile-specific branch anywhere in the accepted-Position chain.** `UnpackPositionEvent` @0x004542C0 resolves the object and calls `HandleReceivedPosition` @0x00454358 with no state/kind test; `HandleReceivedPosition` @0x00453FD0's only kind branch is `arg2 != this->player` @0x0045414D; `MoveOrTeleport` @0x00516330 tests TELEPORT_TS, `this_1->cell == 0` (the body's OWN cell, read at entry), `arg4`, and `player_distance` — never `state & Missile`. A missile takes the identical remote arm. | pseudo-C lines 92896-93054 (HandleReceivedPosition), 93055-93098 (UnpackPositionEvent), 284304-284366 (MoveOrTeleport); independently confirmed twice by the 4b-3 reviews | ✓ re-read | | Teleport/cell-less branch: `teleport_hook` @0x005163EF → `SetFlags(0x1012)` @0x00516414 → `SetPosition` @0x00516420 → `return 1` @0x00516438; decided before `arg4` is read @0x0051638E | same listing | ✓ | | Near branch: `InterpolateTo(this, arg2, IsMovingTo(this))` @0x005163AF, `return 1` @0x005163BE; `IsMovingTo` @0x0050EB10 returns 0 without a `MovementManager` (a missile has none) | lines 276430-276440 | ✓ | | Far branch: `StopInterpolating` ONLY if `position_manager != 0` @0x005163C9-@0x005163CB; `SetPositionSimple(this, arg2, 1)` @0x005163D9 (builds `0x1012`); `return 1` @0x005163E8 | same listing | ✓ | | Airborne: `arg4 == 0` → `return 0` @0x0051636D — nothing written, and `ConstrainTo` skipped (it sits inside `if (MoveOrTeleport(...) != 0)` @0x00454254) | same | ✓ | | **`ConstrainTo` @0x00510520 = `MakePositionManager` @0x00510523 then `PositionManager::ConstrainTo`** — retail creates the manager on demand for a missile; the single remote arming site @0x00454272 has no kind test. So retail WOULD arm a missile's leash on any nonzero return. | lines 278353-278364 | ✓ — the basis of D-P4's recorded divergence | | `PositionManager::UseTime` ticks in `UpdateObjectInternal` @0x005159A9-@0x005159B3 for any object holding a manager — an armed missile leash would be live, not vestigial | lines 283611-283757 | ✓ | | `player_distance` is maintained for missiles: `update_object` @0x00515D10 computes `player_vector` via `Position::get_offset` @0x00515D5B and stores `player_distance` @0x00515D95 for every active unparented in-cell object. (BN artifact: the decomp shows only `.x` feeding it @0x00515D7B — the standard x87-elision of a magnitude; do NOT "fix" acdream's Euclidean distance to `.x`.) | lines 283950-284055 | ✓ | | `MoveOrTeleport`'s `arg5` (velocity) is textually unreferenced in the body; `HandleReceivedPosition` threads `arg6` into it and does nothing else with it; `UnpackPositionEvent` calls no `set_velocity` (the only `set_velocity` in the chain is the LOCAL player's zero @0x004541B4) | all three listings above | ✓ textual; **byte-verification required before landing** (D-P5) | **What this means for the design — stated plainly:** retail's CLIENT mechanically supports an authoritative missile Position (it is just the generic remote path), but the packet does not exist against ACE, and the manager machinery retail would lazily build for it does not exist in acdream for a ballistic body. Route 5 therefore anchors the placement dispositions to retail's generic remote path (faithful), and pins the manager-dependent halves (near-interpolate, leash) as a recorded acdream divergence — **a register row, not an invented retail justification** (D-P7). There is no evidence of any dedicated retail missile-Position path to port; anyone claiming otherwise must produce an address. One reporting note, out of scope but found while verifying: the remote prologue's comment at `LiveEntityNetworkUpdateController.cs:2296-2300` ("PositionPack::UnPack initializes an absent velocity to zero; MoveOrTeleport installs that exact vector with set_velocity") is contradicted by the decomp read above — `MoveOrTeleport` installs no velocity. That comment justifies the REMOTE arm's `TryCommitAuthoritativeVelocity`, which is 4a-owned and untouched by this slice; flagged for a future 4a-family correction, not acted on here. --- ## 5. What must REMAIN true (process rule 1 — for every path, including every refusal) 1. **The pose still advances on the storing partition.** A projectile placement that never reached the engine (`Refused` / `Contention` / `RejectedPreparation`) still commits the accepted destination via `StoreAcceptedDestinationPose`; `Deferred` and `RejectedByPlacement` do not. The partition is extended unchanged — not re-litigated. 2. **Presentation still advances.** On every committed/stored outcome the render entity (`Position`/`Rotation`/`ParentCellId`) and the root pose reflect the RESOLVED canonical body, and the shadow registry is synced (spatial+visible) or suspended (hidden/non-spatial) exactly per the current tail's semantics. A projectile is never left rendered a packet behind its body (#312's layer — tests must assert it). 3. **The entity stays in-world on every non-commit outcome**: `body.InWorld`, object clock active, `FullCellId` intact, spatial projection intact. No park survives the controller. 4. **Prediction invalidation accompanies every body write on this route** (placement AND store fallback), before the write; an in-flight split quantum straddling the packet aborts at `Complete`. The no-op dispositions invalidate nothing. The Vector/State channels' invalidation sites (`:241`, `:272`) are untouched. 5. **Per-quantum integration is untouched** (trap T7): `TryBeginQuantum` / `CompleteQuantum` / `AdvanceQuantum` / `CommitProjectileCell` and the scheduler's split quantum never route through `RuntimeSetPositionState`, and their allocation profile is unchanged (Slice I's 0 B/resolve discipline; the placement budget is per accepted packet, not per quantum). 6. **J5.6's ownership boundary does not regress**: the projectile component, workset, stepper, and cell commit stay in Runtime; App supplies only DAT shape resolution and retained projection/shadow/effect acknowledgements; a rejected presentation acknowledgement invalidates the pending prediction only — it never rolls back or redirects the canonical owner, and never becomes collision authority. 7. **The unified remote tail is untouched** — including `ApplyRemoteContactRouting`, `RunRemoteArmTail`, `ToConstraintArm`, `TryAdoptWireCellAfterRouting`, `ApplyWireAirborneLeftoverBookkeeping`, the TS-44 sticky gate, and the #316-preserved player `AirborneSnap` asymmetry. A missile packet never creates or writes a `RemoteMotion`. 8. **Mutual exclusion is provable** (trap T4): one `FinalPhysicsState` read per packet decides both the classifier's kind and the App's dispatch; Missile-set ⇒ projectile arm, Missile-clear ⇒ remote tail; asserted by the dual-kind theories (§7). 9. **Unhandleable missile packets are swallowed, with their bookkeeping stated positively** (trap T5 + round-2 B1): an invalid payload still fails the shared authority gate exactly as today (`CanAcceptPositionPayload` unchanged); a null/`Rejected*` classification writes nothing and falls through to NOTHING — and the test asserts what DID happen (the gate consumed the timestamps; the merge advanced the snapshot) as well as what did not. 10. **No velocity write from the Position packet**; an in-flight missile's velocity survives a velocity-less packet bit-identically (the retired zeroing defect's converse, asserted positively). 11. **Ledger convergence**: teardown, session reset, and generation change converge `RemotePlacementDrivePendingCount` (both registrations) to zero with projectile operations in flight — the same suite shape 4b-1 built, driven through the projectile arm. 12. **`ParkCollisionResidents`'s overlap throw stays unreachable** — the projectile arm adds packets to the same one-operation-per-key machinery and opens no new operation shape; restate the argument (with 4b-1's B2 stall-not-throw caveat) in the implementation commit. 13. **The lost-cell reaper gains no production caller.** 14. **The Create half and residence-window half are untouched**: the residence kind decision (`:591-595`), first-entry admission (`:311-314`), the continuation executor (including its recorded non-SetPosition trace gap at `:2019-2026` — the REMOTE half of that gap stays open and untouched), the materializer's residence-gated `TryBind` skip, and the projection-visible `TryBind` retry. 15. **`TryBind` and its create branch are NOT deleted** (trap T8) — still the live fallback for `initialResidenceActive == false` and the mid-life Missile flip; C5's deletion pass owns it. Record, don't touch. 16. **`OwnsFarSnap` / `OwnsTeleportPlacement` and the two RemoteMotion arm methods are not widened, not reused, not weakened** — their throwing guards are the loud failure mode protecting item 7. **The D4 constraint-arm partition, extended (the projectile column is the new content; the remote column is 4b-3's, unchanged and re-asserted):** | disposition (wire contact) | retail return | remote arm | projectile arm | |---|---|---|---| | `SetPosition` (teleport/cell-less, any contact) | 1 | arms, every placement outcome | **never arms** (register row) — hook reduction runs (force-end), placement + store partition run | | `SetPositionSimple` (far, grounded) | 1 | arms | **never arms** (row) — placement + store partition run | | `Interpolate` (near, grounded) | 1 | arms | **never arms, no-op** (row) | | `NoPositionOperation` (airborne) | 0 | no arm | no arm, no-op — **faithful, not a divergence** | | null / `Rejected*` | n/a | `UnroutedCatchUp` arms (grounded) / D2 shape (airborne) | **swallow — no arm, no write** (row) | --- ## 6. Proof obligations (must prove, not assume; stated in the implementation commit) - **P1 — invariant 12's unreachability argument**, restated with the B2 caveat. - **P2 — the commit-acknowledgement path.** Verify what acknowledges/retires a `ProjectileAuthoritative` commit that lands in `_awaitingAcknowledgement` (`CommittedHostAcknowledgementPending`, `RuntimeRemotePlacementDriveController:1062-1076`): either the shared projection-acknowledgement chain is kind-agnostic (state where), or the self-heal prune is the retiring mechanism (state that, and why it is acceptable — or route the ack explicitly). Do not let a projectile commit sit in a ledger dimension nothing retires. - **P3 — `RuntimeSetPositionState` kind-agnosticism.** Walk the operation lifecycle for a `ProjectileAuthoritative` operation: the two internal constructors that stamp `Kind = RemoteAuthoritative` (`:3833/:3866` window-departure park; `:5338/:5350` legacy-direct withdrawal) and any kind-conditional stage logic (`:1530`, `:5445`). Establish that none can capture, rewrite, or strand a projectile operation — or fix the stamp to carry the originating kind if one can. (A park constructor relabeling a projectile op as `RemoteAuthoritative` would silently move it between ledger columns — the T4 mis-tag shape at the operation layer.) - **P4 — the byte-decode of `MoveOrTeleport`'s `arg5`** (D-P5). - **P5 — the force-end wiring** (D-P4): one assertion that a teleport/ cell-less projectile packet empties the owner's collision table (the same cheap observable the 4b-3 round-2 review named for R2's regression risk). --- ## 7. Test plan Rules: assert the layer that historically broke (presentation, prediction, ledger — not only `InWorld`/clock); **assert positive facts, not only negatives** (round-2 finding B1 — every "writes nothing" test also asserts the two or three things that DID advance); every new test must fail against a broken implementation (no source-text pins). **The dual-KIND discipline** — this route's analog of the collapse contract's dual-guid theories, because the discriminator here is the Missile bit, not the guid range: every OnPosition-level scenario is a `[Theory]` run twice against the same packet shape — once with `FinalPhysicsState` carrying `Missile`, once without — asserting the projectile arm claimed one (projectile facts advanced; NO `RemoteMotion` exists afterward) and the remote tail claimed the other (`RemoteMotion` facts advanced; no projectile seam effect). This is what makes a future silent mis-tag fail a test. Focused Runtime tests (`tests/AcDream.Runtime.Tests`): 1. **Classification kind derivation** (D-P1): Missile-bit canonical record classifies with `OperationKind == ProjectileAuthoritative` through the production `ClassifyRemoteAcceptedPosition` entry; bit-clear classifies `RemoteAuthoritative`; same packet, same record otherwise. Plus the flip-mid-life pair (bit set after a State merge → next Position classifies Projectile; bit cleared on impact → next Position classifies Remote). 2. **`OwnsPlacement` widening**: projectile SetPosition/SetPositionSimple routes admitted; projectile Create (`InitialCreateFlags`) still excluded; remote routes unchanged (the existing OwnsPlacement expectations stay green untouched). 3. **Per-disposition seam behaviour** (D-P2), one test per row of the §5 table's projectile column: teleport/cell-less commit (body at resolved destination, cell committed canonically, collision table force-ended, prediction version advanced, tail facts per invariant 2); far commit; teleport/far refused (destination outside the service window → pose STILL advances to the accepted destination, no park retained, `InWorld`, prediction invalidated); `RejectedByPlacement` (pose does NOT move, settled pose survives); near no-op (body bit-identical, prediction version UNCHANGED — the positive fact that a straddling quantum may complete); airborne no-op (same); null/`Rejected*` swallow (nothing written; timestamps/merge advanced — positive). 4. **Prediction invalidation across a split quantum** (trap T3): begin a quantum (`TryBeginQuantum`), apply an accepted far/teleport Position through the new arm, then `CompleteQuantum` — the completion must abort (return false / not overwrite the committed placement), and the committed pose must survive. This is the test the scoping said is invisible if you only read the classifier; it must exist before the old path is deleted. 5. **No-velocity invariant**: an in-flight missile with nonzero velocity receives a velocity-less accepted far Position → body placed AND velocity bit-identical (the zeroing defect's regression test, positive form). 6. **Ledger/teardown**: proof obligation-11 suite — reset/teardown with a retained projectile preparation retry and with an awaiting-acknowledgement commit in flight; both registrations converge to zero. 7. **Constraint never armed**: after every projectile disposition, no `PositionManager`/constraint exists anywhere for the entity (and the D4 partition test for remotes is untouched). App-layer tests (`tests/AcDream.App.Tests`): 8. **The dual-kind OnPosition matrix** (above) for at least: far commit, teleport commit, near packet, airborne packet, null-classification packet. Projectile half asserts: no `RemoteMotion` created, no generic wire-pose write, no rebucket-driven bucket move beyond the canonical commit, render entity == resolved body (#312's layer), root pose updated, shadow synced/suspended per spatial state. 9. **The invalid-payload swallow** (T5): an invalid missile Position is consumed (gate/validation) and the remote tail observably did not run — asserted positively via the gate's timestamp state. 10. **Sabotage check (manual, once, before the commit is finalised)** — the collapse contract's experiment, adapted: break the seam (skip the store fallback, or skip `InvalidatePrediction`) and confirm the matrix fails on the projectile half; break the kind derivation (hardcode Remote) and confirm the dual-kind theories fail. If a sabotage survives, fix the test, not the sabotage. Existing tests: `ProjectilePosition_UsesRemoteMoveOrTeleportClassification` survives (it pins the disposition identity, which is unchanged); the `ProjectileController` position tests covering D2/D3's deleted bodies are re-expressed against the seam (not deleted as collateral — each scenario must map to a successor or be named as obsolete-with-reason in the commit). --- ## 8. Gates - **Focused**: the §7 suites, green. - **Complete Release suite**: `$env:ACDREAM_PAK_PATH = "$env:USERPROFILE\Documents\Asheron's Call\acdream.pak"`, `dotnet test AcDream.slnx -c Release -m:1`. **Baseline 11,036 passed / 4 skipped / 0 failed at `30d3d114`.** The count will rise; measure and record the new figure — do not inherit the baseline. Two known flakes, never chase and never conflate (they have been conflated twice): **#302** (`PortalProjectionTests.ClipToRegion_FrameOwnedStore_…`, GC-allocation assertion, App.Tests) and **#308** (`NakEmissionTests.LossSoak_…`, wall-clock deadline, Core.Net.Tests, full-suite load only). If either appears, re-run and say which. - **NO CONNECTED GATE EXISTS, and none is invented.** ACE never sends `UpdatePosition` for a missile (`WorldObject_Tick.cs:333-334`, commented out inside the `PhysicsState.Missile` branch at `:265`; every live `SendUpdatePosition` caller is a player/creature/pet/gamepiece/admin path). The accepted-Position half of this route is unreachable in play against ACE; deterministic tests are its ONLY gate, and this contract records that explicitly so a green connected session is never presented as evidence for it. **Optional, not a gate:** an ordinary bow/spell-bolt smoke (arrow spawns at the launch point, flies a clean arc, vanishes on impact, leaves no invisible collider at the impact point) exercises the UNTOUCHED Create/Vector/State halves and is cheap insurance against a wiring mistake in the deletion — record it as a no-regression observation if run, never as coverage for the Position half. --- ## 9. Budget and stop conditions **Budget** (scoping's figures re-validated against HEAD): ~244 raw lines deleted across the three D-sites (~180 non-comment); added — seam 60-110, kind derivation + builder plumbing 5-15, `OwnsPlacement` widening + docs ~10, App dispatch 25-50, hook-reduction wiring 10-25: **total added 110-210 non-comment production lines; net roughly flat-to-negative.** Tests are the larger share, ~400-700 lines. The collapse SHRANK the App portion versus the scoping's 40-70 (one dispatch site, not two). **Stop and report rather than pushing through when:** 1. Added production lines exceed ~300, or the design starts needing a `RemoteMotion`, `EntityPhysicsHost`, `PositionManager`, or `InterpolationManager` for a projectile — that is the 5b split this contract rejected; it does not get built ad hoc. 2. The unified remote tail, `ApplyRemoteContactRouting`, either surviving guid-conditional, `OwnsFarSnap`/`OwnsTeleportPlacement`, or either RemoteMotion arm method needs an edit beyond comment repointing. 3. Any remote-classification test changes expectation — the remote route must be byte-identical. 4. Proof obligation P3 finds an operation-lifecycle site that can capture or relabel a projectile operation. 5. P4's byte-decode finds a live `arg5` use in `MoveOrTeleport`. 6. Evidence appears that ACE (or the connected environment) DOES emit a missile `UpdatePosition` — the gate section changes and the user decides. 7. The complete Release suite deviates from baseline beyond the two named flakes. --- ## 10. What this slice does NOT do - **AP-131** (shared merge call) — C5. **AP-135** — stays, untouched (its sites are the remote tail's, which this slice does not enter). - **#276** — untouched. - **#316** — the player landing block's missing shadow publish: **OPEN, unmeasured, and must not be "fixed" here** (it lives in the remote tail's preserved asymmetry; measuring it first is its own issue's requirement). - **`ProjectileController.TryBind` + create branch** — recorded, retained; C5's deletion pass (trap T8). - **The per-quantum stepper, Vector channel, State channel** — untouched (invariants 4/5). - **No PositionManager/interpolation machinery for projectiles** (the rejected 5b) and no headless remote/projectile motion consumer. - **No changes to routes 2/3/6/7**, the local-player paths, or the continuation executor's remote trace gap. - **The remote prologue's questionable velocity comment** (`:2296-2300`, §4's reporting note) — reported, not edited; it belongs to a 4a-family correction. --- ## 11. Contradictions and stale claims versus the scoping — reported, not smoothed 1. **Every scoping file:line in `LiveEntityNetworkUpdateController` is stale** (the collapse rewrote the file): the short-circuit `:1428-1448` → `:2104-2125`; the fabricated velocity `:1442-1443` → `:2119-2120`; the `CanAcceptPositionPayload` call `:1205-1208` → `:1898-1901`; `OwnsPlacement` `:274-278` → `:520-524`; the lifetime's kind hardcode `:622` → `:642`. §1 is the corrected inventory. 2. **The scoping's central structural assumption — that route 5 rewrites call sites inside two parallel remote copies — is void.** There is one unified tail, and route 5 does not enter it at all (§2). The scoping's §8 App-rewrite estimate shrinks accordingly. 3. **The scoping under-counted the ownership fences.** It named only `OwnsPlacement` (§5.2); 4b-2/4b-3 added `OwnsFarSnap` and `OwnsTeleportPlacement` (both `RemoteAuthoritative`-gated) and two throwing, RemoteMotion-required arm methods. "The far and teleport branches have no handler the instant the short-circuit is removed" is still true, but the failure mode is now loud (throws/refusals), and the fix is a sibling seam over the shared core — not merely the ~10-line widening the scoping described. 4. **The scoping's §5.2 sequencing warning ("that file is route 4b-2's active edit surface") is spent** — 4b-2/4b-3/collapse/#315 have all landed; route 5 has the file to itself. 5. **The scoping's §1.1 claim that the classifier is "disposition-identical" for Projectile and Remote remains true at HEAD** (re-verified against the current classifier body and its pinning test) — the collapse changed the App, not the classifier. 6. **The scoping's T5 swallow concern is narrower than written**: the invalid-payload swallow largely happens UPSTREAM in the shared authority gate (`CanAcceptPositionPayload` feeds `TryAcceptPosition`, which returns before the short-circuit); D2/D3's internal `return true` swallows cover only the origin-translated-world-position and secondary-velocity checks. The invariant (no fall-through to the remote path) is pinned regardless (§5 item 9); the mechanism the scoping described was partially stale even at its own HEAD. 7. **New since the scoping and binding here:** #316 (filed by the collapse contract; carried untouched), #315's cached-callback pattern (binds new projectile wiring), and the collapse's two protected guid asymmetries. 8. **No contradiction found in the scoping's retail research** — every §2 claim re-verified (§4), including the ConstrainTo/MakePositionManager chain, the arg5 non-use (still textual-only; byte check now mandatory), and the ACE never-sends fact. The scoping's recommendation of §5.1 option 2 (record the divergence, build no machinery) is adopted and pinned (D-P4). 9. **One adjacent-comment defect found while verifying** (not in the scoping): the remote prologue's `:2296-2300` velocity justification contradicts the decomp (§4 note). Out of scope; reported.