acdream/docs/plans/2026-08-02-placement-cutover.md
Erik 1b484937b6 test(physics): C4 route 6 — drops/split-recovery closure, zero production lines
Route 6 needs no production change and this commit contains none: C3c
(529e0e9d) already flipped both hosts' Create paths onto the residence lease,
so a dropped item is byte-for-byte route 1's create classification
(RuntimePositionEntityKind.Remote, RuntimeCreateResidenceKind.TopLevel,
ClassifyCreate -> SetPosition with InitialCreateFlags = Placement | Slide).
Route 6 is a SOURCE of route-1 traffic, not a route of its own. Both drop
flavours converge on LiveEntityHydrationController.OnCreate ->
RegisterEntityWithInitialResidence — the whole-item drop through
ItemInteractionController's DropToWorld (no physics, no position; the server
decides), and split-to-world through TryRecoverUnknownPosition's call to the
identical entry point. Contract:
docs/research/2026-08-04-c4-route-6-contract.md.

Retires a FALSE PREMISE from the campaign plan (:97-100), which claimed
split-recovery creates "need an effect-replay suppression signal". Verified
against the decomp instead of assumed: play_default_script @0x005132B0 /
@0x00513300 has exactly three call sites in the entire pseudo-C dump —
DefaultScriptPartHook::Execute @0x00526c08, DefaultScriptHook::Execute
@0x00526c14, and ACCWeenieObject::DoCollision @0x0058c3b4 — and NONE from
set_description or CreateObject. Neither client plays a default script at
create, so there is nothing to suppress. acdream's only create-time replay is
the F754/F755 queue drain keyed by server GUID, which is retail's own
HandleCreateObject @0x00454C80 behaviour. The plan's other two clauses were
closed at C0 (TryCommitParent/CommitWithdrawal cancellation symmetry;
host-visible cancellation receipts); the list now states what actually
remains — route 7's child-cell two-writer split and the headless
parent-realize gap.

Retail split marking recorded for the record: UIAttemptSplitTo3D @0x0058D850
stores only splitStackSize/splitClassID/splitTime and performs no placement;
DeclareValid @0x0058E340's recovery action is SetSelectedObject @0x0058E481 —
a SELECTION transfer with a 10-second expiry, not effect suppression and not
placement. UIAttemptPutIn3D @0x0058D700 records no marker at all.

Seven tests over the now-flipped path (whole item, split stack, new-GUID
recovery, second drop, unavailable destination, newer Position after the
pending identity is consumed, plus the #314 repro), each sabotage-verified:
the production path was broken on purpose, the test was confirmed to fail,
and the sabotage reverted. R6-c is now settled by assertion rather than
argument — BuildSpawn's wholesale clone of Children/Movement/AnimationFrame/
SetupTableId is measured, not reasoned about.

FOUND WHILE TESTING — #314, filed not fixed (this route is zero-production by
contract). BuildSpawn resets top-level MovementSequence/ServerControlSequence
to 0 but its Timestamps `with` block overrides only Position/Teleport/
ForcePosition/Instance, leaving Physics.Timestamps.Movement and
.ServerControlledMove at the SOURCE item's values.
HasConsistentCreateIdentityAndParent requires the two projections to agree, so
a split whose source carries nonzero Movement timestamps — plausible for any
item dropped once, picked up, and split again — fails the predicate and throws
instead of completing the canonical transaction. Verified in source, not taken
on report. Note this is a crash in the exact mechanism the scoping cited as
EVIDENCE that drops already converge: code reading said the path converges,
driving it said it throws. Fixed in the immediately following commit.

Also filed: #313 (DeclareValid's SetSelectedObject port is missing and the
container-split flavour records no marker — selection UX, deliberately not
implemented inside a placement closure) and #315 (route 4b-3's per-packet
runTeleportHook Func<bool> closure at three RunRemoteArmTail call sites; the
network packet path, not Slice I's per-frame resolve path — filed now because
route 5 adds a fourth site). AP-124 stays open and registered.

Test lines are 410 against a 150-250 guidance, accepted: the excess is a real
ItemInteractionController harness plus the #314 repro, which is what found the
defect. A mock that proved nothing would have been shorter and worthless.

