acdream/docs/research/2026-08-02-runtime-continuation-executor-handoff.md
Erik 9ad590dcc7 docs(physics): hand off placement continuation executor
Synchronize the architecture doc, milestones, roadmap, and ISSUES with the
continuation-executor behavior commit (5db3de3c): the residence system is
now a complete dormant mechanism, both independent reviews PASS, and the
next boundary is the all-host production cutover. The admission handoff
gains its superseded banner; the successor handoff records the executor's
ownership, the retail anchors proven during review (the wire-contact gate,
queue-by-parent-GUID relation replay, HasAnims semantics), the seven new
register rows, exact test totals, the rollback command, and the cutover
checklist. #275 filed for the post-cutover legacy-Position unification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 03:52:30 +02:00

11 KiB

Runtime initial-placement continuation executor handoff - 2026-08-02

Purpose and exact stopping point

Behavior commit 5db3de3c7ab2c6350d11af7f34b852464fc1e0f9 implements the Runtime continuation executor: the missing mechanism that, once an entity's initial authored placement is acknowledged, adopts that placement exactly once, applies the retail Create tail, replays deferred missing-parent work, and drains the admission checkpoint's mixed continuation FIFO in exact arrival order with retail route decisions made at execution time. The residence system built by 38fd4b8d (residence/FIFO) and 30012361 (admission) is now COMPLETE as a mechanism: an entity can enter the world through it and every packet accepted while its placement was pending is applied exactly once, in order, with retail semantics.

This checkpoint deliberately does NOT cut the graphical or headless production routes over — RuntimeLiveEntitySessionController.cs (headless) and App's LiveEntityRuntime still call legacy RegisterEntity, and no host calls Execute. It does not begin AP-22 or AD-10 and does not retire AP-1/AD-1. The executor is exercised by deterministic Runtime tests only, so no connected visual gate was required.

This file supersedes the executor-boundary portions of 2026-08-01-runtime-initial-placement-admission-handoff.md.

Exact workspace and Git state

  • Worktree: C:\Users\erikn\.codex\worktrees\af5e\acdream
  • Branch: codex/port-claude-agents
  • Behavior checkpoint: 5db3de3c7ab2c6350d11af7f34b852464fc1e0f9
  • Documentation checkpoint: the commit containing this file
  • The same eight unrelated dirty paths as the admission handoff remain intentionally unstaged; never stage by blanket.
  • No push or merge is part of this checkpoint.

What the executor owns

RuntimeInitialCreateContinuationExecutor (constructed inside RuntimeEntityObjectLifetime beside the residence state; internal InitialCreateExecution; generation bound through BindEventContext) owns, per exact RuntimeEntityKey + lease:

  • the synchronous, retry-idempotent Execute transaction: Complete -> AdoptCompletedPlacement (consumes the acknowledged initial placement exactly once, resolving the HasRetainedCompletion deadlock so later authored placements for the key can begin, with PlacementAdopted keeping the completed entry current) -> AfterEnterWorld hook request (local player, exactly once) -> deferred replay -> strict-sequence FIFO drain -> ConsumeExecuted release (adoption-revision-checked; Revised re-drains only the tail);
  • per-continuation applies through gate-less instance seams on InboundPhysicsStateController (ApplyAccepted*Snapshot) that read and write the ONE snapshot store — the legacy fused paths are re-expressed as gate + the same shared merge bodies, so there is no drift and no second canonical snapshot;
  • execution-time Position routing via RuntimeAuthoritativePositionRouteClassifier.ClassifyAcceptedPosition with live inputs: the retained wire packet's own IsGrounded bit as the server-asserted contact (never the local body), the data-driven (MotionTableId ?? Physics?.MotionTableId) animation proxy (AP-130), live distance/UsePositionFromServer, and the record's committed cell — driving authored placements for SetPosition routes through the canonical RuntimeSetPositionState Begin/Watch/resume lifecycle with a retryable AwaitingContinuationPlacement yield (a contention flavor with no pending token means "retry Execute later");
  • atomic SameIncarnationCreate envelopes: per-stage index idempotency, buffered publication flushed in stage order after the final stage (AD-59), the object-table apply via the accepted-spawn seam (result observed; a nested replacement abandons), and the three-branch resident-cell disposition (TS-63);
  • missing-parent replay, both flavors, keyed by parent GUID exactly as retail's QueueBlobForObject/ProcessObjectNetBlobs: raw child Creates AND queued accepted parent relations, drained in the initial tail with whole-bucket atomic detach, per-entry exception containment (ReplayFailureCount/LastReplayFailure), typed outcomes (Registered/ReDeferred/Rejected; ParentApplied/DeferredAwaitingParent/ DiscardedStaleParent), and cancellation-aware restore windows whose tokens record every cancellation fired while a batch is detached (ABA-safe; a cleared token restores nothing);
  • the field-masked executor baseline: each apply re-syncs ONLY the tracked fields its own mutations moved, before publication, so external mutations are detected in every quiet window and publish-callback;
  • one shared abandonment routine on every non-retryable exit: forgets any pending continuation placement (cancellation published), retires the residence through the lifetime choke point, discards progress, returns a typed status — the combined ownership ledger (residences, executor progress, deferred buckets, replay windows, placement watches) converges, and residence retirement notifies the executor (BindRetirementNotification);
  • an ordered immutable execution receipt/trace carrying every fact a cutover host needs: per-action kind/sequence/stage, Position route facts (disposition, constrain phase, teleport-hook phase, stop-interpolation, zero-velocity, preserve-heading, send-position-immediately, unparent), replay outcomes, and resident-cell dispositions.

