The last C4 route. Portalling works today; route 3 removes a duplicate placement authority (LocalPlayerTeleportPlacement.Place plus headless's ResynchronizeLocalPlayerForPortalArrival), it does not fix a bug. ~225-400 added non-comment production lines, one slice. Every site re-verified at HEAD by reading, not inherited from the scoping. The authority's shape is RIGHT as-is and redesign is forbidden: RuntimePortalPlacementAuthority's 4-tuple is exactly what transit owns per reveal, and IsValid already cross-checks generation. Only the PRODUCER is missing — the campaign plan's "the adapter does not exist" overstates the gap, since consumption and validation are live production code at three layers. The producer additionally needs no new WorldRevealCoordinator exposure: it re-derives the host token through transit's idempotent TryRegisterHostProjection, which makes a superseded token unobtainable by construction. Retail's local portal arrival is the GENERIC path for the third route running: SmartBox::TeleportPlayer @0x00453910 is SetPositionSimple(player, dest, 1) with flags 0x1012 — route 2's exact primitive — plus PlayerPositionUpdated. TWO rule inversions are the contract's loudest section, because an implementer arriving from the routes just landed will otherwise carry the wrong rule: route 2's "never re-arm the leash" INVERTS (the teleport branch arms ConstrainTo @0x0045418A and zeroes velocity @0x004541B4), and 4b-3's hook-before-placement ordering INVERTS (the local teleport_hook runs AFTER placement, from PlayerPositionUpdated @0x004538AE). Three findings new since scoping: PlayerTeleported @0x006B32B0 byte-confirmed as SetAutoRun(0,1) + SendMovementEvent, with the autorun-cancel gap verified real — nothing cancels the J5.4 latch on arrival today; TryPublishPlace writes no pose, so the committed-receipt suffix is the render entity's mover; and headless TryCompletePortal's fully-synchronous suffix creates a receipt-past-EndTeleport FIFO-wedge hazard, covered by proof obligation P3. SEQUENCING BLOCKER recorded in the contract's front matter: route 7's concurrent diff modifies five route-3 surfaces. The collision is textual, not semantic — route 7 adds parent-cell machinery and touches neither the portal transit, the drive controller, nor either duplicate authority — but route 3 must not start until route 7 commits, and must then re-verify its inventory by symbol and re-measure the Release baseline. #280 is SPLIT OUT, siding with the campaign plan's own separate sequencing over the session handoff's "rides with route 3" claim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58 KiB
C4 route 3 — portal / local-player placement: pinned contract (2026-08-04)
Scope: make the local player's portal arrival canonical — construct the
first production RuntimePortalPlacementAuthority producer, execute the
deferred portal Place through a portal arm on route 2's
RuntimeAcceptedPositionDriveController over the one Runtime SetPosition
owner, re-home the controller-local teleport suffix, and delete the two
surviving duplicate placement authorities (LocalPlayerTeleportPlacement.Place
in App, ResynchronizeLocalPlayerForPortalArrival in Headless).
Route 3 is NOT a bug fix. Portalling works and is user-accepted; this route changes WHO commits the arrival, never when the player sees it. This is the LAST C4 route.
Pinned at HEAD ca96ea5e, branch claude/acdream-physics-divergence-5aa784.
Line numbers are as-of ca96ea5e and WILL go stale; every citation also
names the symbol — trust the symbol (process rule 6).
SEQUENCING BLOCKER — route 7 is concurrently in flight in this same
worktree. Its uncommitted diff modifies RuntimeSetPositionState.cs,
RuntimeAuthoritativePositionRouteClassifier.cs,
RuntimeLiveEntitySessionController.cs, RuntimeEntityObjectLifetime.cs, and
LiveEntityRuntime.cs — five of route 3's surfaces. Route 3 implementation
must not begin until route 7's commit lands. First implementation step:
re-verify §3's site inventory against the post-route-7 HEAD (symbols, not
lines) and re-measure the Release baseline. Nothing in route 7's design
conflicts with this contract (it adds parent-cell propagation and a headless
parent-realize drive; it does not touch the portal transit, the drive
controller, or either duplicate authority) — the collision is textual, not
semantic.
Predecessor documents, binding where they still apply:
2026-08-04-c4-route-3-scoping.md— the research base (committed atca96ea5e). Its §1–§5 findings, §10 trap list, and §12 open gaps are folded in below, re-verified at HEAD. Its correction of the campaign plan ("only the producer is missing") stands.2026-08-03-c4-route-2-contract.md— route 2 owns the seam this route extends. Its pins survive untouched: ack-after-commit,SendPositionImmediatelyas a route property, the ForcePosition no-re-arm rule (which INVERTS here — §4), and the #283 world-frame invariant.2026-08-04-c4-route-4b-3-contract.md— its 13 "must REMAIN true" invariants bind wherever the shared placement machinery is concerned; its hook-BEFORE-placement rule INVERTS here (§4).- The route-5 contract + its three review rounds — the defect classes this contract addresses by name: an invariant satisfied on one arm only (R3/B1/B2), a mapping written against one caller's reachable set (A2), a register row asserting behaviour the code does not have (AP-141 risk column), a retail action skipped with the faithful port in-tree (R2/A3), tests that assert only negatives (B1 round-2), presentation written on outcomes Runtime declined to publish (A1).
2026-08-04-session-handoff-c4-remaining.md— the six process rules apply verbatim. Note: its "#280 rides with route 3" is OVERRIDDEN by this contract (§12 item 1; the scoping's §7 argument).
0. Facts settled before this contract — do not re-derive
- Only the PRODUCER is missing. The portal authority's
consumption/validation side is live production code at three layers and
runs (with an empty portal) for every placement in the game:
RuntimeWorldTransitState.IsCurrentPlacementAuthority(:258-275),RuntimePlacementPresentationSink.TryApply(:100-106),HeadlessRuntimePlacementProjectionSink.TryApply(:100-110+HasValidPortalShape:112-121),LiveEntityRuntime.IsValidPortalPlacementAuthority, andBeginAcceptedPlacementCore's portal gate (RuntimeSetPositionState.cs:1528-1534). The authority is threaded through command, mover preparation, operation, and projection token already. Grep confirms zeroPresent: trueconstructions insrc/. - The surviving duplicates are exactly two:
LocalPlayerTeleportPlacement.Place(src/AcDream.App/Streaming/LocalPlayerTeleportController.cs:214-278) andHeadlessSessionWorldProjection.ResynchronizeLocalPlayerForPortalArrival(src/AcDream.Headless/Hosting/HeadlessSessionWorldProjection.cs:788-836, self-marked "TODO-C4 (route 3)"). - Retail's local portal arrival is the GENERIC path — the third route
in a row:
SmartBox::TeleportPlayer@0x00453910 isCPhysicsObj::SetPositionSimple(player, dest, 1)(flags 0x1012, route 2's exact primitive) +SmartBox::PlayerPositionUpdated(this, 1, FLT_MAX). There is no dedicated portal placement path to port; the work is wiring, ordering, and the post-placement suffix. - The classifier's LocalPlayer+TeleportAdvanced route is fully modeled and
steady-state dead (
RuntimeAuthoritativePositionRouteClassifier.cs:336-356at HEAD — the scoping's:349-368shifted under route 7's working diff):SetPositionSimple+AuthoritativeTeleportFlags+TeleportHookPhase.AfterPositionOperation+ConstrainPhase.AfterPositionOperation+ZeroVelocity: true+SendPositionImmediately: false+PreserveHeading: false+UnparentBeforeRouting: true+ApplyPlacementFrameBeforeRouting: !HasAnimations. It already encodes BOTH inversions (§4). Route 3 consumes this route; it does not invent a parallel one, and the classifier body does not change. - #280 is SPLIT OUT (scoping §7; campaign plan item 3). Not planned here,
not gated here. Route 3 keeps the Place gated on the SAME
readypredicate inLocalPlayerTeleportController.Tick:489-493, whatever radius that predicate uses. - The deferred-Place timing is the accepted architecture (J6/E5, user-gated repeatedly): retail places immediately on the accepted destination Position and blocks SIMULATION on DAT prefetch behind the portal viewport; acdream holds the PLACEMENT until reveal-readiness. Route 3 changes the executor of the Place, never its timing (trap T3). §7's register work records this.
1. Retail ground truth (verified in acclient_2013_pseudo_c.txt at scoping cff52c44; the PlayerTeleported body byte-listed for this contract; re-verify at implementation)
| claim | address | status |
|---|---|---|
F751 (SmartBox::HandlePlayerTeleport) writes exactly three flags — position_update_complete = 0, has_been_teleported = 0, waiting_for_teleport = 1 — after a wrap-safe TELEPORT_TS check. No position, no cell, no physics. |
@0x00452150 (writes @0x00452193-0x004521A7) | ✓ scoping |
HandleReceivedPosition's LOCAL teleport branch (newer_event(TELEPORT_TS) @0x0045415F): TeleportPlayer @0x00454168 → ConstrainTo(player, &var_48 /* WIRE destination */, start, max) @0x0045418A → set_velocity(player, 0, 1) @0x004541B4 → return. |
@0x00453FD0 | ✓ scoping |
SmartBox::TeleportPlayer = SetPositionSimple(player, dest, 1) @0x00453924 + PlayerPositionUpdated(this, 1, FLT_MAX) @0x00453932. SetPositionSimple(…,1) builds flags 0x1012 → generic CPhysicsObj::SetPosition. |
@0x00453910 / @0x005162B0 | ✓ scoping |
PlayerPositionUpdated teleport arm, AFTER the placement: position_update_complete = 0, waiting_for_teleport = 0 (the wait ends at PLACEMENT, not reveal), has_been_teleported = 0, teleport_hook(player) @0x004538AE, cmdinterp->PlayerTeleported() @0x004538B3, set_viewer(&player->m_position, 1) (camera reset), LScape::update_viewpoint(0), blocking CellManager::ChangePosition. |
@0x00453870 | ✓ scoping |
CommandInterpreter::PlayerTeleported @0x006B32B0 is exactly SetAutoRun(0, 1) then a tail-jump to SendMovementEvent. |
pseudo-C 699036-699042 | ✓ byte-listed for this contract |
The local hook ordering FLIPS vs the remote route: local runs teleport_hook @0x00514ED0 AFTER SetPositionSimple returns (from PlayerPositionUpdated); the remote branch runs it BEFORE SetPosition (@0x005163EF). The hook UnConstrains @0x00514F0C and HandleReceivedPosition re-arms @0x0045418A afterwards, so the leash survives. |
✓ scoping | |
CPhysicsObj::enter_world @0x00516170 is NOT on the portal path — its local-player caller is the initial-login path only (@0x00455095). Portal arrival never re-runs enter_world/HandleEnterWorld; the cell install happens inside SetPosition itself. |
caller sweep | ✓ scoping (agent-verified) |
The FORCE_POSITION branch returns @0x0045409D before every ConstrainTo — route 2's no-re-arm finding reconfirmed. The TELEPORT branch DOES arm and DOES zero velocity. |
✓ scoping | |
Retail places IMMEDIATELY on the accepted destination and blocks simulation on prefetch (blocking_for_cells; SmartBox::UseTime @0x00455410 runs only CheckPrefetchStatus) behind the portal viewport. acdream defers the PLACE to reveal-readiness — the accepted architecture (fact 6). |
@0x004559B0 / @0x00455820 | ✓ scoping |
Unverified residuals, none load-bearing (state, do not resolve): the exact
second argument of teleport_hook @0x004538AE (decompiler-elided, almost
certainly 1); CheckPrefetchStatus's apparent 5 s re-check throttle (#280's
territory); where the 0x1012 flag bits are consumed below
SetPositionInternal.
2. THE TWO INVERSIONS — read this before anything else
An implementer arriving from routes 2 and 4b-3 carries two rules that are exactly wrong on this route. Both are already encoded in the classifier's LocalPlayer-teleport branch (fact 0.4) — consume that route; do not re-derive either rule from the neighboring routes' docs.
Inversion A — route 2's "never re-arm the leash" flips
Route 2 pinned (and its seam's class doc at
RuntimeAcceptedPositionDriveController.cs:127-132 states) that the
constraint leash is NOT re-armed, because the FORCE_POSITION branch returns
@0x0045409D before every ConstrainTo. The local TELEPORT branch is the
opposite: retail arms ConstrainTo @0x0045418A — anchored at the received
wire destination (&var_48), not the resolved body position — AND zeroes
velocity @0x004541B4. The classifier carries both
(ConstrainPhase.AfterPositionOperation, ZeroVelocity: true).
An implementer who generalizes the force arm's doc comment to the portal arm
ships a leash-less teleport (the 4b-3 A1 defect class: the ABSENCE of a
re-anchor where one should exist). Also inverted versus route 2:
SendPositionImmediately is false (retail's teleport branch returns
without SendPositionEvent; the outbound tail is SendMovementEvent +
LoginComplete — §5 D-T4/T11) and PreserveHeading is false (the wire
orientation applies).
Note the anchor nuance: today's RearmConstraintLeashAtCurrentPosition
(PlayerMovementController.cs:1834-1843) anchors at _body.CellPosition —
the RESOLVED post-placement position — where retail anchors at the wire
destination. For a committed portal placement the two differ by at most the
placement adjustment (ring search/floor snap). Keep the existing shipped
anchor (the resolved position) and note it in the AD-2 amendment (§7): it is
the Campaign-P-accepted behaviour of SetPositionCore, the delta is
centimeters, and the leash anchor is write-only in the port (route-5 round-3
C1). Do NOT silently switch anchors in this slice.
Inversion B — 4b-3's "hook before placement" flips
4b-3's remote arm runs teleport_hook BEFORE the placement (@0x005163EF
before @0x00516420). The LOCAL route runs it AFTER: teleport_hook fires
from PlayerPositionUpdated @0x004538AE, after SetPositionSimple has
returned. The classifier carries the flip
(TeleportHookPhase.AfterPositionOperation local vs
BeforePositionOperation remote). Copying 4b-3's hook-first shape onto the
local arm is retail-wrong.
Also: the local "hook + suffix" is not RemoteTeleportHook. Its live
actions for the local player are the controller-local UnStick/UnConstrain
(then the Inversion-A re-arm), NotifyTeleported() (the TargetManager pair),
the PlayerTeleported port (autorun cancel + movement event — §5 D-T4), and
the camera/viewpoint resets. All of these run at or after the committed
placement, never before it.
3. Site inventory — re-verified at ca96ea5e
Sites marked [R7-flux] sit in files route 7's uncommitted diff modifies; re-verify their line numbers (symbols hold) after route 7 lands.
3.1 The duplicate authorities to delete
| # | site (symbol) | at HEAD | what it does today |
|---|---|---|---|
| D1 | LocalPlayerTeleportPlacement.Place |
LocalPlayerTeleportController.cs:214-278 (class :183-290, interface ILocalPlayerTeleportPlacement:174-181) |
_physics.Resolve(pos, cell, 0, StepUpHeight) :219 → controller.SetPosition :230 (runs the whole SetPositionCore tail, §3.4) → direct entity.SetPosition/ParentCellId/Rotation :242-244 → RebucketLiveEntity (throws on failure) :254 → _host.Host?.NotifyTeleported() :264 → SetBodyOrientation :265 → camera resets :267-268 → _spatial.Reconcile() :269 → probe/log. No Runtime transaction, no receipt, no portal authority. ~55 non-comment lines. |
| D2 | HeadlessSessionWorldProjection.ResynchronizeLocalPlayerForPortalArrival |
HeadlessSessionWorldProjection.cs:788-836 (doc :779-787) |
CenterOn → Engine.Resolve(wire, lb, 0, 100f) → Engine.ResolvePlacement(0.48f/1.835f, IsPlayer|EdgeSlide) → controller.SetPosition → SetBodyOrientation. Called from PrepareDestination:761. ~40 non-comment lines. AD-42's last surviving citation. |
3.2 The graphical drive (kept; rewired at the Place edge)
| site | at HEAD | note |
|---|---|---|
LocalPlayerTeleportController drive |
:385-789; Place edge Tick:509-533 |
ready = destination + !IsRecenterPending + _worldReveal.Evaluate(cell).IsReady (:489-493); on TeleportAnimEvent.Place: CanPlacePortalDestination preflight :514 → _placement.Place(_pendingPosition, _pendingCell, _pendingRotation) :521 → ObserveMaterialized :527 (a rubber-stamp AFTER the mutation — the structural defect this route retires). PlayExitSound → RevealWorldViewport; FireLoginComplete → EnterWorld + SendLoginComplete + Complete + ResetTransit. _pendingPosition is an App-frame-translated vector (:401) — dies with D1 (trap T4). |
| destination offer | LiveEntityNetworkUpdateController.cs:2950-2957 |
Last statement of OnPosition for a local Apply: OfferDestination(FromAcceptedPosition(update), timestamps.TeleportAdvanced). Unchanged. |
WorldRevealCoordinator |
WorldRevealCoordinator.cs; _hostProjections private (:40-62); TryBeginPortal:117-149 registers the host token |
The producer does NOT need new exposure here — §5 D-T1 pins re-derivation through the transit owner. |
| local generic render-pose write | LiveEntityNetworkUpdateController.cs:2284-2314; stale comment :2276-2277 |
Verified live at HEAD: for the local player earlyRemoteRoute is null (:2167-2175), OwnsSteadyState(null) is false (RuntimeRemoteSteadyStatePosition.cs:71-72 — both pattern-matches fail on null), so every accepted local Apply — including the portal destination Position — writes the raw wire pose onto the local player's WorldEntity AND rebuckets to the wire landblock while portal space covers the viewport. The comment "The local player never reaches this generic-remote code path at all" is FALSE. §5 D-T8 pins the handling. |
3.3 The headless portal flow [R7-flux]
RuntimeLiveEntitySessionController.TryCompletePortal (:421-510 at HEAD;
route 7 added parent-drive methods above it): TryGetAcceptedTeleportDestination
→ TryBeginPortalReveal → TryRegisterHostProjection → ack
ProjectionRegistered → PrepareDestination(generation, destination)
:450 (D2 runs here, plus PlayerState.InWorld and the readiness report) →
AcknowledgeDestinationReadiness → AcknowledgePortalMaterialized → ack
SimulationReleaseProjected → RequireDestinationReservationRelease → ack
DestinationReservationReleased → AcknowledgeWorldViewportVisible +
Complete → ack TerminalProjected → SendGameAction(LoginComplete) →
EndTeleport. The whole suffix is synchronous in one call — see §5 D-T7
for the ordering consequence.
3.4 Runtime surfaces this route builds against
| site | at HEAD | relevance |
|---|---|---|
RuntimePortalPlacementAuthority |
RuntimeSetPositionState.cs:105-119 [R7-flux] |
(bool Present, long RevealGeneration, ushort TeleportSequence, RuntimeWorldHostProjectionToken Projection) with IsEmpty/IsValid. The shape is RIGHT — no change. It is exactly the tuple RuntimeWorldTransitState owns per reveal; IsValid already requires Projection.Generation == RevealGeneration. |
| Begin/Submit portal plumbing | TryBeginExclusiveAuthoredPlacement:1444-1472 (portal param :1448); BeginAcceptedPlacementCore portal gate :1528-1534; TryPrepareAndSubmitAuthoredPlacement portal params :1826/:1886 [R7-flux] |
Begin refuses a non-empty portal unless portal.IsValid && kind is LocalAuthoritative && portal.Projection.DestinationCell == (record.Snapshot.Physics?.Position ?? record.Snapshot.Position).LandblockId — the LATEST merged Position. Transit pins the FIRST accepted destination per generation (J6.3). The mismatch edge is trap T5 / D-T5. |
RuntimeWorldTransitState |
IsTeleportActive:96, ActiveTeleportSequence:97-98, TryRegisterHostProjection:189-231 (idempotent for same generation+cell; refuses mismatch/cancelled/completed), IsCurrentPlacementAuthority:258-275, TryGetAcceptedTeleportDestination:522-527, CanPlacePortalDestination:534-541, AcknowledgePortalMaterialized:595 (requires Readiness.IsReady, refuses double-fire), IsCurrentPortalDestination:870-882 (requires active + generation + Portal kind + !cancelled + !completed + cell match; does NOT require Materialized), EndTeleport:547-556 |
The producer's complete input set exists. Note the validation-window consequence: a portal-carrying Place projection receipt fails IsCurrentPlacementAuthority once Complete/EndTeleport has run — §5 D-T6/D-T7 pin the ordering. |
RuntimeAcceptedPositionDriveController |
seam TryExecuteAcceptedLocalPosition:340-402 (ForcePosition-only gate :348); SubmitAndResolve:670-773 (does not pass portal today); ReconcileAndAcknowledge:830-840; SettlePending/_newestForce re-issue funnel; AbandonPending:312-329 (cancel + PublishCancellation) |
Route 2's landed seam. The portal arm is a SIBLING entry sharing Begin/Submit/outcome handling but NOT the force funnel (trap T7 / D-T2). |
PlayerMovementController |
SetPositionCore:1845-1920; RearmConstraintLeashAtCurrentPosition:1834-1843; CommitCanonicalForcePositionFrame:1944-1950 (the model: body write already canonical; controller-local reconciliation only) |
The single largest risk: every SetPositionCore duty must be accounted for (D-T4). |
| classifier LocalPlayer teleport branch | RuntimeAuthoritativePositionRouteClassifier.cs:336-356 [R7-flux] |
Fact 0.4. Production classify callers today: the drive controller (Force only), ClassifyRemoteAcceptedPosition, the continuation executor. Route 3 is this branch's first steady-state producer. |
RuntimePlacementPresentationSink.TryPublishPlace |
:210-241 |
Snapshots whatever the entity already holds — it writes no pose. Confirmed at HEAD (Snapshot(entity) from entity.Position/Rotation). The committed-receipt suffix must therefore write the render entity itself (D-T6); route 2's B2 coverage gap (no test drives a local-player Place through the sink to a moved WorldEntity) becomes load-bearing here and MUST close. |
SpawnPlacementSettler |
first-entry only (RuntimeLocalPlayerPhysicsPublicationState.cs:812) |
NOT invoked on the portal path; retail has no settle sweep here — contact resolves inside the SLIDE placement (trap T10). Do not add it. |
| world frame | RuntimePhysicsState.ObserveLocalWorldFrame (rebases on teleportAdvanced at merge); App LiveWorldOriginState recenters asynchronously |
The !IsRecenterPending conjunct in ready is what makes both frames agree at Place time (#283, trap T4). The canonical arm keeps that gating and resolves through Runtime's frame (resolveWorldOffsetFromRuntimeFrame: true). |
| autorun latch | RuntimeLocalPlayerMovementState.CancelAutoRun:226-234; ResetInputIntent:335-344 |
Verified gap: no portal-arrival path cancels autorun today (CancelAutoRun callers: run-lock toggle, Stop/posture commands, attack prep; ResetInputIntent only on session reset). Retail's PlayerTeleported @0x006B32B0 does. D-T4 ports it. |
3.5 What is already canonical and must not regress (J6)
RuntimeWorldTransitState owns the reveal generation, destination latch,
F751 correlation (both packet orders), materialization/simulation edge,
viewport observation, wait cue, completion/cancellation, and the 4-stage host
acknowledgement suffix (J6.2/J6.3/J6.4). Route 3 moves NONE of it. The ONLY
transit-adjacent change: AcknowledgePortalMaterialized fires from the
committed placement receipt instead of rubber-stamping after a host mutation.
The lifecycle gate's transitOwnership zero-at-stable-checkpoint discipline
(tools/run-connected-world-lifecycle-gate.ps1) covers this state.
4. What must REMAIN true (process rule 1 — for every path, including every refusal)
- Inversion A holds: on every COMMITTED portal placement the constraint
leash is armed exactly once, post-operation (
ConstrainTo@0x0045418A analog — today'sRearmConstraintLeashAtCurrentPosition, relocated into the teleport frame commit), after the hook-tailUnStick/UnConstrain; and the body velocity is zero (retail @0x004541B4 /StopCompletelyAtPhysicsObjectBoundary). The force arm's no-re-arm rule and its class doc stay force-scoped — the doc gains one sentence scoping itself to ForcePosition (process rule 6), nothing more. - Inversion B holds: no hook-family action (UnStick, UnConstrain, NotifyTeleported, autorun cancel, camera reset, input-edge reset) runs BEFORE the canonical placement on this route. The suffix runs from the committed receipt.
- The Place timing does not move (trap T3): the canonical arm executes
at each host's existing placement edge — graphical
TeleportAnimEvent.PlaceafterCanPlacePortalDestinationand the samereadypredicate; headless insidePrepareDestination's slot inTryCompletePortal. No packet-accept placement, no readiness-predicate change, noTeleportAnimSequencerchange, noWorldRevealReadinessBarrierchange (#280's territory). - On every refusal/rejection/contention outcome the player remains
presentable and the transit remains coherent: the body stays
InWorldwith an active object clock; presentation is never torn from the body (no Withdraw survives —restoreCancelledPark: trueon every cancellation,AbandonPending's exact shape); the portal viewport, wait cue, and readiness evaluation are NOT touched by the failed placement (the reveal either stays active for a retry or is cancelled through the EXISTING transit cancellation — never a half-state); and no path leaves the player permanently in portal space with a dead operation (trap T5 / D-T5). - Reveal/readiness interaction on non-commit paths — nothing changes
there: a refused placement must NOT fire
ObserveMaterialized/AcknowledgePortalMaterialized(it would assert a materialization that did not happen), must NOTRevealWorldViewport, must NOT advance the anim-event stream's terminal events, and must NOT reset the wait cue machinery. The materialization ack fires from the COMMITTED receipt only. - The pose still advances on a committed placement's presentation: after
the committed-receipt suffix, the render
WorldEntitypose == the RESOLVED canonical body pose,ParentCellId== the resolved cell, the draw bucket moved (RebucketLiveEntity), the root pose/camera reset, and the local-player collision shadow agrees (#312's layer — tests assert it). - Exactly zero outbound
AutonomousPositionevents from the portal arm, on any outcome (SendPositionImmediately: false; retail's teleport branch sends none). The outbound tail is exactly: oneSendMovementEvent-family movement refresh from thePlayerTeleportedport (D-T4), and LoginComplete at its existingFireLoginCompleteedge (T11 — unchanged; TS-28 narrowing stands; C3c's login-edge reasoning does NOT transfer). - The force arm is byte-identical:
TryExecuteAcceptedLocalPosition's gate,_newestForce,PositionEventOwed,SettlePending, and every route-2 test keep their expectations. Zero force-arm test changes is a regression tripwire. - J6 lifecycle ownership is untouched (§3.5). The 4-stage host
acknowledgement suffix, F751 correlation, destination latch, wait cue,
AD-38 viewport-retire timing, and
TeleportViewPlaneControllerdo not change. - The world-frame invariant (#283) holds: the arm submits only under
the existing
!IsRecenterPendinggating and resolves world offsets through Runtime's frame (resolveWorldOffsetFromRuntimeFrame: true). The App-translated_pendingPositionvector dies with D1; no second conversion site appears. - No settle sweep (trap T10), no allocation work (trap T9 —
once-per-teleport), no
enter_world/HandleEnterWorldadditions (retail does not run them here — §1). - Headless keeps its non-placement duties (trap T12):
PrepareDestination'sCenterOn, readiness report, andPlayerStatewrites stay host-owned;BeginTeleport'sPlayerState.PortalSpacewrite is out of scope. - Route 7's surfaces are untouched:
RuntimeEntityObjectLifetime's parent/cell propagation,EquippedChildRenderController, the headless parent-realize drive,ParentAttachmentState. If route 3 genuinely needs an edit there, STOP and report the collision — do not plan through it. - The recorded-not-consumed route facts stay recorded-not-consumed: the
LocalPlayer teleport route's
UnparentBeforeRouting/ApplyPlacementFrameBeforeRoutinghave no reader today; this slice adds no reader and does not delete the facts (4b-3's precedent).
5. Design decisions — pinned, not open for redesign
D-T1 — the producer: construct the authority from live transit facts; NO new WorldRevealCoordinator exposure
The authority's shape does not change (§3.4). Construction is pinned as:
new RuntimePortalPlacementAuthority(
Present: true,
RevealGeneration: <the active reveal generation>,
TeleportSequence: transit.ActiveTeleportSequence,
Projection: <token from transit.TryRegisterHostProjection(generation, destinationCell, out token)>)
- Graphical: generation is
_pendingRevealGeneration(LocalPlayerTeleportController:404); the host token is re-derived through the transit owner's idempotentTryRegisterHostProjection:189-231— the same generation+cell returns the existing registered token (:215-216); a stale generation, wrong cell, cancelled, or completed reveal returns FALSE. This is the safety property the scoping's open gap 3 asked for, by construction: a superseded token cannot be handed to the producer, because re-derivation refuses. On refusal the arm does not run — treat as the cancellation shape of D-T5.WorldRevealCoordinator._hostProjectionsstays private; no accessor is added. - Headless: generation,
destination.TeleportSequence, andprojectionare all already in scope insideTryCompletePortal; construct directly. - The authority is passed to BOTH
TryBeginExclusiveAuthoredPlacementandTryPrepareAndSubmitAuthoredPlacement(both already take it); Begin's gate (:1528-1534) and the sinks'IsCurrentPlacementAuthoritydo the validating. Do not add a third validation site.
D-T2 — the portal arm: a sibling entry on RuntimeAcceptedPositionDriveController, sharing the core, NOT the force funnel
New entry (name at implementer's discretion, e.g.
TryExecuteAcceptedPortalArrival(record, in route, in portal)), pinned in
behaviour:
- Preconditions: local player, canonical body present, no active
initial-Create residence, valid portal authority (D-T1), and the transit's
CanPlacePortalDestinationpreflight already passed at the caller. On any precondition failure:NotApplicable-equivalent, write nothing. - Classification: build the LocalPlayer route through the SHARED builder
with the classifier's dormant teleport branch (fact 0.4) — from the
retained accepted destination (the transit's pinned destination /
the offer's captured
TeleportAdvancedfact), never re-derived from live timestamps at the Place edge (by then no timestamp is "advancing" — the packet merged seconds ago). The classifier body does not change. - Execution:
TryBeginExclusiveAuthoredPlacement(record, version, LocalAuthoritative, portal)→TryPrepareAndSubmitAuthoredPlacement(…, portal, resolveWorldOffsetFromRuntimeFrame: true)— the same shape asSubmitAndResolve, either by extending that method with the portal pass-through (preferred if the outcome handling stays shared) or a sibling private core.route.ZeroVelocityis honored at the commit; the teleport frame commit (D-T4) runs on the committed outcome;AcknowledgePortalMaterializedfires from the committed receipt. - NOT inherited from the force arm (trap T7):
_newestForce, the re-issue funnel,PositionEventOwed,SendImmediatePosition, andSettlePending's ack semantics. ACE sends one destination per teleport; the portal route owes no AutonomousPosition; a dead-watch re-issue of a portal placement would fight the transit generation. The portal arm's non-commit outcomes route to D-T5, not to a retry marker.DeferredCellhandling MAY reuse the pending/watch machinery for the collision-generation wake (the destination was centered by the host before submit, so a park should be rare) — but its wake path must re-validate the portal authority before committing, and its cancellation must takeAbandonPending's exact shape (restoreCancelledPark: true+PublishCancellation).
D-T3 — the teleport frame commit: SetPositionCore re-homed, every duty accounted for
Under the canonical commit, the BODY write (SnapToCell) moves into
Runtime's CommitCanonical. Every OTHER SetPositionCore duty
(PlayerMovementController.cs:1845-1920) must be mapped, in the
implementation commit, to exactly one of: (a) already performed by the
canonical commit, (b) performed by the new teleport analog of
CommitCanonicalForcePositionFrame (e.g. CommitCanonicalTeleportFrame),
or (c) deliberately dropped with a retail anchor. Losing one silently is the
4b-2 round-1 defect class. The duties, enumerated:
| duty | pinned destination |
|---|---|
body snap (_body.SnapToCell) |
(a) canonical commit |
render-lerp anchor reset (_prevPhysicsPos/_currPhysicsPos) |
(b) |
UpdateCellId publication ("teleport" reason; render-root publish) |
(b) |
TransientState = Contact|OnWalkable|Active seeding |
verify (a) vs (b) — the #265/#166 check_contact family; if the canonical SLIDE placement already resolves contact, state it; if not, (b) keeps the seed. Do not drop. |
Velocity = 0 |
(b), honoring route.ZeroVelocity (retail @0x004541B4) |
StopCompletelyAtPhysicsObjectBoundary (retail StopCompletely 0x00527E40) |
(b) |
input-edge/mouse state reset (_prevForwardHeld etc.) |
(b) |
UnStick + UnConstrain + leash re-arm |
(b) — Inversion A; anchor per §2 |
_body.LastUpdateTime = 0 + _objectClock.ResetForEnterWorld() |
(b) |
NEW — PlayerTeleported port: CancelAutoRun() on the J5.4 owner + one movement-event send (SendMovementEvent family) |
(b) — retail @0x006B32B0, byte-listed §1. TWO NAMED BEHAVIOUR CHANGES (autorun now cancels on arrival; one movement refresh goes out) — call both out in the commit message, route-2 style. |
The frame commit is Runtime-owned (called from the portal arm's committed
path), exactly like CommitCanonicalForcePositionFrame. Shared private
helpers between the two commits are sanctioned; changing the force commit's
behaviour is not.
D-T4 — graphical Place edge rewrite: acknowledge, don't author
LocalPlayerTeleportPlacement.Place (D1) is deleted as an authority. The
Place edge becomes: build the authority (D-T1) → call the portal arm (D-T2)
→ on the committed receipt run the presentation suffix → ObserveMaterialized
(which now gates a mutation that already happened canonically — the
rubber-stamp inverts into a real acknowledgement). The presentation suffix,
pinned (all sourced from the RESOLVED committed body, not the wire pose):
entity.SetPosition(resolved)+entity.ParentCellId = resolvedCell+entity.Rotation+RebucketLiveEntity— the same writes D1 performs today, re-sourced as a projection of the canonical result (the sink'sTryPublishPlacewrites no pose — §3.4 — so this suffix is the render entity's mover; the sink publishes world-state/shadow/visibility from it).NotifyTeleported()(TargetManager pair), camera resets (Legacy.Update/ResetViewerToPlayer— retailset_vieweranalog),_spatial.Reconcile().- The probe line (D-T9).
Whether ILocalPlayerTeleportPlacement survives as a thin acknowledge-only
seam or is deleted and inlined into the controller is the implementer's
choice; if it survives as a trivial adapter, record it as a C5 sweep
candidate rather than deleting here.
Ordering caveat (proof obligation P2): the placement projection subscription may acknowledge the Place receipt synchronously INSIDE the SetPosition call — before this suffix runs — so the sink can snapshot the pre-suffix entity pose (the T8 wire pose). Pin the END state, not the intermediate: by the end of the Place edge every presentation surface the sink touched (world snapshot store, local-player shadow, root pose) must reflect the resolved pose. If tracing shows a surface that is written only by the sink's snapshot and never refreshed, re-publish it from the suffix — and state which in the commit.
D-T5 — refusal, rejection, contention, and the Begin cell-mismatch edge: defined, not discovered
The genuinely new edge (scoping §4): Begin validates the portal's destination cell against the LATEST merged snapshot while transit pins the FIRST accepted destination per generation. A second local Position merging between the offer and the Place edge makes Begin refuse (default token). Today benign (ACE sends one destination per teleport) — but every non-commit outcome is pinned:
| outcome | pinned behaviour |
|---|---|
| D-T1 re-derivation refuses (stale generation / cancelled / completed) | the arm does not run; the Place edge returns without mutating; the transit's own cancellation/supersession machinery (already J6-owned) is the authority on what happens next. No new cancellation path is invented. |
| Begin refuses (cell mismatch, contention, retained completion) | no body write, no presentation write, no materialization ack, no viewport change. The Place edge logs the probe line with the refusal cause and RETURNS — the anim stream stays where it is, so the NEXT Tick re-attempts the Place edge (the anim event re-fires while ready holds; verify and pin with a test — if the Place anim event is one-shot, the re-attempt must be driven by the same Tick predicate that produced it, and THAT mechanism must be stated in the commit). A permanent refusal (mismatched second destination) converges through the transit's existing supersession (the newer destination starts its own generation) or session reset — never a silent wedge in portal space. |
Contention/retryable preparation |
same visible behaviour as Begin-refusal: nothing mutates, re-attempt on a later edge/pump; any retained pending must carry the portal authority and re-validate it at wake (D-T2.4). |
DeferredCell park |
allowed through the shared machinery; the wake commit re-validates the portal authority; cancellation restores the park (restoreCancelledPark: true). The player stays in portal space (viewport intact) until the commit — which is exactly today's user-visible wait-cue behaviour. |
Rejected/cancelled after Begin |
cancel the token (CancelToken shape), write nothing, no materialization ack; same re-attempt/supersession convergence as Begin-refusal. |
| teardown / disconnect mid-transit | AbandonPending + the session reset's existing transit reset; the ledger (AcceptedPositionDrivePendingCount or the portal arm's own registration) converges to zero — asserted by the reset suite. |
The invariant across every row: the pose the player last had remains presented (portal space owns the viewport, the body did not move, and no Withdraw was published), and the transit lifecycle is exactly as J6 left it.
D-T6 — headless: PrepareDestination flips to the same arm
ResynchronizeLocalPlayerForPortalArrival (D2) is deleted.
PrepareDestination keeps CenterOn + readiness reporting + PlayerState
writes and calls the SAME portal arm (via the session controller's existing
drive access) with the authority built from the in-scope
generation/sequence/projection. Ordering pinned: the placement commits
before AcknowledgePortalMaterialized (as today — D2 runs inside
PrepareDestination, ahead of the materialization ack at :469), while the
transit is active and current, so the synchronous projection acknowledgement
inside the commit validates against a live authority. Because
TryCompletePortal then runs Complete + EndTeleport synchronously, a
portal-carrying Place receipt left unconsumed past EndTeleport fails
IsCurrentPlacementAuthority forever — proof obligation P3 establishes
that the headless sink consumes or the cancellation retires every portal
receipt before that edge, or the design adjusts (e.g. the commit's
synchronous ack is confirmed to be the only consumer headless).
The headless arm reuses the identical Runtime entry — dual-host parity is a test obligation, not an aspiration (§8).
D-T7 — the T8 second writer: tolerated, comment corrected, nothing suppressed
The local generic render-pose write + rebucket
(LiveEntityNetworkUpdateController.cs:2284-2314) KEEPS running for accepted
local Apply packets, including the portal destination Position. It is
pre-existing (AP-131/#275 territory, C5's scope), hidden behind the portal
viewport, and the committed-receipt suffix (D-T4) overwrites it with the
resolved pose. Route 3 does NOT suppress it during the teleport window —
suppression would be an unowned behaviour change on the ordinary local Apply
path. The stale comment at :2276-2277 ("The local player never reaches
this generic-remote code path at all") is corrected in this slice to state
what the code does (process rule 6). The tolerance is stated in the AD-2
amendment (D-T9) so the next reader knows the overwrite ordering is
load-bearing.
D-T8 — probe
ACDREAM_PROBE_LOCAL_TELEPORT=1, PhysicsDiagnostics-owned, TEMPORARY
family (strip with the physics-probe family). One line per portal-arrival
attempt: cause (portal/recall/admin), host (graphical/headless),
placement status, portal generation/sequence, destination cell, resolved
cell, hookTail=ran, leash=armed, autorun=cancelled. The connected gate
is a pass ONLY with probe evidence (process rule 5).
D-T9 — register, issue, and documentation bookkeeping, in the implementation commit
- AD-42 is DELETED. Its last surviving citation is D2's two-call
Resolve+ResolvePlacementsplit; the replacement is the canonical placement family (the faithful port). Register rule: the commit that ports the retail mechanism deletes the row. - AD-2 is AMENDED, not given a sibling row: add the deferred-Place
sentence — retail places immediately on the accepted destination Position
and blocks simulation on DAT prefetch (
blocking_for_cells,SmartBox::UseTime@0x00455410,CellManager::PreFetchCells@0x00455820); acdream defers the PLACEMENT itself to the reveal-ready Place edge behind the portal viewport, executed by the canonical Runtime transaction — plus the T8 overwrite-ordering note (D-T7) and the leash-anchor nuance (§2 Inversion A). This closes the scoping's open gap 1 (no existing row states the placement-timing adaptation; AD-2 is the row that owns this architecture). - The 2026-07-16 pseudocode correction LANDS IN THIS SLICE (decision on
scoping documentation defect 1):
2026-07-16-portal-completion-pseudocode.mdattributes portal arrival toenter_world(player.enter_world(destination)in its §"accepted portal destination becomes ready" listing, and theenter_worlddiscussion above it). That is the LOGIN path (@0x00455095-caller); portal arrival isSmartBox::TeleportPlayer→SetPositionSimple(§1). Add a dated correction banner citing the caller sweep; the doc's conclusion (commit the cell before releasing simulation) survives. Rationale for in-slice: it is the retail record for the exact mechanism this commit ports, and this commit's own citations contradict it — leaving it is the "a register row asserting behaviour the code does not have" class applied to a research doc. - The
:2276stale comment correction LANDS IN THIS SLICE (decision on scoping documentation defect 2) — D-T7. The behaviour itself is untouched. - The campaign plan's gap line is corrected: plan
:92-93("zero producing call sites; the adapter … does not exist") becomes a dated correction — the consumption/validation half was live before route 3; route 3 added only the producer. Same commit family as the route's docs update. - The force-arm class doc (
RuntimeAcceptedPositionDriveController.cs:127-132) gains the one force-scoping sentence (§4 item 1). - ISSUES.md: none closed by this slice. #280, #275, #316 untouched. AP-131/AP-135 untouched.
6. Proof obligations (prove, not assume; stated in the implementation commit)
- P1 — the D-T3 duty map: every
SetPositionCoreduty mapped to (a)/(b)/(c) with the contact-seeding question answered from the canonical commit's actual behaviour (readCommitCanonical's transient-state handling; do not guess). - P2 — presentation end-state (D-T4 caveat): trace every surface the
sink's
TryPublishPlacewrites for the local player (world snapshot store,_localPlayerShadow, visibility sinks) and establish each reflects the resolved pose by the end of the Place edge — or is re-published by the suffix. Name the mechanism per surface. - P3 — no wedgeable portal receipt (D-T6): walk both hosts'
projection-subscription consumption for a portal-carrying Place: establish
that the receipt is consumed while
IsCurrentPortalDestinationstill holds (synchronous ack inside the commit, or pumped beforeComplete/EndTeleport), and that every failure path (declined sink, teardown, supersession) retires it through the existing cancellation/Discard machinery. A receipt nothing can ever consume or retire is a FIFO wedge — the failure mode the sinks' own doc comments warn about. - P4 — the re-attempt mechanism on a refused Place edge (D-T5): establish
whether
TeleportAnimEvent.Placere-fires on subsequent Ticks whilereadyholds (readTeleportAnimSequencer); if it is one-shot, name and test the actual re-attempt driver. - P5 — ledger convergence: teardown, session reset, and generation
change with a portal operation in flight converge the drive's pending
count and the transit ownership counters to zero (the reset suites +
transitOwnershipcheckpoints). - P6 — the movement-event half of the
PlayerTeleportedport: confirm the outbound movement event goes through the existingLocalPlayerOutboundControllerseam with retail's shape (one refresh, reflecting the stopped post-teleport state), and that ACE accepts it without side effects (the connected gate observes the arrival stance on a second client).
7. Deletion inventory
| site | action | lines |
|---|---|---|
LocalPlayerTeleportPlacement.Place body (LocalPlayerTeleportController.cs:214-278) |
authority deleted; class rewritten to the D-T4 acknowledge suffix (or inlined; interface fate per D-T4) | ~55 non-comment deleted; suffix re-added smaller |
LocalPlayerTeleportPlacement.CellLocalForSeed (:280-289) |
dies with D1 (the App frame translation — trap T4) | ~9 |
_pendingPosition App-frame plumbing in the controller (:401, its writes in TryAimAcceptedDestination) |
replaced by the transit's retained destination (D-T2.2) | small |
HeadlessSessionWorldProjection.ResynchronizeLocalPlayerForPortalArrival (:788-836 + doc :779-787) |
deleted; PrepareDestination:761 call replaced by the portal-arm drive (D-T6) |
~40 non-comment + 9 doc |
SessionPlayerComposition.cs:888 (new LocalPlayerTeleportPlacement(...)) |
rewired to the surviving suffix shape | ~8 ctor args |
tests/AcDream.App.Tests/Streaming/LocalPlayerTeleportControllerTests.cs |
the fake-placement scenarios re-expressed against the canonical arm + suffix — each scenario maps to a successor or is named obsolete-with-reason in the commit (route-5 discipline), never dropped as collateral | audit |
| stale comments (process rule 6) | :2276-2277 (D-T7); HeadlessSessionWorldProjection:779-787 TODO block (dies with D2); the drive controller class doc force-scoping sentence; grep LocalPlayerTeleportPlacement/ResynchronizeLocalPlayerForPortalArrival across src/ + docs/architecture/ and re-point every survivor |
— |
Net: ~225-400 added non-comment production lines (Runtime portal arm
90-150; teleport frame commit 40-80 incl. the PlayerTeleported port;
graphical producer + Place rewrite 60-110; headless flip 15-30; probe ~10;
D-T1 needs no coordinator exposure so the scoping's 10-20 there drops out),
net roughly +150 to +250. Tests are the larger share (~500-900 lines).
8. Test plan
Rules: assert the layer that historically broke (presentation, transit
ownership, ledger — not only InWorld/clock); positive facts, not only
negatives; every new test must fail against a broken implementation (route-5
round-3's self-verifying-discriminator standard where staging permits).
Focused Runtime tests (tests/AcDream.Runtime.Tests):
- Producer validity: the authority built through D-T1 satisfies
IsValidandBegin's gate for the pinned destination; a stale generation, cancelled reveal, completed reveal, or wrong cell makes re-derivation refuse and the arm return without writing (positive half: the transit snapshot and body are bit-unchanged). - Committed portal placement: body at resolved destination, cell
committed canonically, velocity zero, leash armed exactly once
post-operation at the resolved anchor (count the arms — 4b-3 P3's
observable), autorun latch cleared, exactly one movement event and zero
AutonomousPosition events queued, object clock reset, input edges reset,
AcknowledgePortalMaterializedobserved by the transit (Materialized true, simulation available), probe fields. - The Begin cell-mismatch edge (T5): merge a second local Position with a different landblock between offer and Place → Begin refuses → nothing mutates, no materialization, transit still active; then the D-T5 convergence path (supersession or reset) drains the ledger to zero.
- Refusal matrix (one test per D-T5 row): refused re-derivation;
contention;
DeferredCellpark + collision-generation wake (wake re-validates the authority; commit then fires materialization); rejected after Begin; teardown mid-park (restoreCancelledParkrestores, ledger zero). Every row asserts the positive facts: body unmoved,InWorld, clock active, viewport/wait-cue state untouched, no Withdraw published. - Inversion tests, both directions: (a) the force arm still never arms (route 2's existing partition test untouched) while the portal arm always arms on commit; (b) no hook-family action runs before the canonical commit on the portal arm (observable ordering, e.g. the leash is UnConstrained-then-re-armed only after the commit's receipt).
- Dual-host parity: the headless flow (D-T6) drives the same arm; a
headless portal completion produces the same canonical body/cell/leash/
autorun/ack facts as the graphical one, and
TryCompletePortal's acknowledgement suffix still converges (P3's no-wedge property asserted: no unconsumed portal receipt survivesEndTeleport). - Ledger/reset: P5.
App-layer tests (tests/AcDream.App.Tests):
- The committed-receipt presentation suite (#312's layer + route 2's B2
closure): after a committed portal placement through the REAL sink +
suffix, the render
WorldEntityposition/rotation/ParentCellIdequal the resolved body, the draw bucket moved, the local-player shadow agrees, and the sink's Place receipt was consumed with a VALID portal authority (the portal gate finally exercised live — assert it discriminates: a stale-authority receipt is not consumed and is retired by the cancellation path, not wedged). - The T8 overwrite ordering: an accepted portal destination Apply writes the wire pose (the tolerated generic write), and the Place edge's committed suffix then overwrites with the resolved pose — asserting the END state and that the intermediate never leaks past the Place edge.
- Refused Place edge presentation: a refused arm leaves the portal viewport owning presentation, fires no materialization/reveal/exit-sound event, and the player entity is untouched (positive: the pre-teleport pose is still the presented pose).
- Sabotage check (manual, once, before finalizing): break the suffix
(skip the render-entity write) → test 8 fails; break the leash re-arm →
test 2 fails; hardcode the force route onto the portal arm
(
ConstrainPhase.None) → test 5a fails; skipCancelAutoRun→ test 2 fails. If a sabotage survives, fix the test.
9. Gates
-
Focused: §8 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,063 passed / 4 skipped / 0 failed atcff52c44. Route 7 will move this number before route 3 starts — measure the post-route-7 baseline first and record the new figure; never inherit. Two known flakes, never chase and never conflate: #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. -
Connected graphical gate (user-run, REAL and MANDATORY). Release build,
ACDREAM_RETAIL_UI=1,ACDREAM_PROBE_LOCAL_TELEPORT=1, live ACE. One session exercising, in order:- a physical outdoor portal (e.g. Holtburg portal);
- a dungeon portal (indoor destination — the EnvCell readiness path);
/lslifestone recall AND one spell recall (the F751 recall family);- an ACE admin teleport of the LOCAL player (
@teleto/@teleloc) — advances ObjectTeleport and, per the route-2 visual-gate doc, exercises exactly this route; - a same-destination revisit (ACE may omit CreateObject on revisit);
- autorun through a portal: engage autorun, walk into a portal —
arrival must be at REST (the
PlayerTeleportedport observable); - graceful close.
Pass requires ALL of (a clean-looking session is NOT a pass — process rule 5):
- one probe line per arrival with
placement=Committed, the portal generation/sequence, the resolved destination cell,leash=armed,autorun=cancelled(arrivals 1-5), and zeroRefused/Contentionlines in ordinary play; - user visual: the purple materialization silhouette without an opaque pop
or late tail (the 2026-07-25 accepted baseline), camera reset behind the
player, movement works immediately (walk out with W held — the
input-edge half), idle stance (no run-in-place), no rubber-band/tether
after arrival AND no leash absence (the probe's
leash=armedfield is the observable — do not invent a visual for it); - a second client observing an arrival sees a normal materialization and stance (P6's movement-event observable);
- the exact lifecycle/reconnect gate
(
tools/run-connected-world-lifecycle-gate.ps1) passes with everytransitOwnershipcounter zero at every stable checkpoint.
-
Headless parity gate: the K-style connected four-stop portal route (K3 closeout recipe) with the probe enabled — the same probe-line-per-arrival requirement on the no-window host, proving D2's replacement executed there.
-
Honest gap to record up front (4b-3 style): mid-transit supersession (a second teleport before the first materializes) and mid-transit disconnect are hard to provoke against ACE on demand. If the session does not produce them, record the stale-generation/cancellation behaviour as test-verified-only — never fold it into a blanket "gate passed".
10. Budget and stop conditions
Budget: ~225-400 added non-comment production lines, ONE slice (§7). Calibration: 4a 364; 4b-2 350-500; 4b-3 ~250 net; route 5 ~131.
Stop and report rather than pushing through when:
- Added production lines exceed ~500.
- The design starts needing changes to
RuntimeWorldTransitState's lifecycle semantics, theTeleportAnimSequencertimings, orWorldRevealReadinessBarrier— each is a sign #280 or a J6 regression is being smuggled in. - The Begin cell-mismatch edge (D-T5) turns out to be reachable in ordinary play (ACE double-destination) — the refusal design needs the user's eyes.
- P3 finds a portal receipt no mechanism can consume or retire — the FIFO-wedge shape changes the design, not the test.
- Route 3 needs an edit inside route 7's surfaces (§4 item 13).
- Any force-arm (route 2) test changes expectation.
- The complete Release suite deviates from the measured post-route-7 baseline beyond the two named flakes.
11. What this slice does NOT do
- #280 — split out; its own slice with its own visual gate (campaign plan item 3). The session handoff's "rides with route 3" is overridden — reported, not smoothed.
- AP-131 / #275 — the shared merge call and the ordinary local Apply path (including D-T7's tolerated generic write) stay for C5.
- AP-135, #276, #316 — untouched.
- Route 7's ownership —
RuntimeEntityObjectLifetimeparent/cell propagation,EquippedChildRenderController, headless parent drive. - AP-1/AD-1 retirement, the legacy-deletion sweep, parity tests, the
final connected matrix — C5. Surviving trivial seams
(
ILocalPlayerTeleportPlacementif reduced to an adapter, the test-onlyBeginAcceptedPlacement/BeginAuthoredPlacementwrappers) are recorded as C5 sweep candidates, not deleted here. - No headless remote consumer, no reveal-gate changes, no
presentation/anim/viewport changes, no
enter_world/HandleEnterWorldadditions, no settle sweep, no allocation work. - The leash-anchor nuance (§2 Inversion A) — kept as shipped, recorded; switching to retail's wire-destination anchor is its own decision if ever taken.
12. Contradictions and open questions — reported, not smoothed
- The session handoff vs the campaign plan on #280: the handoff says "#280 rides with [route 3]"; the plan sequences it as its own item. This contract follows the plan (scoping §7's mechanical argument: disjoint blast radii, disjoint review lenses, both changes gate the same session but share no mechanism). If the reviewer prefers the handoff's bundling, that is a scope decision for the user — the technical recommendation is SPLIT.
- The campaign plan's
:92-93("the adapter … does not exist") overstates the gap — the validation half is live production code; only the producer is missing (scoping §1.1, re-verified here). D-T9 corrects the plan line in the docs commit. - The 2026-08-02 route inventory remains wrong in the eight ways the scoping's §3 enumerated; it is a dated research record (route-5 A11 precedent: acceptable), and this contract supersedes its route-3 section.
- Scoping delta: the scoping's §8 budgeted 10-20 lines for
"
WorldRevealCoordinatorhost-token exposure"; this contract's D-T1 removes that item entirely (re-derivation through the transit's idempotentTryRegisterHostProjectionis safer — a stale token is unobtainable by construction — and needs no new surface). The scoping's classifier line range (:349-368) is already stale under route 7's working diff (:336-356atca96ea5e+ diff); symbols hold. - New since the scoping, found while pinning: (a)
CommandInterpreter::PlayerTeleported@0x006B32B0 byte-listed —SetAutoRun(0,1)+SendMovementEvent— and the autorun-cancel gap confirmed real (no arrival path cancels the J5.4 latch today), so D-T3 ports it as two named behaviour changes; (b) the sink'sTryPublishPlacewrites no pose (route-5 R3's finding re-confirmed for the LOCAL player), making the committed-receipt suffix the render entity's mover — pinned in D-T4 rather than discovered in review; (c) the headlessTryCompletePortalsuffix is fully synchronous, producing the receipt-past-EndTeleportwedge hazard P3 exists for.
Open questions routed to the reviewers:
- To the retail-conformance reviewer: (a) verify the §1 table against
the pseudo-C independently, especially the
PlayerPositionUpdatedaction order and theenter_worldcaller sweep (the load-bearing negative); (b) judge the leash-anchor nuance (§2) — resolved-position anchor kept vs retail's wire-destination anchor — is the recorded delta acceptable or should this slice switch it?; (c) confirmSendMovementEvent's outbound shape for the post-teleport refresh (P6) matches retail's (autonomy handling, stance content). - To the architecture reviewer: (a) P3's no-wedge walk on both hosts;
(b) whether the portal arm should share
SubmitAndResolve(extended with the portal pass-through) or a sibling core — pinned behaviour either way, but the sharing decision affects the force arm's blast radius; (c) the D-T5 re-attempt mechanism (P4) once read from the sequencer.