acdream/docs/plans/2026-07-20-automated-world-lifecycle-gate.md

142 lines
6.6 KiB
Markdown

# Automated world-lifecycle gate
**Status:** In progress (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 <occurrence> [timeout-ms]` waits for the authoritative
portal completion count;
- `checkpoint <name>` emits one JSON record containing reveal state,
landblock/entity/animation and resource-owner counts, managed memory, and
the latest frame-profiler summary;
- `screenshot <name> [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 for every lifecycle invariant;
- full Release solution build and test suite;
- two-process connected lifecycle report with screenshots and JSONL timeline;
- accepted capped and uncapped same-session metrics;
- `GameWindow` extraction retains the exact accepted lifecycle trace;
- roadmap, issues, architecture, divergence register, memory, `AGENTS.md`, and
`CLAUDE.md` agree on the resulting ownership and remaining visual gates.