acdream/docs/plans/2026-07-25-modern-runtime-slice-h.md

11 KiB
Raw Blame History

Modern runtime Slice H execution plan

Status: COMPLETE (2026-07-25) 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:

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.

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.

H-a3 — equipped-child transition work — COMPLETE

  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.

Landed evidence: ../research/2026-07-25-slice-h-a3-attached-pose-reconcile.md.

H-a4 — diagnostics and frame scratch — COMPLETE

  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 optional shadow enumeration. Preserve landblock visibility counting because the normal title and lifecycle checkpoints are active consumers of lb V/T; neutralizing it would be a visible/automation behavior change.
  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, no iterator allocation for stable landblock views, and no shadow traversal with all optional consumers disabled.

Landed evidence: ../research/2026-07-25-slice-h-a4-frame-scratch.md.

3. H-b — exact light top-k — COMPLETE

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.

Landed evidence: ../research/2026-07-25-slice-h-b-light-top-k-report.md. The deterministic differential fixtures preserve exact accepted output; the 463-light diagnostic microbenchmark reduced selection CPU time by 29.1% with zero warmed allocations. AP-85 remains open because its retail dual-pool behavior is outside this performance-only unit.

4. H-c — ordered, allocation-conscious network I/O

H-c is executed as three independently reversible units:

  1. H-c1 — pooled receive owner — COMPLETE. One cancellable async socket receive, a retained full-size edge buffer, right-sized pooled FIFO datagrams, unchanged blocking handshake cadence, and direct span sends. Evidence: ../research/2026-07-25-slice-h-c1-pooled-receive-owner.md.
  2. H-c2 — borrowed decode — COMPLETE. Parse and verify headers, optional fields, and fragments as borrowed views. Copy only multi-fragment state that must survive the current datagram. Evidence: ../research/2026-07-25-slice-h-c2-borrowed-packet-decode.md.
  3. H-c3 — direct outbound framing — COMPLETE. Write packet and fragment framing into caller storage and remove intermediate payload arrays. Evidence: ../research/2026-07-25-slice-h-c3-direct-outbound-framing.md.

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 IL start only after Slice H is measured and documented, but no additional authorization is required.

7. Closeout

All H-a, H-b, and H-c implementation units are complete. The Release build and complete solution pass 8,292 tests with 5 skips. The connected login/portal/dungeon/revisit/graceful-disconnect/fresh-process-reconnect gate passed on commit 41c1a593927fcf71ef83b4825c659a4970e9b858 with all seven checkpoints ready, no invariant or transport failure, and both sessions closing through the normal logout path.

The connected automation deliberately constructs the retained G4 current-path oracle, so its scene-sized per-frame allocation is comparison-instrumentation cost and not representative of production. A separate normal uncapped Release session, with neither lifecycle automation nor the oracle composed, stabilized at 25.6 KiB/frame and roughly 500 presented frames/second under RDP. Allocation stack attribution identifies the remaining dominant production owners as Transition query scratch (Slice I) and the retained current partition/referee path (G5). The H-owned packet decode and recurring outbound framing paths independently allocate zero bytes when warm. The program-wide 4 KiB/frame target therefore remains an end-of-G5/Slice-I acceptance condition rather than being misreported as achieved by H alone.

Closeout evidence: ../research/2026-07-25-slice-h-closeout.md.