docs(architecture): close GameWindow render slice

Record the clean Release, lifecycle, soak, and framebuffer gates for Slice 7, advance the structural program to Slice 8, and preserve the observed process-residency diagnostic gap as issue 232 rather than weakening its leak threshold.\n\nCo-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 08:40:52 +02:00
parent 9d7df1bfc5
commit 96f8bfcfa8
8 changed files with 176 additions and 64 deletions

View file

@ -115,7 +115,7 @@ and the final two-client portal-out/materialization observer flow are
user-gated. Deterministic world-lifecycle automation protects fresh login,
outdoor/world-edge/dungeon travel, same-location revisit, exact graceful
disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts.
Release builds; 7,182 tests pass / 5 skip.
Release builds; 7,341 tests pass / 5 skip.
**Active prerequisite before new M4 subsystem work:** continue the
behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21.
@ -123,16 +123,16 @@ Selection/interaction Slice 1, live-animation-presentation Slice 2, complete
live-session ownership Slice 3, and live-entity App integration Slice 4 are
landed. Focused hydration, teardown, inbound-authority, network-update, and
motion-runtime owners now sit over canonical `LiveEntityRuntime` without a
second GUID dictionary. Slice 5 landblock presentation and Slice 6 update-frame
orchestration are complete. Streaming, input, the object/network barrier,
liveness, teleport, player mode, and camera presentation have typed phase
owners; `GameWindow.OnUpdate` is one orchestrator handoff with no substantial
transitive callback facade. `GameWindow` is 7,026 raw lines / 241 fields / 108
methods, down 8,697 lines (55.3%) from the 15,723-line campaign baseline. The
7,182-test Release suite, 314-second lifecycle/reconnect gate, and 394-second
synchronized nine-stop soak pass. Slice 7 draw-frame orchestration is active;
Slice 8 finishes composition and Silk callback cleanup.
See `docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining
second GUID dictionary. Slices 57 are complete: landblock presentation,
update-frame orchestration, and render-frame orchestration all have typed
owners. `GameWindow.OnUpdate` and `GameWindow.OnRender` are one-handoff methods;
the frame owners have no direct window or anonymous callback-bag ownership.
`GameWindow` is 4,666 raw lines / 196 fields / 70 methods, down 11,057 lines
(70.3%) from the 15,723-line campaign baseline. The 7,341-test Release suite,
315.6-second lifecycle/reconnect gate, and 395.2-second synchronized nine-stop
soak pass. Final Slice 8 composition/shutdown and Silk callback cleanup is
active. See `docs/architecture/code-structure.md`. **Carried:** #232, #153,
#116, remaining
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Pipeline MP1b+, and #225's
lifestone/particle alpha visual gate.

View file

@ -113,7 +113,7 @@ and the final two-client portal-out/materialization observer flow are
user-gated. Deterministic world-lifecycle automation protects fresh login,
outdoor/world-edge/dungeon travel, same-location revisit, exact graceful
disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts.
Release builds; 7,182 tests pass / 5 skip.
Release builds; 7,341 tests pass / 5 skip.
**Active prerequisite before new M4 subsystem work:** continue the
behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21.
@ -121,16 +121,16 @@ Selection/interaction Slice 1, live-animation-presentation Slice 2, complete
live-session ownership Slice 3, and live-entity App integration Slice 4 are
landed. Focused hydration, teardown, inbound-authority, network-update, and
motion-runtime owners now sit over canonical `LiveEntityRuntime` without a
second GUID dictionary. Slice 5 landblock presentation and Slice 6 update-frame
orchestration are complete. Streaming, input, the object/network barrier,
liveness, teleport, player mode, and camera presentation have typed phase
owners; `GameWindow.OnUpdate` is one orchestrator handoff with no substantial
transitive callback facade. `GameWindow` is 7,026 raw lines / 241 fields / 108
methods, down 8,697 lines (55.3%) from the 15,723-line campaign baseline. The
7,182-test Release suite, 314-second lifecycle/reconnect gate, and 394-second
synchronized nine-stop soak pass. Slice 7 draw-frame orchestration is active;
Slice 8 finishes composition and Silk callback cleanup.
See `docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining
second GUID dictionary. Slices 57 are complete: landblock presentation,
update-frame orchestration, and render-frame orchestration all have typed
owners. `GameWindow.OnUpdate` and `GameWindow.OnRender` are one-handoff methods;
the frame owners have no direct window or anonymous callback-bag ownership.
`GameWindow` is 4,666 raw lines / 196 fields / 70 methods, down 11,057 lines
(70.3%) from the 15,723-line campaign baseline. The 7,341-test Release suite,
315.6-second lifecycle/reconnect gate, and 395.2-second synchronized nine-stop
soak pass. Final Slice 8 composition/shutdown and Silk callback cleanup is
active. See `docs/architecture/code-structure.md`. **Carried:** #232, #153,
#116, remaining
R6 ownership cleanup, TS-50/TS-51/TS-53, Modern Pipeline MP1b+, and #225's
lifestone/particle alpha visual gate.

