acdream/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-k-canonical-soak.md
Erik 5c955c36ec docs(architecture): record GameWindow automated closeout
Reconcile the architecture, roadmap, milestones, issue ledger, session instructions, and durable memory with the 1,622-line native shell, canonical soak evidence, connected framebuffer comparison, and sole remaining user visual gate.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 20:52:25 +02:00

225 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GameWindow Slice 8 Checkpoint K — canonical soak snapshots
**Status:** Complete 2026-07-22 (`bca41487`, corrected gate semantics
`6c5e0604`).
**Parent:**
[`2026-07-22-gamewindow-slice-8-composition-lifecycle.md`](2026-07-22-gamewindow-slice-8-composition-lifecycle.md),
Checkpoint K.
**Integrated result:** `GameWindow.cs` is 1,622 raw lines, App Release passes
3,451 tests / 3 skips, and the complete Release suite passes 7,823 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.
Every route teleport supplies an explicit identity quaternion so the timed turn
begins from a reproducible heading. The same-location Caul return → Caul
plateau comparison requires exact equality for the deterministic loaded/total
world domain, while visible-landblock and authoritative entity/animation/live-
entity changes are named workload warnings. Teardown/retirement queues, staged
work, and composite warmup remain hard zero at every checkpoint. Mesh, atlas,
tracked-GPU, composite/particle-texture, and VFX owner counts may retire and
shrink normally; any growth is a hard leak failure when the visible and
authoritative workload is stable, and a named owner-growth warning when that
workload changed. Particles, emitters, and active scripts are always transient
workload warnings rather than silent exclusions. The report therefore says
which canonical owner grew without mistaking legitimate retirement for a leak.
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.
## 6. Completion evidence
The focused checkpoint suite passes 74 tests. The Release build succeeds with
only the 17 pre-existing test-project warnings tracked by #228. Two independent
fresh-process routes produced all nine ordered render-frame checkpoints and
closed gracefully:
- `connected-r6-soak-20260722-201335.report.json`: 403.139 seconds; Caul
return-to-plateau working/private deltas +20.2/+10.3 MiB; update p95 1.5 ms.
- `connected-r6-soak-20260722-202025.report.json`: 403.021 seconds; Caul
return-to-plateau working/private deltas +165.0/+157.2 MiB; update p95 1.3 ms.
Every checkpoint had zero pending teardown/retirement, staged upload work, and
composite warmup work. Neither run found unconfounded canonical owner growth,
and both passed the unchanged process-residency and performance limits.
The first connected implementation run also proved that exact cache equality
was the wrong leak predicate: visible landblocks and authoritative entities
changed while mesh/GPU/cache owner counts decreased through legitimate
retirement. The corrected contract therefore hard-fails owner *growth* when
the workload is stable, reports named growth warnings when the authoritative
or visible workload changed, and permits shrinking. It does not weaken the
process limits or hide an identified owner leak.