# P1 — origin-recenter retirement-receipt loop ## Observed failure `launch-feeltest-oclone.log` contains 243 consecutive failures with this shape: ```text streaming: origin-recenter preparation will resume: InvalidOperationException: Landblock 0xC85AFFFF already has a full retirement receipt. ``` The stack is `StreamingController.TryAdvanceOriginRecenterPreparation` → `LandblockPresentationPipeline.DetachAllForOriginRecenter` → `LandblockRetirementCoordinator.AdoptDetachedFull`. ## Root cause An ordinary full retirement detaches every landblock-owned presentation resource first, then parks surviving live entities in `GpuWorldState._pendingByLandblock` while the exact cleanup ticket advances asynchronously (`GpuWorldState.DetachLandblock`, around lines 1188–1314). The origin-recenter swap incorrectly treated every pending-only live bucket as another landblock presentation generation (`GpuWorldState.cs`, former lines 1352–1353). It therefore emitted a second full cleanup receipt for the same already-retired generation. `LandblockRetirementCoordinator` correctly rejected that duplicate at lines 416–425. Because spatial detachment had already committed, the broad retry catch in `StreamingController.TryAdvanceOriginRecenterPreparation` then repeated the detach against the changed state every frame. The pre-fix regression test `OriginRecenterAdoption_PendingOnlyLiveProjectionDoesNotCreateSecondFullReceipt` failed because the recenter returned one receipt for the pending-only bucket. ## Retail and reference boundary Retail destroys one concrete landblock owner synchronously: `CLandBlock::destroy_static_objects` (`0x0052FA50`) leaves and deletes the landblock's static objects; `CLandBlock::Destroy` (`0x0052FAA0`) releases its buildings and landblock data; `CLandBlock::release_all` (`0x0052FCF0`) releases the landblock's object and visibility ownership. A live object parked outside a loaded landblock is not a second `CLandBlock` and therefore cannot create a second landblock-destruction transaction. The extracted WorldBuilder reference follows the same ownership boundary: `ObjectRenderManagerBase` removes an actual `_landblocks` entry before `UnloadLandblockResources`, and `PortalRenderManager` only unloads a removed `PortalLandblock`. Neither treats an independently parked object as a new landblock resource owner. Acdream retains its approved asynchronous adaptation: the first exact receipt owns cleanup, while the live projection survives spatial recentering. ## Fix - `GpuWorldState.DetachAllForOriginRecenter` no longer creates retirement receipts from `_pendingByLandblock` alone. Pending live identities are still captured from `_projectionLocations`, cleared atomically, and re-parked unchanged. - A landblock that also owns loaded, pending-render, pending-near, tier, or bounds state still receives its exact full receipt. - A receipt-ledger invariant thrown after spatial detachment is now surfaced as a committed `StreamingMutationException`; it is terminal rather than falsely logged as resumable work. - The genuine duplicate-receipt guard remains unchanged. ## Deterministic evidence - The new pending-only regression failed before the source fix and passes afterward. - `OriginRecenter_PendingOnlyLiveProjectionKeepsItsExistingRetirementOwner` drives the production recenter/controller sequence and proves the origin commits while the first cleanup ticket remains pending. - `OriginRecenter_CommittedReceiptInvariantFailsFastInsteadOfReplayingDetach` proves a genuine post-detach ledger violation surfaces once rather than entering a frame-by-frame retry loop. - The complete `OriginRecenter` focused group passes 20/20. ## Gate evidence - Release build: 0 errors (21 pre-existing warnings). - Complete Release suite: 10,815 passed, 0 failed, 4 skipped. - Connected lifecycle/reconnect gate: `logs/connected-world-gate-20260802-203751/report.json` — `Passed=true`. - Connected nine-stop soak: `logs/connected-r6-soak-20260802-204309.report.json` — `Passed=true`, `Failures=[]`, graceful exit, all 9 canonical checkpoints present, no wait cue, no pending landblock retirement, no reveal invariant failure, and no render-shadow mismatch. - The soak artifacts contain zero occurrences of `already has a full retirement receipt`; the captured failing session had 243.