View file

@ -26,12 +26,15 @@ What does NOT go here:
## Current queue — 2026-07-22
- **Active structural work:** `GameWindow` decomposition. Slices 16 are
complete; `GameWindow.OnUpdate` is one typed orchestration handoff and the
class is 7,026 lines / 241 fields / 108 methods. Slice 7 draw-frame
orchestration is active in
- **Active structural work:** `GameWindow` decomposition. Slices 17 are
complete; `GameWindow.OnUpdate` and `GameWindow.OnRender` are typed
orchestration handoffs and the class is 4,666 lines / 196 fields / 70
methods. Final Slice 8 composition/shutdown cleanup is active in
[`docs/architecture/code-structure.md`](architecture/code-structure.md).
This is the behavior-preserving prerequisite before new M4 feature bodies.
- **Connected-gate fidelity:** `#232` adds canonical managed/GPU/cache-owner
snapshots to the nine-stop soak so process-residency variance cannot be
mistaken for an owner leak or silently waved away.
- **Separate rendering gate:** `#225`, lifestone/particle alpha ordering. Its
connected performance, lifetime, and unattended portal routes pass.
- **Carried behavior debt:** `#153` far-teleport unstreamed-edge arrival and
@ -70,6 +73,42 @@ Copy this block when adding a new issue:
---
## #232 — Nine-stop soak process-memory gate lacks canonical owner snapshots
**Status:** OPEN
**Severity:** LOW
**Filed:** 2026-07-22
**Component:** connected automation / resource diagnostics
**Description:** Identical-binary nine-stop runs can cross the same-location
working/private-process-memory tolerance even when all deterministic lifecycle,
entity, animation, allocation-rate, update-cost, movement, and graceful-close
checks pass. At Slice 7 closeout, two runs reported Caul-plateau working-set
growth of +240.9 MiB and +497.4 MiB; a third unchanged run passed at +85.7 MiB
(private +59.3 MiB). Earlier Slice 6 development history also contains both a
coarse-memory failure and subsequent clean runs.
**Root cause / status:** The current soak samples only process working set and
private bytes plus coarse world/title counters. Those totals combine live .NET
objects, committed-but-free GC segments, native allocations, mapped pages, and
GPU-driver residency, so a failed total cannot identify the owner that grew.
This is a diagnostic blind spot, not evidence that the threshold should be
raised. The unchanged gate produced a clean required closeout pass; no runtime
workaround or tolerance change was made.
**Files:** `tools/run-connected-r6-soak.ps1`;
`src/AcDream.App/Diagnostics/WorldLifecycleAutomationController.cs`;
`src/AcDream.App/Rendering/RenderFrameDiagnosticsController.cs`.
**Acceptance:** Each named soak checkpoint records the existing canonical
world-lifecycle resource snapshot (managed used/committed, tracked GPU buffers
and textures, mesh/atlas caches, composite/particle texture ownership, VFX and
pending teardown counts). Same-location assertions identify which owner grew;
process residency remains a secondary guard. Repeated clean runs pass without
loosening the canonical-owner leak limits.
---
## #231 — F-key pickup omits retail pending destination-slot presentation
**Status:** DONE (2026-07-21, `52dbb574` + `5acc3f01`)