Retail anchors proven this slice

Beyond the admission handoff's eight anchor functions:

  • retail's local-ordinary interpolate gate is UsePositionFromServer && wire-contactPositionPack bit 0x4 → has_contact (pseudo-C 284654) → UnpackPositionEvent arg5 (93092) → the gate at 93044. The earlier research note's "isForce" reading was a misnomer disproven during review; the shipped classifier was correct.
  • ProcessObjectNetBlobs detaches the whole per-GUID bucket before dispatching (93617 → 93649) — mirrored by the detach/restore windows.
  • missing-parent relations are QUEUED by parent GUID (standalone parent handler 0x004535D0: lookup 92312, queue 92326; QueueBlobForObject 0x005092D0's GUID-keyed placeholder bucket 271082-271088) — never discarded; the round-4 discard was overturned on this evidence.
  • HandleReceivedPosition's HasAnims gate (92992) is animation-queue presence (CSequence::has_anims = non-empty list), anchoring AP-130.
  • the same-incarnation tail order and resident-cell cleanup (93865..93943) are mirrored stage-for-stage, with the claimedCell==0 destruction branch proven structurally unreachable for admitted envelopes (every envelope carries a WeenieDescription by shape).

Divergence register

Rows filed in the behavior commit: AD-59 (envelope buffered live-record events), AD-60 (executor canonical cell semantics — wire positions never directly commit residency), AP-130 (HasAnims MotionTableId proxy), AP-131 (legacy Position merge's unconditional placement-frame/parent- clear flags — retired by construction at cutover), AP-132 (parent incarnation gating vs retail's pointer-only GUID replay), TS-62 (no live ConstrainTo binding in the dormant slice — trace-only), TS-63 (resident-cell abandonment/delegation split). AP-1 and AD-1 remain open until the cutover. Issue #275 tracks the post-cutover unification of the legacy Position path onto the classifier.

Validation

  • Focused executor/residence/classifier gate: 161/161.
  • Complete Runtime project: 903/903 (829 baseline + 74 slice tests).
  • Complete Release solution: 10,696 passed / 4 intentional skips / 0 failed (-m:1, installed acdream.pak); Release build 0 errors, 21 pre-existing test-project warnings.
  • git diff --check clean; the eight unrelated dirty paths untouched.
  • Independent reviews (both read-only, both required to PASS): the retail-conformance reviewer and the architecture/adversarial reviewer each ran four passes across five implementation rounds. Finding classes fixed at root cause along the way: wire-vs-body contact source; two-store snapshot divergence; WeenieDescription wholesale-overwrite; non-converging abandonment; reentrant mid-drain residence retirement; the acknowledged-completion leak that would have blocked all future placements for a key; per-field baseline blessing; replay exception containment and detached-batch resurrection; and the stale-parent discard overturned in favor of retail's queue-by-parent-GUID replay. Final verdicts: RETAIL REVIEW: PASS; ARCHITECTURE REVIEW: PASS (three residual NOTEs, all defense-in-depth observations, none blocking).

Production routes intentionally unchanged

Graphical Create still flows through LiveEntityRuntime.RegisterEntity; headless still uses RuntimeLiveEntitySessionController's legacy RegisterEntity; no production code calls RegisterEntityWithInitialResidence or Execute. The residence+executor system is a complete, reviewed, dormant mechanism awaiting the cutover.

Next implementation boundary — the production cutover

Route graphical AND headless registration through the residence+executor owner together, then every Create, Position, ForcePosition, Parent, Pickup, withdrawal, delete, remote-movement, projectile-correction, and dropped-item edge through the same transaction. Hosts project immutable Runtime results only; they may not resolve a second placement or create another body. Delete the legacy duplicate paths only after parity tests pass (this retires AP-131 and closes #275 by construction). Run the exact lifecycle/reconnect and canonical nine-stop connected routes, two-client observation, and the user visual matrix. Only then retire AP-1 and AD-1.

Cutover-specific notes from this slice:

  • The execution receipt carries every route fact a host must bind — the constrain phases and stop-interpolation/zero-velocity flags (TS-62), the teleport-hook phases, and the send-position-immediately echo.
  • AwaitingContinuationPlacement has two flavors: pending token (host must prepare/submit/acknowledge the placement, then retry Execute) and contention (no pending token; retry Execute after the conflicting operation resolves).
  • The dormant placement path's 1,880-bytes/operation allocation budget (2,048 cap) remains the standing 4B2 activation blocker for frame-frequency traffic; resolve or budget it before the cutover routes high-frequency Position traffic through the owner.

After the cutover: AP-22 (authored collision shapes; ShadowShapeBuilder sole authority), then AD-10 (remote contact-plane projection), then the final automated + connected matrix and ledger synchronization close the campaign; vendor Slice 5 resumes after.

Rollback

git revert 5db3de3c7ab2c6350d11af7f34b852464fc1e0f9

The documentation checkpoint containing this file is separate and may be reverted independently. Do not revert the 38fd4b8d/30012361 foundation beneath it without a separately proven defect.

Resume checklist

  1. Continue in the exact worktree/branch above; confirm git log contains 5db3de3c and the documentation commit containing this file.
  2. Preserve the eight unrelated dirty paths; never git add -A.
  3. Read this file, the admission handoff, and docs/architecture/acdream-architecture.md.
  4. Re-run the focused gate before modifying execution code: the Residence + Classifier + Executor filter must report 161/161.
  5. Begin ONLY the production cutover checkpoint. Do not fold AP-22, AD-10, or vendor work into it.