diff --git a/docs/plans/2026-07-24-modern-runtime-architecture.md b/docs/plans/2026-07-24-modern-runtime-architecture.md index 45a5d6cc..c9da2d15 100644 --- a/docs/plans/2026-07-24-modern-runtime-architecture.md +++ b/docs/plans/2026-07-24-modern-runtime-architecture.md @@ -883,6 +883,12 @@ proportional to resident content. **Purpose:** Remove remaining work that scales with uncapped FPS. +**Execution plan (active 2026-07-25):** +[`2026-07-25-modern-runtime-slice-h.md`](2026-07-25-modern-runtime-slice-h.md). +The plan separates H-a text/UI/attachment/frame work, H-b's exact light-set +optimization, and H-c's ordered network-I/O change into independently +revertible gates. + - Skip diagnostics with no consumer and reuse renderer visibility facts. - Dirty-layout retained UI: apply anchors only after geometry changes. - Maintain an overlay-participant registry instead of a second full-tree walk. diff --git a/docs/plans/2026-07-25-modern-runtime-slice-h.md b/docs/plans/2026-07-25-modern-runtime-slice-h.md new file mode 100644 index 00000000..b812ac12 --- /dev/null +++ b/docs/plans/2026-07-25-modern-runtime-slice-h.md @@ -0,0 +1,169 @@ +# Modern runtime Slice H execution plan + +**Status:** ACTIVE +**Parent plan:** `2026-07-24-modern-runtime-architecture.md`, Slice H +**Prerequisite state:** Slice G4 production cutover is automated-gated; its +user visual gate remains pending. + +## 1. Safety boundary + +Slice H removes work which scales with presentation rate. It does not change +retail gameplay rules, visible-cell authority, light membership, packet +ordering, acknowledgement timing, heartbeat placement, or UI presentation. + +The G4 old-route referee remains available until the user accepts the visual +gate. Slice H must not delete or alter that rollback boundary. + +If the G4 visual result is wrong, revert only: + +```text +git revert ef1d263337997bb030eadb7b8e71d73dc659907a +``` + +Do not reset history and do not revert G3. The portal-warmup corrections +`129dd77d` and `03b10183` are independent of the retained draw-source cutover. + +## 2. H-a — retained UI, live attachments, diagnostics, and frame scratch + +### H-a1 — cached shaped text + +1. Add a small retained text-layout cache keyed by source revision/value plus + width, padding, color, and font identity. +2. Convert appraisal item, inscription, spell, creature, character-info, and + active-effect detail providers so expensive report construction and + wrapping occur only after source or layout changes. +3. Preserve `UiText.LinesProvider` as the rendering seam. Dynamic one-line + widgets remain dynamic; this change is limited to report/wrapped content. +4. Ensure selection, appraisal response, component count, enchantment, + character-property, font, and resize changes invalidate the right cache. +5. Add tests proving stable draws return the same line collection while source + and geometry changes rebuild it. + +Gate: the existing appraisal/character/effect behavior tests remain unchanged, +and repeated stable provider polls allocate no report/wrap objects. + +### H-a2 — visible cooldown participants + +1. Keep the shared retail heartbeat and one cooldown result per represented + item. +2. Index mounted `UiItemList` participants once at bind time. +3. At heartbeat, visit only lists whose complete ancestor chain is visible. + Hidden panels keep no stale visual state: their slots query zero while + hidden and are refreshed on the first visible heartbeat. +4. Keep future-slot support and shared-group behavior. + +Gate: hidden inventory, equipment, external-container, vendor, and spell-bar +lists are not scanned; reopening immediately displays the authoritative +cooldown step. + +### H-a3 — equipped-child transition work + +1. Preserve both frame ordering points: pre-network presentation and + post-network spatial reconciliation have different authority boundaries. +2. Split transition retry from pose recomposition. +3. Run the complete parent-first pose walk once after animation. +4. In the post-network phase, recompose only attachments dirtied by accepted + root/relation/appearance changes. +5. Replace mutation-safe dictionary `ToArray` snapshots with retained key + scratch buffers. Callback reentrancy still observes the same transition + generation checks. + +Gate: equip, unparent, reparent, pose loss, rollback, delete, GUID reuse, and +subtree-withdrawal suites preserve exact event and resource counts. + +### H-a4 — diagnostics and frame scratch + +1. Reuse one synchronous `RetailPViewFrameInput` owned by + `WorldSceneRenderer`; reset every field before each draw. +2. Expose stable borrowed landblock entry/bounds views instead of creating + iterator state in each frame. +3. Consumer-gate diagnostic landblock visibility counting and shadow + enumeration. When no DebugVM/collision/probe consumer exists, publish a + neutral diagnostic outcome without scanning resident landblocks. +4. Do not rework `InteriorEntityPartition` while the G4 referee remains. + Issue #241 closes with G5 old-route deletion, not by editing the fallback. +5. Profile capped and uncapped production paths and retain evidence. + +Gate: identical framebuffer/scene digest, no per-frame PView input allocation, +and no diagnostic world traversal with all consumers disabled. + +## 3. H-b — exact light top-k + +Retail anchors: + +- `CEnvCell::add_dynamic_lights` at `0x0052D410` +- `Render::insert_light` at `0x0054D1B0` +- `Render::add_dynamic_light` at `0x0054D420` +- global caps at `0x0081EC94` / `0x0081EC98` + +Execution: + +1. Preserve the resident `_all` registry and existing visible-cell filter. +2. Preserve dynamics-first ordering and squared distance from the player. +3. Replace only the over-cap complete sort with a bounded exact top-k + selection. +4. Define tie-breaking from the existing comparator so the selected set and + final submission order are identical, including equal-distance fixtures. +5. Differential-test randomized candidate sets and the captured 463-light Town + Network fixture against the old full-sort oracle. +6. Run the fixed-camera screenshot comparison and connected light gate. + +Gate: identical selected IDs and submission order for every fixture, identical +Town Network screenshot, reduced overflow CPU/allocation, and AP-85 retired +only after the visual evidence passes. + +## 4. H-c — ordered, allocation-conscious network I/O + +Retail/transport invariants: + +- one outstanding receive; +- kernel datagram arrival order remains inbound queue order; +- one acknowledgement decision per accepted packet; +- `LinkStatusHolder::OnHeartbeat` at `0x004113D0` remains at the same + last-heard point; +- `PumpOnce` handshake pacing remains unchanged; +- fragmented message assembly and sequence gates remain authoritative. + +Execution: + +1. Capture allocation and ordering baselines for login, idle, motion, portal, + appraisal, container, and combat traffic. +2. Introduce a single cancellable socket receive owner using reusable/pool + storage. +3. Decode packet headers and fragments from spans/borrowed storage. +4. Copy only payloads whose lifetime crosses the receive/dispatch boundary; + pooled receive memory is never returned while referenced. +5. Replace outbound temporary arrays with span/list segment writes where the + socket API permits. +6. Prove cancellation, remote close, malformed packet, receive fault, fragment + reassembly, queue backpressure, and reconnect cleanup. +7. Run connected lifecycle, reconnect, portal, interaction, and soak gates. + +Gate: identical decoded event/ack traces, no receive-thread death, no pooled +buffer lifetime violation, and materially reduced bytes per packet. + +## 5. Commit and evidence order + +Each numbered unit lands as a bisectable commit after focused tests, App +Release, complete Release, and documentation reconciliation: + +1. H-a1 cached shaped text. +2. H-a2 cooldown visibility. +3. H-a3 attachment retry/recomposition. +4. H-a4 diagnostics/frame scratch. +5. H-b exact light top-k. +6. H-c network receive/decode/send allocations. +7. Slice-H connected measurements and closeout. + +Raw captures stay under `.test-out/` or `logs/`; reviewed summaries and compact +fixtures are committed under `docs/research/` or the matching test project. + +## 6. Deferred boundaries + +- Physics `Transition` pooling (#237) remains Slice I and requires reset- + completeness/identity tests first. +- G5 old-route/referee deletion waits for the user's G4 visual acceptance. +- Static publication indexing (#242) is not silently folded into H; it is + measured after H-a and scheduled only if still material. +- Slices I–L start only after Slice H is measured and documented, but no + additional authorization is required.