View file

@ -1,9 +1,9 @@
# acdream — code structure & extraction sequence
**Status:** Living document. Created 2026-05-16; implementation reconciliation
completed 2026-07-21; Slices 16 and the Slice 7 draw-frame cutover landed by
2026-07-22. Slice 7 connected closeout is active before the final Slice 8
composition/shutdown cleanup and new M4 subsystems enter the App layer.
completed 2026-07-21; Slices 17 landed by 2026-07-22. The final Slice 8
composition/shutdown cleanup is active before new M4 subsystems enter the App
layer.
**Purpose:** Describe the desired structural state of the App layer,
explain the rules we've adopted, and lay out the safe extraction
sequence from today's reality (one 15,723-line `GameWindow.cs` at the
@ -644,11 +644,11 @@ counts, and a 0.8 ms update-frame p95 at the final Caul checkpoint.
smaller than the campaign baseline. TS-50, TS-51, and TS-53 remain accurately
registered; this behavior-preserving extraction introduced no new divergence.
#### Slice 7 — extract `RenderFrameOrchestrator`
#### Slice 7 — extract `RenderFrameOrchestrator` — COMPLETE 2026-07-22
Detailed execution ledger:
[`docs/plans/2026-07-22-gamewindow-slice-7-render-frame-orchestration.md`](../plans/2026-07-22-gamewindow-slice-7-render-frame-orchestration.md)
(connected closeout active).
(complete).
Move the complete draw graph and its reusable frame-local scratch state into a
GL-owning App collaborator. Preserve the exact modern pipeline order, clip
@ -667,10 +667,14 @@ value-only handoff to `RenderFrameOrchestrator`; focused resource, world,
private-presentation, and diagnostic owners contain the former frame body and
failure recovery. The Release suite passes 7,341 tests with five intentional
skips. `GameWindow` is 4,666 raw lines / 196 fields / 70 methods: 11,057 lines
(70.3%) smaller than the campaign baseline. The connected lifecycle and
resource-soak closeout remains before Slice 7 is final.
(70.3%) smaller than the campaign baseline. The 315.6-second lifecycle and
395.2-second synchronized nine-stop soak pass with code-zero graceful exits;
the six stable framebuffer checkpoints preserve the Slice 6 presentation.
Issue #232 records the coarse process-residency gate's run-to-run variance so
future diagnostics can distinguish canonical owner growth from OS/driver/GC
residency without weakening leak detection.
#### Slice 8 — composition and shutdown cleanup
#### Slice 8 — composition and shutdown cleanup — ACTIVE
Keep GL/window construction in `GameWindow.OnLoad`, but group creation into
small composition functions and delete feature state left behind by prior

View file

