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 <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 19:46:21 +02:00
parent 31e6e192b3
commit 2862622ba2
2 changed files with 198 additions and 1 deletions

View file

@ -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 IJ 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 <name>` 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 19, 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.

View file

@ -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.