# Automated world-lifecycle gate **Status:** Complete (2026-07-20) **Owner:** M3 stabilization / R6 rendering-lifecycle rebaseline **Depends on:** `WorldRevealReadinessBarrier`, retained-UI automation, `FrameProfiler`, connected local ACE ## Outcome Create a deterministic connected Release gate that catches the structural failures which previously required someone to stare at the client for several minutes: - the first login frame cannot expose world geometry before the destination's render meshes, composite textures, and collision data are all ready; - every portal/recall lifetime crosses the same readiness edge, materializes once, and returns to the normal viewport once; - dungeon entry and exit use the same lifecycle without grey frames, stale-source geometry, or an uncollidable destination; - graceful logout followed by a fresh reconnect starts a new reveal lifetime and cannot inherit readiness or resources from the previous process; - repeated destinations do not cause cumulative memory, owner-count, allocation, update-time, or GPU-time growth; - each stable checkpoint produces machine-readable state plus a screenshot for later human comparison. This is a correctness and resource-lifetime gate. Screenshots preserve visual evidence, but automation does **not** claim retail visual equivalence. Color, composition, animation feel, and subtle geometry artifacts remain user gates. ## Canonical runtime contract `WorldRevealReadinessBarrier` remains the only definition of destination readiness. It will expose a structured snapshot rather than forcing telemetry to repeat the readiness formula. A snapshot records the destination cell, indoor/outdoor classification, required radius, render publication, composite texture readiness, collision readiness, an impossible/unhydratable claim, and the final `Ready` result. A focused App-layer `WorldRevealLifecycleTelemetry` owns diagnostic reveal generations. It has no GL calls and no knowledge of `GameWindow`. For each login or portal generation it records: 1. begin; 2. destination acquisition; 3. each distinct readiness transition; 4. the first frame where the normal world viewport is actually eligible to draw; 5. completion or cancellation. Making the normal viewport visible before `Ready` is a hard invariant failure, not a warning. A newer generation retires the older one, so stale asynchronous completion cannot satisfy the new destination. `GameWindow` only supplies facts and invokes the controller at existing lifecycle seams. It does not gain a new feature body. ## Production automation seam The retained-UI automation runner gains runtime commands through an injected interface: - `wait world-ready [timeout-ms]` waits on canonical lifecycle state instead of a guessed sleep; - `wait materialized [timeout-ms]` waits for the authoritative portal completion count; - `checkpoint ` emits one JSON record containing reveal state, landblock/entity/animation and resource-owner counts, managed memory, and the latest frame-profiler summary; - `screenshot [timeout-ms]` queues a default-framebuffer capture after the complete world and retained UI have drawn, then waits for the render thread to finish the PNG; - existing `input` commands perform deterministic turns and movement through `InputDispatcher`. All state mutation and GL readback stay on the update/render thread. The external gate only launches the process, observes files/logs and OS process metrics, and requests normal `WM_CLOSE` shutdown. ## Connected route The gate runs two capped/uncapped-aware sessions against local ACE: 1. fresh login → wait for canonical readiness → checkpoint + screenshot; 2. outdoor dense scene → turn → stable checkpoint + screenshot; 3. world-edge scene → turn → stable checkpoint; 4. known dungeon destination → checkpoint + screenshot → local movement; 5. return outdoors → checkpoint + screenshot; 6. revisit the first dense scene → stable resource comparison; 7. graceful close; 8. reconnect the same account → repeat the fresh-login readiness and screenshot gate → graceful close. The existing seven-destination R6 soak remains the longer performance route. The lifecycle gate is shorter and more diagnostic; it composes with that soak rather than replacing it. ## Hard failures - world viewport observed before the active reveal snapshot is ready; - destination never reaches readiness or materialization within the bounded connected test timeout; - missing or duplicate reveal/materialization/completion edges; - missing checkpoint JSON or screenshot, zero-sized/corrupt screenshot; - absent required destination landblock/EnvCell/collision readiness; - retained per-owner resources after delete/session teardown in deterministic tests; - same-location resource counts or memory/per-frame allocation grow beyond the route's documented relative tolerance; - unhandled exception, access violation, OOM, GL/device loss, disconnect, unexpected WeenieError, nonzero exit, or failure of graceful shutdown. Absolute FPS is recorded, never compared across local and RDP sessions. The gate compares like-for-like samples within one process and reports CPU and GPU frame time separately. ## Implementation sequence 1. Add a structured readiness snapshot and exhaustive barrier tests. 2. Add lifecycle telemetry as a pure App owner with stale-generation, cancellation, duplicate, and early-visible tests. 3. Add the automation runtime interface, deterministic waits, checkpoints, and screenshot request/completion protocol. 4. Add the render-thread screenshot owner and structured resource snapshots. 5. Wire the owners at login, F751 portal start, TAS placement/completion, world draw eligibility, and session teardown. 6. Add the connected route and PowerShell report/gate orchestration. 7. Run capped and uncapped Release gates, fix root causes, and retain artifacts. 8. Extract the now-protected streaming/portal/reveal frame orchestration from `GameWindow` without changing the accepted lifecycle trace. 9. Run focused tests, full Release build/test, connected gates, graceful-close verification, and documentation reconciliation. ## Completion evidence - Focused App tests cover readiness composition, stale generations, cancellation, duplicate lifecycle edges, early-visible rejection, artifact capture, automation timeouts, and resource snapshots. - `dotnet build AcDream.slnx -c Release` succeeds. The complete repository suite is 6,480 passed / 5 skipped; the 17 existing test-project warnings remain tracked by issue #228. - The final two-process connected report passed with no failures. The capped process completed fresh login, Aerlinthe, Rynthid, Facility Hub, Holtburg, and an Aerlinthe revisit in 244.424 seconds. The uncapped process then reconnected the same account and completed in 61.717 seconds. - Both processes closed through `WM_CLOSE`, received the authoritative character-logoff confirmation, exited with code 0, and were matched to ACE's exact client UDP endpoint and `PacketHeader Disconnect` record. - Every checkpoint had zero pending live teardowns, landblock retirements, staged mesh uploads, composite warmups, and reveal invariant failures. - All six PNG artifacts were valid and inspected. Login, indoor dungeon, dungeon exit, Aerlinthe revisit, and reconnect showed complete world geometry rather than a grey or partially revealed destination. - The uncapped reconnect sampled 172.7 FPS / 5.79 ms at the checkpoint; its latest profiler window measured 5.7 ms CPU p50, 6.1 ms p95 and 5.7 ms GPU p50, 6.0 ms p95 with zero pacing time. This is machine-specific throughput evidence, not a cross-display FPS requirement. - The Aerlinthe revisit retained balanced owners and stayed inside the documented relative memory/resource tolerances. One circuit is not claimed as a permanent memory plateau proof; the longer seven-destination R6 soak remains the endurance gate. - `WorldRevealCoordinator` now owns the protected lifecycle outside `GameWindow`; the accepted trace did not change after extraction. ## Landed commits - `db45b81f` — expose canonical readiness snapshots and lifecycle telemetry; - `354c2adc` — add deterministic checkpoints and framebuffer screenshots; - `b03371c0` — add the connected lifecycle/reconnect gate; - `68578fa5` — port retail graceful character logout and transport disconnect; - `a4ef5788` — centralize the reveal lifetime in `WorldRevealCoordinator`; - `f7b09617` — preserve singleton endpoint/checkpoint collections in the gate. The remaining visual work is deliberately outside this gate: the R6 locomotion/collision/projectile/teleport retail comparison, the two-client portal-out/materialization observer comparison, and issue #225's translucent lifestone/particle ordering comparison.