@ -1,6 +1,6 @@
# acdream — strategic roadmap
**Status:** Living document. Updated 2026-07-22. **M3 landed; M4 is next after the active `GameWindow` structural prerequisite.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. The current program is the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md); Slices 16 are complete and Slice 7 draw-frame orchestration is active. New M4 quest/emote/character-creation feature bodies wait until that campaign is complete. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
**Status:** Living document. Updated 2026-07-22. **M3 landed; M4 is next after the active `GameWindow` structural prerequisite.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. The current program is the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md); Slices 17 are complete and final Slice 8 composition/shutdown cleanup is active. New M4 quest/emote/character-creation feature bodies wait until that campaign is complete. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
---
@ -68,7 +68,18 @@ passes 7,182 tests / 5 skips; the 314-second lifecycle/reconnect gate and
394-second synchronized nine-stop resource soak pass with graceful exits and
stable owner counts. The completed ledger is
[`2026-07-21-gamewindow-slice-6-update-frame-orchestration.md`](2026-07-21-gamewindow-slice-6-update-frame-orchestration.md).
Slice 7 `RenderFrameOrchestrator` extraction is now active.
Slice 7 render-frame orchestration is complete. `GameWindow.OnRender` now
supplies one immutable frame input to focused resource, world-scene,
private-presentation, and diagnostic owners. Exact world/PView/alpha/portal/
paperdoll/retained-UI/ImGui/screenshot/GPU-close order and failure recovery are
pinned by tests. `GameWindow` is 4,666 raw lines / 196 fields / 70 methods,
11,057 lines (70.3%) below the campaign baseline. The Release suite passes
7,341 tests / 5 skips; the 315.6-second lifecycle/reconnect gate and 395.2-
second synchronized soak pass with graceful exits, and the six stable PNG
checkpoints preserve Slice 6 presentation. Issue #232 tracks the coarse
process-residency gate's diagnostic blind spot; no tolerance was loosened.
Final Slice 8 composition/shutdown cleanup is now active.
This is a behavior-preserving structural program. Severe regressions still get
root-cause fixes in separate commits; ordinary feature work resumes with M4

View file

@ -32,7 +32,16 @@ suite passes 7,182 tests / 5 skips; the 314-second capped/reconnect lifecycle
gate and synchronized 394-second nine-destination resource soak both pass with
graceful exits and stable owner counts. The completed Slice 6 ledger is
[`2026-07-21-gamewindow-slice-6-update-frame-orchestration.md`](2026-07-21-gamewindow-slice-6-update-frame-orchestration.md).
Slice 7 draw-frame orchestration is active.
Slice 7 draw-frame orchestration is complete. `GameWindow.OnRender` is one
typed frame handoff; resource, world-scene, private-presentation, and
diagnostic owners preserve the accepted draw/failure graph. `GameWindow` is
4,666 raw lines / 196 fields / 70 methods, down 11,057 lines (70.3%) from the
campaign baseline. The full Release suite passes 7,341 tests / 5 skips; the
315.6-second capped/reconnect lifecycle gate and 395.2-second synchronized
nine-destination soak pass with graceful exits, and six stable PNG checkpoints
preserve Slice 6 presentation. Final Slice 8 composition/shutdown cleanup is
active. Issue #232 tracks process-residency variance in the soak without
loosening its leak threshold.
Carried:
#153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus

View file

@ -1,6 +1,6 @@
# GameWindow Slice 7 — render-frame orchestration
**Status:** Active 2026-07-22.
**Status:** Complete 2026-07-22.
**Parent program:** [`docs/architecture/code-structure.md`](../architecture/code-structure.md), Slice 7.
**Baseline:** `9512404e`; `GameWindow.cs` is 7,026 raw lines, 241 fields, and
108 methods. The Release suite passes 7,182 tests / 5 fixture or environment
@ -30,7 +30,7 @@ port, or resource-lifetime redesign.
PView/fallback world branches, particles, debug world draw, and completion.
- [x] G — compose `RenderFrameOrchestrator`, cut `GameWindow.OnRender` to one
handoff, and delete obsolete frame bodies, fields, helpers, and callbacks.
- [ ] H — corrected-diff reviews, full Release suite, connected lifecycle and
- [x] H — corrected-diff reviews, full Release suite, connected lifecycle and
soak gates, framebuffer comparison, documentation, memory, and metrics.
Every checked checkpoint is one bisectable architectural commit. A checkpoint
@ -517,6 +517,22 @@ After three clean corrected-diff reviews:
8. audit architecture, divergence pointers, roadmap, milestones, issues,
`AGENTS.md`, `CLAUDE.md`, and durable memory.
Completed 2026-07-22. The 315.6-second lifecycle/reconnect gate passed at
`9d7df1bf` with six valid PNG checkpoints, code-zero graceful capped exit, and
fresh-process uncapped reconnect. Side-by-side comparison with the Slice 6
artifacts preserved world geometry, UI/paperdoll layering, private viewports,
and depth/presentation; only live weather, particle timing, authoritative
vitals, and small scripted camera-settling differences changed. The unchanged
nine-stop gate then passed in 395.2 seconds with nine materializations, all
Caul/Holtburg movement exercises, code-zero graceful shutdown, update p95 at
or below 0.8 ms, and same-location Caul plateau deltas of +85.7 MiB working set
and +59.3 MiB private memory. Two immediately preceding identical-binary runs
crossed the coarse process-residency limit while every other deterministic
lifecycle, timing, and shutdown check passed; #232 records the need to add
canonical managed/GPU/cache owner snapshots to that gate instead of weakening
its leak threshold. Release build and the complete suite remain green at 7,341
passed / 5 skipped. Slice 7 is closed with no new retail divergence.
The accepted baseline at docs-only commit `9512404e` is behavior-equivalent to
production cutover `e91f3102`: 7,182 passed / 5 skipped, 314.195-second
lifecycle/reconnect, and 393.581-second soak. Exact counters are recorded in