Complete Release suite MEASURED at 11,020 passed / 4 skipped / 0 failed
(baseline 11,013/4/0 at 6dc7ba51; +7 new). Neither known flake fired.

Connected gate (user-run) still owed: drop a whole item, split a stack to the
ground, drop a second within ~1 m, repeat indoors and after a portal recall,
then walk two landblocks away and back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 16:45:57 +02:00

451 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Placement production cutover — campaign plan (2026-08-02)
The final leg of the remaining physics-divergence campaign before AP-22 and
AD-10: route graphical AND headless production placement through the
residence + continuation-executor owner (`38fd4b8d` / `30012361` /
`5db3de3c`), delete the legacy duplicate authorities, and retire AP-1/AD-1
behind connected + user-visual gates.
## Handoff checkpoint — 2026-08-03
**Status: stabilization checkpoint accepted; campaign closeout is not yet
complete.** The C3c production cutover and the O(changed) collision
publication checkpoint are now playable after five separately committed
root-cause fixes:
- `01f4791e` stops origin recenter from manufacturing and replaying a second
retirement receipt for a pending-only live-projection bucket. Its exact
binary passed the complete Release suite, lifecycle route, and canonical
nine-stop soak (`connected-r6-soak-20260802-204309`, nine stops, zero
failures/wait cues/pending retirements).
- `670f307c` keeps remote Create placement, the local-player physics host,
targeting, chasing, and attacks in the same world-coordinate frame. The
user accepted monster placement/chase/hit behavior and static placement
after portals.
- `1fc529cd` materializes the canonical minimal static physics host before a
distant Use/MoveTo route and reconciles the pre-PartArray startup motion
suffix. The user accepted near and distant object use.
- `f24532ad` defers one-shot F754/F755 effects until canonical placement has
bound presentation, retries projectile/static-animation sidecars on the
committed visibility edge, and keeps effect cells synchronized. The user
accepted buffs, recalls, arrows, combat spell projectiles, portals, and
static animation.
- `175ad6b0` sends LoginComplete from the local first-placement terminal edge
instead of raw PlayerCreate receipt, so ACE's intentional login Hidden/
materialization state cannot race placement. The user accepted the login
haze behavior.
Focused verification after the final fix passed 90 App effect/projectile/
static-scheduler tests, two Runtime login tests, the exact live-entity cell
tracking regression, all 79 Headless tests, and the Release solution build
with zero errors. The long connected soak and complete solution suite have
**not** been rerun on the final `175ad6b0` binary. A broader selected fixture
run also exposed five `LiveEntityRuntimeTests` failures tied to the still-open
placement cutover plus one old remote first-entry fixture that supplies an
empty collision source; classify and fix those before claiming C5 closure.
Remaining campaign work, in order:
1. Reproduce and repair the six fixture failures without weakening their
assertions or adding compatibility bypasses.
2. Finish C4's routes 27 and remove their legacy placement writers; fold in
#276 and #277 where their route becomes authoritative.
3. Resolve #280 with retail's configured destination-prefetch window so the
portal viewport never reveals visibly constructing far terrain.
4. Run C5's complete Release suite, lifecycle/reconnect route, latest-binary
nine-stop soak, two-client observation, and the remaining #269 slope-glide
visual check. A pass from `01f4791e` is evidence for that fix, not a
substitute for the final-binary soak.
5. Delete the superseded paths, retire AP-1/AD-1/AP-131 and AD-60's legacy
half only when the code proves they are gone, then complete AP-22 and
AD-10 and close the campaign ledger.
**Inputs (read in order):**
1. [`2026-08-02-runtime-continuation-executor-handoff.md`](../research/2026-08-02-runtime-continuation-executor-handoff.md)
— the completed dormant mechanism and its cutover notes.
2. [`2026-08-02-cutover-route-inventory.md`](../research/2026-08-02-cutover-route-inventory.md)
— the full 8-route, both-host call-chain inventory with exact file:line
for every duplicate authority to remove. THE map for all slices below.
3. [`2026-07-31-remaining-physics-campaign-handoff.md`](../research/2026-07-31-remaining-physics-campaign-handoff.md)
— the original per-route requirements and prerequisite definitions.
**Standing discipline per slice:** pinned contract → single implementer →
independent retail-conformance + architecture/adversarial reviews (both must
PASS on the final diff) → focused + complete Runtime + Release build +
complete solution gates → bisectable behavior commit (register rows in the
same commit) → docs/handoff commit. No workarounds; no fused slices.
## Confirmed pre-cutover gaps (from the inventory)
- The executor publishes only generic entity deltas; nothing bridges its
completion to `RuntimePlacementProjectionChannel`, so no host can learn
"my initial placement committed" through the built observer seam.
- No atomic controller/body publication owner exists (prerequisite C);
App and headless hand-write divergent `PlayerMovementController`
construction, and `SubmitPreparedPlacement` requires a canonical
`PhysicsBody` that nothing currently publishes atomically.
- The dormant placement path's 1,880 B/operation (2,048 cap) allocation
remains the activation blocker for frame-frequency routes.
- `Execute`'s live inputs (`UsePositionFromServer`, `PlayerDistance`) are
computed by no host; they must derive from Runtime's own character-option
and local-player owners.
- `RuntimePortalPlacementAuthority` has zero producing call sites; the
adapter from `RuntimeWorldTransitState` does not exist.
- The exact-Setup mover chain (`PrepareMover` /
`RuntimeSetPositionMoverPreparer.TryBuild` /
`IPreparedCollisionSource.ReadSetupCollision`) exists piecewise, unwired.
- **Corrected 2026-08-04 (C4 route 6 closure,
`docs/research/2026-08-04-c4-route-6-contract.md`): all three clauses
above were stale.** Route-6 split-recovery does NOT need an effect-replay
suppression signal — that premise was unsubstantiated; acdream's only
create-time effect replay is the F754/F755 queue drain keyed by server
GUID, and the one plausible mechanism (a cloned `DefaultScriptType`
surviving `BuildSpawn`) never fires at create in either client
(`CPhysicsObj::play_default_script @0x005132B0`/`@0x00513300` has exactly
two callers, both animation hooks, verified against
`acclient_2013_pseudo_c.txt`). Route-7's `TryCommitParent`/
`CommitWithdrawal` cancellation-symmetry fixes and host-visible
cancellation receipts were BOTH closed at C0 (see the C0 slice below).
What actually remains for route 7: the child's canonical cell has two
writers (Runtime commits it cell-less unconditionally in
`CommitAcceptedParentCellless`, while `EquippedChildRenderController
.TickChild` re-cells it from a per-frame render tick), and headless has no
`EquippedChildRenderController` at all, so every headless parented child
stays cell-less forever — the same defect seen from two sides, not two
separate gaps.
## Slices
- **C0 — Runtime bridge + live inputs — COMPLETE at `67f63e85`
(2026-08-02, dual reviews PASS).** The executor publishes an
acknowledge-only `ExecutorCompleted` receipt through the one placement
stream (registered before dispatch; correlation reaped on
acknowledgement/discard/clear; `PendingCompletionReceiptCount` in
`IsConverged`); all three production sinks acknowledge-and-ignore the
kind via early returns proven behavior-preserving for every other kind
(sanctioned seam completion — provably inert, no production publisher);
`UsePositionFromServer` derives retail-exactly from
`RuntimeCharacterState.AutonomyLevel != 2` and `PlayerDistance` from the
live movement controller with null-safe fallback to the caller struct;
`TryPrepareAndSubmitAuthoredPlacement` chains the prepared-collision
Setup read through `PrepareMover` to submission with zero validation
changes; `TryCommitParent`/`CommitWithdrawal` gained the sibling
cancellation flow (the `LeaveWorld` omission in `TryCommitParent` is
retail-REQUIRED per `set_parent` 0x00515A90:283832-283833's single gated
`leave_world`). Not fully dormant by design: the two cancellation fixes
change live Runtime paths production already calls; everything else has
no production caller.
**C3 prerequisites recorded from C0's reviews:** (a) the completion
receipt/trace surface is internal-only — C3 must define the public host
consumption shape when it wires the hosts; (b) `PlayerDistance` is
resolved once per `Execute` entry, not per continuation — a multi-Position
FIFO classifies later entries against entry-time distance (documented
deferral; refine at C3/C4 if the connected gates show it matters);
(c) any future host exposure of `TrySetAutonomyLevel` must carry retail's
`SendAutonomyLevelEvent` (699550).
- **C1 — atomic controller/body publication — SATISFIED BY EXISTING
MECHANISM (research finding 2026-08-02, plan amended same session).**
`RuntimeLocalPlayerPhysicsPublicationState` (1,033 lines) plus the
~15-method dormant local-activation family on `RuntimeSetPositionState`
already implement the full sanctioned option-2 transaction:
off-canonical preparation against a scratch quantum clock and a sealed
candidate controller, one validated atomic Commit, and a staged
Evaluate/Commit/FinalizeActivation chain re-validated against
PhysicsOwnershipEpoch/ObjectClockEpoch/ControllerOwnershipEpoch/session
identity at every entry — with zero production callers. See
[`2026-08-02-canonical-body-writer-map.md`](../research/2026-08-02-canonical-body-writer-map.md)
(6 canonical body writers; the two host escape hatches; both hosts'
divergences). The remaining work — routing both hosts' local-player
construction through the publication lifecycle, sealing the public
`RuntimeLocalPlayerMovementState.Controller` setter, retiring App's
direct object-clock bypasses, and containing headless's uncaught
prepared-collision `InvalidDataException` — IS the C3 route-1 flip and
moves there. No separate C1 commit.
- **C2 — placement allocation budget — COMPLETE at `63c601ff`
(2026-08-02, dual reviews PASS after two fix rounds).** 2,032 → 944
B/op via pooled operation envelopes (bounded, reset-at-rent, double-
retire guarded, reset/dispose-cleared, ledger-visible), a cached
collision-callback delegate over an explicit context stack, and a
non-boxing pending-head read; gate tightened to 1,536. The pooling
forced a class-wide staleness rework: captured-token-vs-fresh-lookup at
every reentrancy-spanning frame (26-site audit), hoisted stack locals
for retail's handle_all_collisions bits, token-gated bookkeeping
writes, and a deliberately identity-agnostic settle path (retail's
SetPositionInternal completes unconditionally even for displaced
operations).
**Residual floor (documented at the gate, decision deferred to the C3
activation gate where the user is in the loop):** ~520 B/op inside
Core's `PhysicsEngine.SetPosition` (transition init / query-footprint
materialization — a potential C2b if C3's connected profile shows it
matters) and ~208 B/op of sorted-tree node per pending receipt.
**Maintenance notes from review (no action):** the no-reentrancy
proofs on the 15 surviving reference-based currency checks are
comment-enforced; `IsCurrent(Operation)` remains available and a new
reentrancy-spanning call site would silently inherit the tautology —
its doc comment warns.
- **C3 — spawn-frequency cutover: routes 1 + 8 — DECOMPOSED 2026-08-02
after the first implementation pass stopped with findings.** C3-1 (the
public executor-completion surface via
`RuntimePlacementProjectionChannel.TryGetInitialCreateCompletion`)
landed separately. Two structural gaps halted the flip, both real and
neither in the planning docs:
**(B)** the local player's residence lease opens its SetPosition
operation at Create time, but `SubmitPreparedPlacementCore` requires a
pre-existing canonical body that only the zero-caller publication chain
can attach — first-entry needs an explicit resumable sequence
(begin-placement → publication Prepare/Commit attaches the body →
authored-mover submit → Place receipt → Execute), which matches the
campaign handoff's route-1 required order but exists nowhere as a
driveable state machine;
**(C)** ordinary remote-creature Creates classify to `SetPosition` but
have NO production body-construction path at Create time (bodies arrive
with first motion today; retail constructs physics at CreateObject via
`ACCObjectMaint::CreateObject`/`set_description`, which our retail
notes fully document — the defaults come from the wire PhysicsDesc,
not invention).
Sub-slices, each with the standing contract/dual-review/gate
discipline:
- **C3a — Runtime first-entry sequencing — COMPLETE at `960373df`
(2026-08-02, dual reviews PASS).** `RuntimeLocalPlayerFirstEntryState`:
five stages (mover-prep → publication Prepare/Commit → activation →
acknowledgement → Execute) in retail's own order — mover shapes
BEFORE placement, matching makeObject/set_description preceding
enter_world; the original contract prose had it backwards and the
tested preconditions forced the faithful order. Acknowledge-stage
authority discrimination, automatic convergence through the (now
multicast, snapshot-iterated) retirement fan-out, ownership-ledger
fold, transactional late-bind Publication seam. Dormant: C3c's first
act is the GameRuntime binding + production Advance drive.
**Carried findings for C3c:** the controller is live from the
activation commit onward (abandonment leaves it to ordinary entity
teardown — retail has no entry-flow rollback); EvaluateActivation's
post-commit DeferredCell overload is encapsulated behind Advance.
- **C3b — remote body construction at Create — COMPLETE at `0934a121`
(2026-08-02, dual reviews PASS).** `RuntimeRemoteBodyDescription` +
`RuntimeRemoteFirstEntryState`: the full `set_description` order with
the byte-certain gates (friction [0,1] inclusive, NaN sanctioned-skip;
elasticity clamp with retail's unordered-to-zero; translucency
!= 0.0f), the movement-branch discriminator on retail's
`movement_buffer != 0` (empty-buffer → placement branch, no autonomy),
motion-table zero-id pass, ctor-defaults for absent wire fields, and
never-clobber coexistence with the build-at-first-motion production
path. The acknowledge discriminator is one shared body
(`RuntimeFirstEntryAcknowledgement`) for both conductors. Dormant.
- **C3c — the host flips (production) — COMPLETE at `529e0e9d`
(2026-08-02, dual Opus reviews: initial FAIL 2+2 MAJOR → R1 fix
round → delta PASS both).** Both hosts register initial Creates
through residence + conductors via the shared
`RuntimeFirstEntryDriveController`; Controller setter sealed;
rebucketing presentation-only strictly while the residence is
ACTIVE (post-residence entities take the full legacy path including
the `prepare_to_enter_world` clock edges); content-less headless
keeps pre-flip direct registration. Five fix slices landed inside
the cutover, each connected-gated: F1 (Runtime ownership seam for
movement stats/server physics — the post-logout retired-controller
crash), F2 (the login activation wedge: admission-prefix gate
factored from the seal, rearm generation identity, auto-entry
requires the published controller), F3 (landblock-prefix 0-sentinel
→ explicit absent-id; corner landblocks legal), F4 (diagnosis only:
the nine-stop soak's convergence failure is pre-existing `6b28ff99`
whole-world collision-clone throughput — its fix is the next slice
before C5), F5 (local-player first-entry ground contact via the
shared `SpawnPlacementSettler` at `FinalizeActivation`; the
standing-cast airborne rejections are gone; register AD-61). R1
additionally armed the login constraint leash at the committed
placement (`HandleReceivedPosition` 0x00453FD0 analog) and
refreshed AD-42. Final gates: complete solution 10,816/0/4 skips;
lifecycle/reconnect gate PASS (`connected-world-gate-20260802-
175401`). Closeout:
[`2026-08-02-c3c-cutover-closeout.md`](../research/2026-08-02-c3c-cutover-closeout.md).
**Carried to C4/C5:** route-1 far-Create service-window conversion
if either streaming/broadcast radius changes (#277); the
window-departure park narrowing; `NotifyRetirement`-on-active-entry
subscriber invariant; the reachable equip-mid-conductor fail-fast;
settle-CellId discard (#276-adjacent, see ISSUES).
- **C4 — remaining routes: 2 (ForcePosition), 3 (portal, with the
`RuntimeWorldTransitState``RuntimePortalPlacementAuthority` adapter),
4 (remote Create/Position; delete `RemoteTeleportController`/`Placement`
and the inline MoveOrTeleport duplicate), 5 (projectile authoritative),
6 (drops + split-recovery marking), 7 (residual pickup/parent/delete
polish). — route 2 COMPLETE AND USER-ACCEPTED 2026-08-03 (`9966b531`);
routes 3/4/5/6/7 remain OPEN.**
**Route 4 SPLIT into 4a and 4b (user-directed 2026-08-03).** Scoping
([`2026-08-03-c4-route-4-scoping.md`](../research/2026-08-03-c4-route-4-scoping.md))
put whole-route 4 at 1,500-2,500 production lines against a stated ~400
budget, so it is split to keep each landing reviewable:
- **4a — the steady state.** The classifier's `Interpolate` (contact,
`PlayerDistance < 96 m`) and `NoPositionOperation` (no contact) branches.
NEITHER runs a `SetPosition`, so 4a has no deferred-cell park, no
service-window work, and no placement-allocation exposure. Fixes two of the
three unfiled divergences (the NPC airborne hard-snap that ignores the wire
`IsGrounded` bit; `ConstrainTo` armed before the operation instead of
after). Highest visible value — this is what makes creatures move smoothly.
- **4b — the edges.** `SetPosition` / `SetPositionSimple`: teleport, far-snap
(>= 96 m), and cell-less first placement. This is where the parks, the
Position-time service-window guard, #277's broken bound, N3 (headless never
calls `RetryPending`), and the third divergence (`ConstrainTo` never armed
on the remote teleport branch) all live.
**4b also inherits 4a's ownership remainder — scheduled here, not implied
by code comments.** Two independent reviews flagged that 4a satisfies
contract items 1 and 2 only partially, and the plan must carry that rather
than leaving it in `// 4b deletes this fallback` comments:
- Runtime owns the classification, the request construction (one shared
builder, `RuntimeAcceptedPositionRouteRequests`), the near-InterpolateTo
decision with AP-87, and the post-operation `ConstrainTo`. **App still
owns** branch selection, the airborne early return, the
`RemoteMotion.CellId` write, the `WorldEntity` pose write, and the
collision-shadow publish — all in `LiveEntityNetworkUpdateController`.
- Item 2 ("both hosts drive the identical Runtime entry point") is
satisfied only VACUOUSLY: `RuntimeLiveEntitySessionController` returns
early for remotes, so no no-window host exercises this path at all and
nothing can diverge yet. That stops being true the moment a headless
host needs remote motion.
- Every legacy fallback 4a deliberately left in place is 4b's to delete:
the pre-operation unconditional `ConstrainTo`, the player arm's
`!update.IsGrounded` no-op, the player and NPC legacy near/far routing
(each still carrying its own duplicate `96f` / `4f` constants), and the
airborne-precedence carve-out
(`LiveEntityNetworkUpdateController.ApplyRemoteContactRouting`) that
keeps a landing body snapping. Retiring the last one is a real behaviour
decision — retail makes no player/NPC distinction there — and needs its
own live evidence, not a silent convergence.
- Register row **AP-135** (the airborne no-op's retained acdream
bookkeeping: the server cell id for the free-fall sweep gate, and the
last-server-position sample) — **CORRECTED 2026-08-04: this row does NOT
retire with 4b.** Its own stated condition is retirement together with the
free-fall sweep gate (`RuntimeRemotePhysicsUpdater.cs:342`), which 4b does
not touch, and its sites are the airborne no-op branches — 4a-owned
dispositions, not 4b's far-snap/teleport/cell-less. The trap is that those
two writes sit physically inside `OnPosition`, which 4b rewrites heavily,
so an implementer will assume they go. They stay. See
[`2026-08-04-c4-route-4b-scoping-and-split.md`](../research/2026-08-04-c4-route-4b-scoping-and-split.md).
- **4b is itself split into 4b-1 / 4b-2 / 4b-3** (2026-08-04). Scoping put
4b at 1,300-2,200 production lines — 4-6x route 4a — plus ~2,500-3,500
lines of test work. 4b-1 is infrastructure with no remote behaviour change
(the per-entity placement owner, the service-window guard, the
refuse-rather-than-park policy, N3's headless `RetryPending` pump); 4b-2 is
the far branch alone; 4b-3 is teleport/cell-less and the ~739-line class
deletions. 4b-1 stays a separate landing regardless: it is where the
park-withdraws-the-entity failure mode is decided, and it must not be
reviewed alongside a large deletion.
- **4b-2 LANDED at `7f1c1f5a` (2026-08-04); far-snap connected gate
USER-PASSED same day.** Four fix rounds, eight Opus reviews; the slice was
fully green at 10,990 / 10,997 / 11,004 while containing real defects
(a frozen remote pinned as correct by its own test; a fallback that
over-wrote on the exact retail paths that decline to store; a park guard
incomplete on two independent axes). Final suite 11,009 / 4 / 0 against a
**measured** 10,968 baseline — the 10,973 figure used earlier was wrong.
Its real yield was a defect under routes 1 and 2, not the far snap:
`ParkDeferred`'s quiescence parks withdrew the entity and were never
restorable while `Forget(restoreCancelledPark: true)` runs for every
accepted Position on every entity. The restorable decision now lives
inside `ParkDeferred` after `SnapToCell`, read against every live
quiescence.
**Still outstanding: #309.** The `ACDREAM_PROBE_PARK=1` capture from the
accepting session shows 11 parks, all `cause=unplaceable` — zero
quiescence-cause parks, so the shared-core park change is NOT yet
connected-verified. Without the probe that session would have been
recorded as a pass.
Process lesson recorded: the round-1 defect was caused by the contract
omitting "and still advance the pose", and the park defect should have
been split into its own slice the moment it surfaced in round 2 instead
of riding inside 4b-2 for three more rounds.
Findings chain:
[contract](../research/2026-08-04-c4-route-4b-2-contract.md) →
[round 1](../research/2026-08-04-c4-route-4b-2-review-findings.md) →
[round 2](../research/2026-08-04-c4-route-4b-2-delta-review-findings.md) →
[round 3](../research/2026-08-04-c4-route-4b-2-round3-correction.md) →
[round 4](../research/2026-08-04-c4-route-4b-2-round4-correction.md).
Note the route-4 Create half is ALREADY DONE (C3b/C3c); the remaining work is
steady-state remote Position plus the deletions. AP-131 is NOT retired by
either sub-slice — see the scoping doc for why route 4 alone cannot.
4a contract: [`2026-08-03-c4-route-4a-contract.md`](../research/2026-08-03-c4-route-4a-contract.md).
**Route 2 connected gate PASSED (user, 2026-08-03).** Provoked with the
retail `@pklite` entry-collision bump (`69ba9486` — the only reachable ACE
trigger for `ObjectForcePosition`; admin teleports advance `ObjectTeleport`
and exercise route 3 instead, see
[`2026-08-03-c4-route-2-visual-gate.md`](../research/2026-08-03-c4-route-2-visual-gate.md)).
The user observed the visible slide off the overlapped character (the
ForcePosition applied), correct animation, no heading change, and no leash
tethering or rubber-band after the correction — so the two named behaviour
changes (ack after commit; no `ConstrainTo` re-arm on this route) are
accepted live. Both Opus reviews PASS on the final diff after three FAIL
rounds.
**Adjacent, NOT a route 2 regression:** shipping `@pklite` made PK Lite
reachable for the first time and immediately exposed pre-existing PvP gaps —
melee/ranged attacks refuse a PKLite target (auto-target retargets to the
nearest other; auto-target off does nothing) while spells on the same target
work. Under investigation; filed separately.
**Route 2 (ForcePosition) — implemented 2026-08-03, contract:**
[`2026-08-03-c4-route-2-contract.md`](../research/2026-08-03-c4-route-2-contract.md),
**plan:** [`2026-08-03-c4-route-2-implementation-plan.md`](../research/2026-08-03-c4-route-2-implementation-plan.md).
`RuntimeAcceptedPositionDriveController`
(`src/AcDream.Runtime/Session/RuntimeAcceptedPositionDriveController.cs`)
is the single accepted-Position execution seam for a ForcePosition on the
already-live local player; `LocalForcePositionTransaction` and
`HeadlessSessionWorldProjection.BlipLocalPlayer` are deleted, and the
generic App render-tail is skipped for the local player's ForcePosition.
Named behaviour changes (both retail-exact, ISSUES #285): the outbound
ack now fires strictly after the canonical commit, and the constraint
leash is no longer re-armed on this route (retail's FORCE_POSITION branch
never reaches `ConstrainTo`).
**Fix round (2026-08-03):** both independent dual reviews (retail-
conformance + architecture/adversarial) FAILed the first pass — see
[`2026-08-03-c4-route-2-review-findings.md`](../research/2026-08-03-c4-route-2-review-findings.md)
for the full R1-R9 list. The critical finding (R1) was that the
DeferredCell park could not survive a single ACE broadcast interval in
production (`RuntimeEntityObjectLifetime.TryApplyPosition`'s unconditional
`Forget` on every accepted Position cancelled it before its collision
generation could commit), silently dropping the correction forever;
`RuntimeAcceptedPositionDriveController.Advance` now detects the dead
watch and re-issues from the entity's current canonical snapshot. R2/R3
restored headless's collision re-centering and login-window fallback; R4
stopped the force-ack from stealing a receipt the presentation sink had
legitimately declined; R5/R6/R9 corrected false doc claims, closed a
`_pending`-leak/overwrite gap, and fixed streaming-observer/pose-dirty
side effects firing on a declined placement. R7 corrected a fixture bug
(a dummy Setup sphere with its centre at the origin) that had been
written up as a retail fidelity gain; R8 added App-layer double-write
source pins and corrected an overclaimed single-ack test. Full detail:
[`2026-08-03-c4-route-2-review-findings.md`](../research/2026-08-03-c4-route-2-review-findings.md).
Complete Release solution after the fix round: **10,853 passed / 4
skipped / 0 failed** (baseline 10,844/4/0; first pass 10,848/4/0).
**Acceptance item 2 is NOT met — recorded gap, B2 (2026-08-03 round 2).**
An earlier revision of this paragraph claimed R8 "added the App-layer
double-write source pins the plan's own acceptance item required". That was
a claim of coverage this changeset does not have, and it is corrected here
rather than left as the citation a future session trusts (same rule that
produced R7). The truth, per the adversarial review:
- *First half — "the generic tail no longer double-writes the local
player":* **source-pinned, not proven.** The pin is a regex/`Assert.Single`
over `LiveEntityNetworkUpdateController`'s source text, so it would still
pass if a second write were spelled differently, and **no test exercises
the branch** at runtime.
- *Second half — "the committed projection is what moves the render
entity":* **uncovered at any layer.** No test drives a route-2
ForcePosition through `RuntimePlacementPresentationSink` /
`TryApplyRuntimePlacementPlace` and asserts the `WorldEntity` actually
moved. Given R4 (the force-ack no longer consumes a declined `Place`),
this is precisely the seam whose failure mode is silent: the canonical
body moves and the render entity stays put.
Closing this gap needs an App-layer test that runs the accepted
ForcePosition end to end and asserts the render entity's position/cell came
from the committed placement receipt — carry it into C5's parity tests or
file it before this sub-landing closes.
**Not yet done:** both reviews must be RE-RUN on this fixed diff, and the
connected (user-gated) acceptance gate this campaign's standing
discipline requires, before this sub-landing is considered closed — those,
and the commit itself, are next. May land as more than one commit if a
route proves large; each sub-landing keeps the full review discipline.
- **C5 — legacy deletion + closeout gates — OPEN.** Delete every superseded legacy
path; parity tests; exact lifecycle/reconnect + canonical nine-stop
connected routes; two-client observation; **user visual matrix** (the
campaign's stopping point for user acceptance). Retire AP-1, AD-1,
AP-131, AD-60's legacy half, and close #275. Update register/roadmap/
milestones/architecture/memory + successor handoff.
After C5: AP-22 (authored collision shapes), then AD-10 (remote
contact-plane projection), then the campaign's final matrix and ledger
closeout; vendor Slice 5 resumes.