175 lines
7.6 KiB
Markdown
175 lines
7.6 KiB
Markdown
# 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 — COMPLETE
|
||
|
||
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.
|
||
|
||
Landed evidence:
|
||
[`../research/2026-07-25-slice-h-a1-ui-text-cache.md`](../research/2026-07-25-slice-h-a1-ui-text-cache.md).
|
||
|
||
### H-a2 — visible cooldown participants — COMPLETE
|
||
|
||
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.
|
||
|
||
Landed evidence:
|
||
[`../research/2026-07-25-slice-h-a2-cooldown-scope.md`](../research/2026-07-25-slice-h-a2-cooldown-scope.md).
|
||
|
||
### 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.
|