View file

@ -2,9 +2,9 @@
## Current state
The behavior-preserving App ownership campaign is complete through Slice 6.
The behavior-preserving App ownership campaign is complete through Slice 7.
`GameWindow.cs` moved from the 2026-07-21 baseline of 15,723 lines / 278 fields /
205 methods to 7,026 lines / 241 fields / 108 methods: 8,697 lines (55.3%) were
205 methods to 4,666 lines / 196 fields / 70 methods: 11,057 lines (70.3%) were
removed without changing accepted gameplay or rendering behavior.
| Slice | Ownership moved out | Closeout size |
@ -15,11 +15,14 @@ removed without changing accepted gameplay or rendering behavior.
| 4 | live-entity hydration, teardown, and network presentation | 10,301 / 267 / 163 |
| 5 | landblock build, publication, retirement, and shared-origin lifetime | 8,811 / 247 / 153 |
| 6 | complete update-frame orchestration | 7,026 / 241 / 108 |
| 7 | complete render-frame orchestration and failure recovery | 4,666 / 196 / 70 |
Slice 6 implementation commits are `99a3e819`, `4e4aac2c`, `0bc9fda9`,
`c5570383`, `eeb0f6b4`, `947c61d2`, and production cutover `e91f3102`.
The detailed ledgers and earlier commit sets live under `docs/plans/2026-07-21-
gamewindow-slice-*.md` and `docs/architecture/code-structure.md`.
Slice 7 implementation commits are `7e4cfb37`, `733126a2`, `bc6f09f9`,
`6d6e5b5f`, `85239fb3`, `28e1cf80`, and production cutover `9d7df1bf`.
The detailed ledgers live under `docs/plans/2026-07-2*-gamewindow-slice-*.md` and
`docs/architecture/code-structure.md`.
## Frozen update graph
@ -45,40 +48,70 @@ the session generation. Extracted phase owners query these typed runtimes and
must not create replacement dictionaries, service locators, or callback
facades into substantial `GameWindow` methods.
## Frozen render graph
`GameWindow.OnRender` creates one value-only `RenderFrameInput` and calls
`RenderFrameOrchestrator.Render`. The accepted healthy order is:
1. begin the GPU-flight transaction;
2. begin/reset frame resources, clear, and publish live resources;
3. begin the optional ImGui frame;
4. advance weather display preparation;
5. draw the complete world/PView/shared-alpha/particle/debug scene;
6. draw the portal/private viewport using the pre-private foundation snapshot;
7. refresh/draw paperdoll, retained gameplay UI, then submit ImGui;
8. capture a requested screenshot;
9. publish title/resource/frame diagnostics;
10. close the GPU-flight transaction.
Recovery is one reverse-lifetime transaction. An active ImGui frame closes
through the owning Silk controller, and text rendering restores exact borrowed
GL state on success or failure. The orchestrator and its immediate phase owners
retain no direct `GameWindow` or anonymous callback bag. Recursive reachability
through canonical UI/input owners is not frame ownership; the known paths and
review rule live in `docs/architecture/code-structure.md`.
## Accepted verification
- Release suite: 7,182 passed / 5 fixture or environment skips.
- Connected lifecycle/reconnect: 314.195 seconds, graceful close and fresh
process reconnect passed; only 25 expected world-edge empty landblocks.
- Synchronized nine-stop resource soak: 393.581 seconds, graceful exit; stable
21,025 entity and 13 animation-owner counts at the Caul return and Caul
plateau; update p95 0.8 ms. Working/private memory delta was +112.2/+111.0
MiB, inside the gate.
- The 35 missing VFX table/emitter diagnostics are known DAT-driven records,
not a Slice 6 regression.
- TS-50, TS-51, and TS-53 remain registered; Slice 6 introduced no new retail
- Release suite: 7,341 passed / 5 fixture or environment skips.
- Connected lifecycle/reconnect: 315.6 seconds, graceful capped close and fresh
process uncapped reconnect passed; only 25 expected world-edge empty
landblocks.
- The six lifecycle PNGs preserve Slice 6 world geometry, depth, UI/paperdoll,
private viewport, and presentation. Differences are live weather/particles,
authoritative vitals, and small scripted camera settling.
- Synchronized nine-stop resource soak: 395.2 seconds, nine materializations,
all movement/jump/combat exercises, and graceful exit passed; update p95 was
at or below 0.8 ms. Caul return → plateau working/private delta was
+85.7/+59.3 MiB, inside the unchanged gate.
- Two immediately preceding identical-binary runs exceeded the coarse process-
residency threshold while deterministic ownership/lifecycle/timing checks
passed. #232 adds canonical resource-owner snapshots; do not solve this by
loosening the process-memory threshold or treating residency alone as an
identified owner leak.
- The 1833 missing VFX table/emitter diagnostics are known DAT-driven records,
not a Slice 7 regression.
- TS-50, TS-51, and TS-53 remain registered; Slice 7 introduced no new retail
divergence.
## Next work
Slice 7 extracts `RenderFrameOrchestrator`: the modern draw graph, portal/PView
visibility routing, landscape/opaque/shared-alpha flushes, particles, debug
draw, paperdoll, retained UI, frame fences, and reusable frame-local scratch.
It must keep the exact accepted order and use a small immutable service set plus
explicit per-frame input. It may not become a GL service locator or call
substantial draw bodies back on `GameWindow`.
Slice 8 then groups composition and shutdown wiring and reduces Silk callbacks
to narrow calls into input, update, render, resize, focus, and shutdown owners.
Slice 8 groups composition and shutdown wiring and reduces Silk callbacks to
narrow calls into input, update, render, resize, focus, and shutdown owners.
It removes leftover feature state only where Slices 17 already established a
canonical owner; it does not redesign gameplay, rendering, or resource lifetime.
## Do not retry
- Do not reintroduce delegate facades into `GameWindow`; an ordering wrapper is
not an extraction until the state and behavior body move.
- Do not reorder the frozen update graph during structural work. TS-53 records
the known retail host-order difference for a separate evidence-backed port.
- Do not reorder the frozen update or render graphs during structural work.
TS-53 records the known retail host-order difference for a separate evidence-
backed port.
- Do not add a second GUID, session, spatial, or resource owner.
- Do not fold full `GameEntity` aggregation into this campaign; evaluate it
after Slice 8.
- Do not loosen the soak process-memory threshold to hide #232. Add canonical
owner snapshots and preserve process residency as a secondary guard.
- Small value/policy callbacks and diagnostics are acceptable only when they do
not call a substantial window body or hide mutable ownership.