Connected Release session against the local ACE with the retail UI
(ACDREAM_RETAIL_UI=1). User verdict on the S1/S2 gate: works fine - effects
stay attached to moving entities across cell boundaries, and lit statics are
unchanged (the deliberately-preserved case).
The session log corroborates it: 9 completed world reveals including portals,
58 reveal events all failures=0, zero unhandled exceptions, zero parked
placements, zero firings of #284's new terminal world-frame invariant, and a
graceful exit.
#282 and #284 are closed. #283 (Runtime's world frame and App's render origin
rebasing at different moments during a teleport) remains open and is
deliberately sequenced immediately before C4 route 3, which shares its portal
code; its first step proves or disproves reachability before anything is
restructured.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fixes#282 (plan S2). Adds register row AP-133.
Retail gives a CPhysicsObj exactly ONE cell: ShouldDrawParticles @0x0050fe60
reads this->cell and calls IsInView on it, and set_cell_id @0x0050f4f0 /
change_cell @0x00513390 are the only things that move it. acdream splits that
into ParentCellId (render parent, deliberately null for outdoor dat stabs) and
EffectCellId (the authored landcell those parentless stabs still need) - an
adaptation, now recorded as AP-133.
WorldEntity.EffectCellId documents itself as the stab field, with live and
interior entities using ParentCellId. f24532ad began writing it for live
entities too. Because EntityEffectPoseRegistry resolved EffectCellId FIRST,
that write won - and the audit shows only 3 of 14 cell writers maintain it.
The other 11 do not, including the hottest paths: RemotePhysicsUpdater:239,294
and LiveEntityOrdinaryPhysicsUpdater:107 write ParentCellId every physics tick
from the snapshot, and LocalPlayerProjectionController:79 writes the local
player's cell every frame.
So a moving entity updated its cell constantly while EffectCellId stayed
frozen at whatever cell it materialized in. Its particles and lights kept
being tested against that stale cell and failed IsInView the moment it crossed
a boundary - effects vanishing on a monster that is plainly visible, or
drawing through a wall from a room the viewer cannot see.
The consumers had also drifted into disagreeing: EntityEffectPoseRegistry
preferred EffectCellId while WbDrawDispatcher.TryGetEntityCell and the remote
spawn seed preferred ParentCellId - two answers to "which cell is this in".
- WorldEntity.VisibilityCellId (ParentCellId ?? EffectCellId) is the single
accessor; all five consumer sites resolve through it, so the precedence
cannot drift apart again.
- LiveEntityRuntime's three live-entity EffectCellId writes are removed,
restoring the field to its documented purpose. Its real writers -
LandblockLoader:80,97 and LandblockBuildFactory:408 - are untouched, and the
parentless-stab path is pinned by a new test.
- f24532ad's actual fix is preserved: RebucketLiveEntity still installs the
committed cell, just on the one field live entities use.
LiveEntityLightControllerTests.Refresh_FollowsCurrentTopLevelRootAndCell is
back to moving the entity by ParentCellId alone - its original pre-f24532ad
form - and passes. CanonicalOnlyRebucket_DoesNotOverwriteAuthoritativeFullCell
had its two EffectCellId assertions (added by f24532ad, encoding the defect)
replaced with the corrected contract: ParentCellId set, EffectCellId null,
VisibilityCellId resolving - a stronger assertion, not a relaxed one.
Complete Release solution: 10,836 passed / 4 skipped / 0 failed.
User visual check still outstanding: a monster with an active spell effect
crossing a cell boundary, and a lit static object, indoors and outdoors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fixes#284 (plan S1).
A first-entry placement that could not be prepared returned
RetrySetupUnavailable and was re-Advanced every pump forever. Nothing counted
it, nothing named its cause, and nothing distinguished "waiting for something
that will arrive" from "waiting for something that never can". That is why
#281's 43 test failures presented as four unrelated symptoms across App and
Runtime instead of one cause, and why a stuck entity in the live client simply
never appears with no log line to follow.
Worse, the two causes were conflated: 670f307c's missing-world-frame park
reported itself as RetrySetupUnavailable, sending anyone diagnosing it to the
prepared-asset pipeline rather than to the absent local-player Create that
actually publishes the frame.
- RetryWorldFrameUnavailable splits the two causes. Call sites now ask
IsRetryable() instead of comparing against one reason, so a future retry
reason cannot be silently reclassified as a hard rejection - the exact way
this class of bug hides.
- The operation retains its RuntimeSetPositionParkReason, and
RuntimeSetPositionOwnershipSnapshot reports parked work by cause
(ParkedAwaitingSetupCollisionCount / ParkedAwaitingWorldFrameCount /
ParkedPlacementCount), so parked placements appear wherever ledgers are
already asserted.
- ObserveLocalPlayerCreate records the accepted local-player Create even when
it carries no landblock - precisely the case where no frame is ever
published - and ThrowIfWorldFrameUnreachable makes that contradiction
terminal. Waiting is legitimate only while that Create is outstanding; after
it, no later pump can supply the frame. Same shape as 01f4791e, which made a
violated receipt-ledger invariant terminal rather than resumable.
This is observability plus fail-fast. There is no timeout, no retry cap, and
no grace period anywhere in it; retryable work still retries exactly as before
and no placement behaviour changed.
The parked counts are deliberately NOT folded into IsConverged: #277 documents
a far Create legitimately parking for a whole session, so a parked entry at
teardown is not automatically a defect. Wiring them into the connected gates
is carried with #277's service-window conversion, where "legitimately parked"
becomes definable.
Runtime 1,012/1,012. Complete Release solution: 10,834 passed / 4 skipped /
0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three defects introduced by the 2026-08-02/03 stabilization batch, all found
while reconciling #281's 43 test failures. Each is an instance of the weakness
the placement campaign exists to remove - two owners of one fact with no single
writer keeping them agreed - so they are cleared before C4 stacks six more
placement routes on top of them.
#282: WorldEntity.EffectCellId documents itself as existing only for outdoor
dat stabs, whose null render parent still needs retail's outdoor landcell for
CObjCell::IsInView gating; live/interior entities were explicitly meant to use
ParentCellId. f24532ad began populating it for live entities, and because
EntityEffectPoseRegistry.UpdateRoot resolves EffectCellId ?? ParentCellId it
now wins - while 12+ sites still write ParentCellId alone. Retail carries one
cell per object (CPhysicsObj::set_cell_id @0x0050f4f0, change_cell @0x00513390,
ShouldDrawParticles @0x0050fe60).
#283: 670f307c gave Runtime a world frame that rebases on the accepted teleport
Position, while App's LiveWorldOriginState rebases only after old-window
retirement completes. Between those edges the two disagree by the landblock
delta. Not yet proven reachable; the plan proves or disproves it before
restructuring anything.
#284: a placement that cannot resolve returns RetrySetupUnavailable forever
with nothing counting it or naming its reason. The fix is observability plus
fail-fast on contradictory states, never a retry cap or timeout.
Plan sequences S1 (#284) first so the other two are observable rather than
archaeological, then S2 (#282), then S3 (#283) immediately before C4 route 3,
which shares its portal code. Also records the gating change that would have
caught all of this: the complete Release suite must be green before every
commit, not a focused subset.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f24532ad changed two presentation contracts that these fixtures still
expressed in their pre-change shape. Both failures date exactly to that
commit; they are independent of the world-frame family fixed in 6dcb94ac.
LiveEntityLightControllerTests.Refresh_FollowsCurrentTopLevelRootAndCell moved
the entity by writing ParentCellId alone. f24532ad now populates EffectCellId
at materialization and keeps it synchronized on canonical rebuckets
(LiveEntityRuntime.RebucketLiveEntity:845-856), because retail's
CPhysicsObj::set_cell changes the one CObjCell that ShouldDrawParticles reads.
EntityEffectPoseRegistry.UpdateRoot:163 resolves EffectCellId ?? ParentCellId,
so a production cell move writes both together and the old single-field move
left effects and lights on the stale materialization cell.
LiveEntityAnimationSchedulerTests.RetainedProjectileWithRemote_WhenMissileClears_TransfersMovementToRemoteOnce
seeded its shared remote body by assigning Position directly. Projectile
classification now validates and adopts the canonical body's own cell frame
(ProjectileController:184-190 - body.CellPosition.ObjCellId /
.Frame.Origin) rather than deriving it from the sidecar's FullCellId and the
streaming center, since a residence-managed Create legitimately still reports
FullCellId 0. A Runtime-committed body always carries its (cell, local) frame,
so the fixture now seeds it through the same SnapToCell placement API; leaving
it cell-less was correctly refused.
Both fixtures keep their original assertions - only the modelled world state
moved to match what production now commits.
Complete Release solution: 10,831 passed / 4 skipped / 0 failed
(App 4,048/3, Bake 15, Cli 4, Content 124, Core.Net 762, Core 4,247/1,
Headless 79, Runtime 1,009, UI 543).
Closes#281.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ACE intentionally creates the local player Hidden and releases that materialization state on LoginComplete. Sending LoginComplete from raw F746 receipt raced canonical placement and left the login haze visible. Route one one-shot completion callback from Runtime's local first-entry terminal edge to graphical and prepared headless hosts; retain a guarded accepted-Create edge only for content-less headless sessions. Focused Runtime login tests, all 79 Headless tests, the connected user gate, and the Release build pass.
C3c created graphical effect, projectile, and static-animation sidecars before Runtime finished the entity's first SetPosition. One-shot F754/F755 packets could be discarded, projectiles could adopt a cell-less body, and animated statics could compete for body ownership. Keep effects behind an exact-incarnation presentation barrier, retry projectile/static binding on the committed visibility edge, and keep effect cells synchronized with canonical rebuckets. User verified spell, recall, arrow, projectile, portal, and static presentation; 90 focused App tests and the Release build pass.
Root cause: pending-only live projection buckets were misclassified as landblock presentation owners during origin recentering. That manufactured a second full cleanup receipt for a generation whose first receipt was still advancing; the duplicate guard threw and the broad retry path replayed the already-committed detach 243 times.
Keep pending live projections through the spatial identity map without issuing another receipt, and fail fast when a receipt-ledger invariant occurs after detachment. Evidence: docs/research/2026-08-02-collision-throughput-handoff/p1-retirement-receipt-loop.md. Release suite, lifecycle gate, and nine-stop soak pass.
Late-arriving adversarial-review artifact: deletions confirmed clean
(no surviving consumers, no post-Revoke dereference), one dead orphan
(CollisionWorldStateSlot.TransferTo), two stale test names, and the
stale-docs catalog for whoever lands the collision work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Publication-throughput rework per the D2 design (docs/research/
2026-08-02-collision-throughput-handoff/design-note.md): O1 per-prefix
installed-key ledgers replacing the seal's full-map scans; O2 per-
landblock delta commit (LandblockReplacementApplyCursor against the
active root) replacing whole-world TransferTo; O3 empty staging root,
commit-time reflood (CObjCell::init_objects 0x0052B420 ->
recalc_cross_cells 0x00515A30), journal/peer-rebase machinery deleted
(~1,900 lines net).
Automated gates green: Runtime 999, Core physics 2,135, App 4,039/3,
Headless 79, complete solution 10,812/0/4; lifecycle gate PASS
(connected-world-gate-20260802-193029). Soak 194423: publication-side
acceptance fully met (37 -> 4 failures, all convergence dims zero,
loadedLandblocks baseline-identical, waitCue 6/9 -> 1/9).
COMMITTED AS WIP ON USER DIRECTION - NOT ACCEPTED. The user feel-test
FAILED on this tree: monsters still pop into existence at close range,
monsters spawned mid-air far ahead, static placements visibly wrong,
plus 243x "Landblock already has a full retirement receipt"
InvalidOperationException catch-retry loop during origin recenter
(launch-feeltest-oclone.log). The 4 remaining soak failures
(pendingLandblockRetirements 131/122 at the Caul->Sawato stops) and the
implementer's "exposed pre-existing" classification are under
re-judgment against that loop. Dual reviews were dispatched and then
stopped mid-flight on user direction; NO review has passed this commit.
Full problem inventory + next-agent instructions:
docs/research/2026-08-02-collision-throughput-handoff/.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User session observations: late monster pop-in, extended/stuck portal
space, and portal-exit character pop-in are the 6b28ff99 publication-
throughput regression made visible by C3c retail-correct wait-for-
collision placement (next slice). Intermittent spell particle loss filed
as #279: one-shot scripts arriving in the suppressed-until-receipt
window need retail pending-script deferral to presentation binding.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C3c COMPLETE at 529e0e9d in the placement-cutover plan (five fix slices,
R1 dual-review round, final gates). New closeout research note. ISSUES
#276 (settle-CellId discard), #277 (route-1 far-Create radius bound),
#278 (user-session triage bundle). Register AD-60/AD-61 numeric order.
The next slice before C5 is the 6b28ff99 O(changed) collision clone
(soak convergence); C4 resumes after.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Campaign P remaining-physics-divergence, placement cutover slice C3c
(docs/plans/2026-08-02-placement-cutover.md). Both production hosts now
register every initial Create through the residence + continuation-
executor + first-entry-conductor machinery (C0-C3b):
- Graphical (route 1): RegisterEntityWithInitialResidence at Create; the
shared RuntimeFirstEntryDriveController pumps both conductors from the
placement-receipt flow; MaterializeProjection and RebucketLiveEntity
are presentation-only while a residence is ACTIVE (ExecutorCompleted is
the presentation-binding receipt); post-residence entities take the
full legacy path including the prepare_to_enter_world clock edges.
PlayerModeController attaches presentation to the Runtime-published
controller; its legacy resolve/step-heights/host-construction path is
deleted; presentation-only rollback (retail has no entry-flow rollback).
- Headless (route 8): OnSpawned registers with residence when a drive
exists; content-less sessions keep the pre-flip direct registration;
SynchronizeLocalPlayer/CreateController/ApplySetupStepHeights deleted;
prepared-collision read failure is a typed AwaitingCollisionSource
retry; far remotes outside the service window complete celless.
- RuntimeLocalPlayerMovementState.Controller setter sealed internal; all
controller mutation flows through the publication lifecycle.
Fix slices landed within this cutover, each dual-gated:
- F1: live movement-stat/server-physics application routed through the
Runtime ownership seam (post-logout ingest crash on the retired
controller eliminated; RuntimeMovementSkillProjection deleted).
- F2: login activation wedge - collision-admission prefix gate factored
out of the seal (reentrant-commit RejectedAuthority), rearm generation
identity corrected, PlayerModeAutoEntry requires the Runtime-published
controller (world reveal can no longer seal unmaterialized).
- F3: landblock-prefix 0-sentinel replaced by explicit absent-id guards;
map-corner landblocks (grid row/col 0) fully legal through admission,
park/rearm/retire, quiescence, and outdoor shadow seeds.
- F5: local-player first-entry ground contact seeded by the shared
SpawnPlacementSettler (moved App->Core) at FinalizeActivation - the
retail first-gravity-frame touch (enter_world 0x00516170 carries no
seed); the legacy unconditional force-seed is overwritten by a real
floor-found contact; airborne spawns stay airborne; outbound contact
bit verified end-to-end. Fixes the standing-cast 'You can't do that
while in the air!' rejections.
- R1 (dual-review round): login constraint leash armed at the committed
placement (HandleReceivedPosition 0x00453FD0 analog); register rows
AD-61 (settle-timing compression now covering the local player) and
AD-42 (repointed off the deleted resolve split) in this commit;
residence-conversion owner API; wire-landblock guards; drive-pending
ledger in IsConverged; route attach/detach latch; executor-drain drift
model documented + source-pinned.
Gates: Runtime 1,003, App 4,039/3 skips, Headless 79, complete solution
10,816/0 failed/4 skips (Release, -m:1); connected lifecycle/reconnect
gate PASS (logs/connected-world-gate-20260802-175401; graceful exits,
world-visible, zero airborne rejections). The nine-stop soak remains red
for the pre-existing 6b28ff99 whole-world collision-clone throughput
regression (attributed with evidence; scheduled as its own slice before
C5). Dual Opus reviews (retail-conformance + adversarial): delta PASS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C3b landed at 0934a121 with dual review PASS. The plan records the
remote-entry mechanism and its verified retail anchors; the float-gates
doc gains the port note pinning the NaN dispositions (friction's
sanctioned skip; elasticity and translucency routed exactly as the
binary; ACE's elasticity NaN divergence recorded). Every dormant C3
prerequisite is now complete — C3c, the host flip with the connected
gates, is the sole remaining piece of C3.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C3a landed at 960373df with dual review PASS. The plan records the
conductor's five-stage sequence (verified step-for-step against retail's
entry order, with the mover-shapes-first correction the tested
preconditions forced), the convergence/wiring closures, and the two
carried findings C3c must honor. Next: C3b remote body construction at
Create, whose float-gate oracle is committed at 874d94bf.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C3b's blocking retail question, resolved byte-certain from the
PDB-paired v11.4186 binary: CPhysicsObj::set_description applies the
desc's friction only when 0.0 <= friction <= 1.0 (outer JNP-on-parity
gate vs 0.0 double at .rdata 0x00794610; inner <= 1.0 vs 0x3FF0... at
0x007928c0), and applies live translucency + the CPartArray propagation
only when translucency != 0.0f (FCOMP m32 vs 0.0f at 0x007c6a80;
translucencyOriginal is written unconditionally before the gate). Every
FLD/FCOM operand address read from .rdata and every FNSTSW/TEST/Jcc
decoded by hand; ACE PhysicsObj.cs:3557-3568 independently reproduces
all three predicates as the cross-check. Unblocks the C3b remote
body-construction port.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first C3 implementation pass landed C3-1 (fe02c4f5) and correctly
stopped on two structural gaps no planning document captured: the local
player's first-entry circularity (the residence opens its placement at
Create, submission needs a body, and only the zero-caller publication
chain can attach one — resolvable by the campaign handoff's own route-1
order, but no driveable state machine exists) and the absence of any
remote-creature body construction at Create time (retail builds physics
in ACCObjectMaint::CreateObject; ours arrive with first motion). The
plan now records the C3a (first-entry conductor, dormant) / C3b
(retail-anchored remote body construction at Create, dormant — its
contract must first resolve set_description's three FPU-elided
friction/translucency gates from the PDB-paired binary) / C3c (the
actual host flips + connected gates) decomposition.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C2 landed at 63c601ff with dual review PASS after two fix rounds. The
plan records the halved allocation result and tightened gate, the
class-wide token-based staleness rework the pooling forced, the
documented residual floor (Core-side ~520 B/op deferred to the C3
activation gate as a possible C2b), and the two review maintenance
notes. Next slice: C3, the spawn-frequency host cutover of routes 1+8.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The C1 body-writer research found the atomic controller/body transaction
already built and tested: RuntimeLocalPlayerPhysicsPublicationState plus
the dormant local-activation family implement the sanctioned
off-canonical-prepare + validated-atomic-commit shape end-to-end, with
zero production callers. The committed writer map records the six
canonical body writers, the two host escape hatches (the public
Controller setter both hosts write directly; App's object-clock facade
bypasses), the headless prepared-collision fragility, and both hosts'
construction divergences. C1 therefore collapses into C3's route-1 flip
— the remaining work is production wiring, not mechanism design — and
C2 (the placement allocation budget) becomes the next slice.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C0 landed at 67f63e85 with dual review PASS; the plan now records its
delivered seam (acknowledge-only ExecutorCompleted receipts through the
one placement stream, retail-exact live-input derivation, the chained
authored-mover preparation, the cancellation-symmetry hardening) and the
three C3 prerequisites its reviews surfaced: the internal-only completion
receipt surface, the per-Execute distance-freshness deferral, and the
SendAutonomyLevelEvent obligation on any future autonomy-level host
exposure. Next slice: C1, the atomic controller/body publication.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The continuation executor (5db3de3c) completed the dormant residence
mechanism; the cutover is the campaign leg that makes it production truth.
The committed 8-route inventory maps every duplicate placement authority in
both hosts with exact call chains, confirms the placement-receipt observer
seam is fully built but unattached, and surfaces five pre-cutover gaps the
shipped mechanism cannot yet express (executor-to-channel bridge, atomic
controller/body publication, the 1,880 B/op activation budget, Runtime-side
live-input derivation, the portal-authority adapter). The plan decomposes
the cutover into C0-C5 bisectable slices under the campaign's standing
contract/dual-review/gate discipline, ending at the connected routes and
the user visual matrix that retire AP-1/AD-1.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
The admission checkpoint (30012361) sealed accepted updates behind a
pending initial placement; nothing could apply them, so AcknowledgeAdoption
refused any non-empty FIFO and the residence system had no path to
completion. RuntimeInitialCreateContinuationExecutor is that missing
mechanism: a synchronous, retry-idempotent Execute transaction that adopts
the acknowledged initial placement exactly once (consuming the retained
completion so later authored placements for the key can begin), emits the
AfterEnterWorld hook request for the local player, replays deferred
missing-parent raw Creates and queued parent relations by parent GUID
(retail ProcessObjectNetBlobs order: whole-bucket detach, FIFO dispatch,
cancellation-aware restore), and drains the mixed continuation FIFO
strictly by sequence with retail route decisions taken at execution time
via ClassifyAcceptedPosition on live inputs (server-asserted wire contact,
data-driven animation proxy, live distance/options).
Apply bodies are shared with the legacy fused paths through new gate-less
instance seams on InboundPhysicsStateController that keep the one snapshot
store in lockstep; SameIncarnationCreate envelopes apply atomically with
per-stage idempotency and buffered publication after the final stage;
every abandonment path retires the residence through the lifetime choke
point and converges the ownership ledger (executor progress, deferred
buckets, replay windows, placement watches all folded into IsConverged).
Position/placement side effects are exactly-once under retry, external
mutations are detected via a field-masked executor baseline, and
AwaitingContinuationPlacement yields keep the FIFO head retryable.
Production routes are deliberately untouched: graphical and headless
Create still use legacy RegisterEntity, and no host calls Execute. The
cutover is the next checkpoint; AP-1/AD-1 remain open until it lands.
Register rows AD-59/AD-60/AP-130/AP-131/AP-132/TS-62/TS-63 document the
slice's deviations in this commit.
Reviewed: retail-conformance PASS + architecture/adversarial PASS after
five implementation rounds (wire-contact source, snapshot lockstep,
WeenieDescription merge, abandonment convergence, reentrant retirement
windows, acknowledged-completion leak, baseline precision, replay
containment/restore, queue-by-parent-GUID relation deferral all fixed at
root cause). Runtime tests 903/903; complete Release solution 10,696
passed / 4 intentional skips; focused executor gate 161/161.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>