From 2862622ba2114f4a18e09c32cf0f43ac0e0be0d1 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 22 Jul 2026 19:46:21 +0200 Subject: [PATCH] docs(architecture): plan canonical soak snapshots Define the deferred checkpoint acknowledgement, post-diagnostics frame phase, exact nine-stop artifact schema, canonical owner gates, and unchanged process-residency guard for Checkpoint K. Co-authored-by: Codex --- ...dow-slice-8-checkpoint-k-canonical-soak.md | 196 ++++++++++++++++++ ...amewindow-slice-8-composition-lifecycle.md | 3 +- 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md diff --git a/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md new file mode 100644 index 00000000..59057af8 --- /dev/null +++ b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md @@ -0,0 +1,196 @@ +# GameWindow Slice 8 Checkpoint K — canonical soak snapshots + +**Status:** Active 2026-07-22. +**Parent:** +[`2026-07-22-gamewindow-slice-8-composition-lifecycle.md`](2026-07-22-gamewindow-slice-8-composition-lifecycle.md), +Checkpoint K. +**Integrated baseline:** `31e6e192`; Checkpoints I–J are complete, +`GameWindow.cs` is 1,625 raw lines, App Release passes 3,441 tests / 3 skips, +and the complete Release suite passes 7,813 tests / 5 skips. +**Issue:** [`#232`](../ISSUES.md#232--nine-stop-soak-process-memory-gate-lacks-canonical-owner-snapshots). +**Behavior rule:** this checkpoint changes diagnostic capture and connected-gate +evidence only. It does not change rendering, streaming, gameplay, resource +budgets, or the existing process working/private-memory thresholds. + +## 1. Outcome + +Make every scripted `checkpoint ` a deferred, acknowledged render-frame +barrier. A checkpoint is written only after private presentation and the normal +render diagnostics phase have both observed the same immutable +`RenderFrameOutcome`. Its JSON contains the canonical world/reveal/resource +owner snapshot and that exact frame outcome. The script cannot execute the next +command until serialization and both writes succeed, fail, or are explicitly +cancelled during shutdown. + +The nine-stop soak then consumes exactly nine ordered checkpoints, gates +canonical owner stability at the Caul return → Caul plateau same-location pair, +labels server-controlled entity/animation population changes as workload +warnings, and retains process residency as an unchanged secondary guard. + +## 2. Runtime contract + +### 2.1 Acknowledgement token + +Replace the synchronous automation method with a request contract equivalent +to: + +```csharp +enum RetailUiAutomationCheckpointStatus +{ + Pending, + Succeeded, + Failed, + Cancelled, +} + +interface IRetailUiAutomationCheckpoint +{ + RetailUiAutomationCheckpointStatus Status { get; } + string? Error { get; } +} + +bool TryRequestCheckpoint( + string name, + out IRetailUiAutomationCheckpoint? checkpoint, + out string error); +``` + +The production token also retains the assigned request sequence and validated +name across the update → render edge. Only the controller can transition it, +exactly once, from Pending to a terminal state. + +`RetailUiAutomationScriptRunner` stores one token together with the active +command index. While Pending, repeated ticks return without enqueueing again or +advancing the command. Success clears the token and advances once. Failure or +cancellation clears it and stops on the token's exact error. Disposal still +releases held input; runtime shutdown is responsible for cancelling queued +tokens. + +### 2.2 FIFO request owner + +`WorldLifecycleAutomationController` becomes the sole FIFO owner and an +`IDisposable` frame-phase participant: + +- validation failure creates no request and consumes no sequence; +- accepted requests receive one monotonic sequence and enter one FIFO; +- a successful render drains accepted requests in order; +- each request serializes one `WorldLifecycleCheckpoint` containing its + sequence/name, current reveal state, the exact current `RenderFrameOutcome`, + and one canonical resource snapshot; +- Succeeded is published only after the JSONL append and named JSON write both + complete; +- capture/serialization/I/O failure marks only that request Failed with + contextual sequence/name error and does not throw out of rendering; +- shutdown marks every still-pending request Cancelled with an explicit error; +- enqueue after shutdown fails synchronously and cannot create an orphan token. + +The controller is adopted by `FrameRootRuntimeBindings` separately from its +retained-UI late binding, so the binding detaches and pending requests cancel +under the existing retryable frame-root lifetime. + +### 2.3 Post-diagnostics render phase + +Add a narrow `IRenderFramePostDiagnosticsPhase` with a no-op implementation. +`RenderFrameOrchestrator` calls it exactly once after: + +1. resource preparation; +2. world rendering; +3. private presentation and screenshots; +4. `IRenderFrameDiagnosticsPhase.Publish`; +5. then checkpoint drain; +6. finally the existing GPU-flight close. + +If an earlier render phase fails, post-diagnostics is not called and the FIFO +remains pending for the next successful frame. An unexpected post-phase throw +uses the existing render failure/recovery path, although production capture and +I/O failures are represented on tokens rather than thrown. No previous-frame +diagnostic value is paired with a current-frame owner snapshot: +`WorldLifecycleResourceSnapshotSource.Capture(RenderFrameOutcome)` takes +visible/total landblocks from the supplied outcome and reads the already- +published aggregate FPS/frame-time snapshot only after diagnostics runs. + +## 3. Artifact and soak schema + +`WorldLifecycleCheckpoint` adds the exact frame outcome. Existing reveal and +resource fields retain their names. The route adds these nine commands in this +order at the end of each settled destination block: + +1. `caul-baseline` +2. `sawato-baseline` +3. `rynthid` +4. `aerlinthe` +5. `sawato-return` +6. `holtburg` +7. `caul-return` +8. `sawato-plateau` +9. `caul-plateau` + +`run-connected-r6-soak.ps1` reads the JSONL only after the route completes and +requires one row for every expected name, exact sequence 1–9, exact order, and +the current process id. It embeds those records in the report. + +Every checkpoint hard-gates zero: + +- pending live teardowns; +- pending landblock retirements; +- staged mesh uploads and bytes; +- composite warmup work. + +The same-location Caul return → Caul plateau comparison requires exact equality +for deterministic owner/cache counts and bytes: loaded/visible/total landblocks, +materialized live owners, teardown/retirement queues, VFX binding/owner/script/ +light counts, mesh render-data/atlas/estimated bytes, staged work, tracked GPU +bytes/buffers/textures, and composite/particle texture ownership. Connected +`WorldEntities`, `AnimatedEntities`, `LiveEntities`, particles, and active +scripts may legitimately change with authoritative population or transient +effects; those deltas remain named workload warnings, not silent exclusions. +Managed used/committed deltas are reported diagnostically. Existing +working/private-memory, update-p95, and allocation-p50 thresholds remain byte- +for-byte unchanged as the secondary residency/performance guard. + +## 4. Implementation sequence + +1. Add token states and change the automation runtime/script runner to the + one-token-per-command polling contract. Cover delayed success, repeated + pending ticks, failure, cancellation, invalid request, and disposal while + pending. +2. Refactor `WorldLifecycleAutomationController` into the FIFO request owner; + pass the frame outcome into snapshot capture and write it into artifacts. + Cover FIFO order, sequence stability, write failure, no duplicate drain, + shutdown cancellation, and enqueue-after-dispose. +3. Add the post-diagnostics phase to `RenderFrameOrchestrator`, wire the + controller through `FrameRootCompositionPhase`, and adopt its lifetime + separately from the late UI binding. Pin exact phase order, skipped drain on + prior failure, post-phase failure recovery, and partial-composition cleanup. +4. Add the nine route commands. Parse/validate JSONL in the soak, attach the + canonical checkpoints to the report, add zero-work and same-location owner + gates, and preserve the old process/performance formulas verbatim. +5. Run behavior/order, architecture/ownership, and adversarial failure review + passes. Correct findings and re-run focused App tests, App Release, Release + build, and the complete Release suite. +6. Run two fresh-process connected nine-stop routes before closing #232. Both + must exit gracefully, produce exact ordered checkpoints, pass canonical + owner/cache gates, and pass the unchanged process residency guard. +7. Reconcile architecture, roadmap, milestones, issues, AGENTS/CLAUDE, and + durable memory; commit Checkpoint K as its own bisectable diagnostic unit. + +## 5. Automated acceptance + +- one checkpoint command creates one request, one sequence, and one artifact; +- a pending token blocks all later script commands without duplicate enqueue; +- render failure delays rather than loses or duplicates the request; +- diagnostics publication precedes same-frame capture; +- independent accepted requests drain FIFO and retain name/sequence identity; +- capture/write failure reaches the script as the exact failed-token error; +- shutdown reaches pending scripts as explicit cancellation; +- no controller/runtime reference points back to `GameWindow`; +- all nine route names and sequences are exact and appear in the soak report; +- canonical pending/staging/warmup work is zero at every checkpoint; +- Caul return → plateau deterministic owners/caches are unchanged, while + authoritative workload deltas are explicitly warned; +- working/private-memory thresholds and update/allocation formulas are + unchanged; +- focused, App, and complete Release suites pass with no new warnings. + +No visual gate is required for K because it changes diagnostic observation +only. Checkpoint L owns the final connected framebuffer and user visual gate. diff --git a/docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md b/docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md index 1d390a12..a3c288b0 100644 --- a/docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md +++ b/docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md @@ -36,7 +36,8 @@ audit. owner and prove all partial-load/reentrant/retry paths. Detailed plan: [`2026-07-22-gamewindow-slice-8-checkpoint-j-lifetime-shutdown.md`](2026-07-22-gamewindow-slice-8-checkpoint-j-lifetime-shutdown.md). - [ ] K — in a separate #232 commit, add canonical owner snapshots to every soak - checkpoint without weakening the process-memory guard. + checkpoint without weakening the process-memory guard. Detailed plan: + [`2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md`](2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md). - [ ] L — corrected-diff reviews, focused and full Release gates, connected lifecycle/soak, framebuffer comparison, documentation, memory, and final visual handoff.