docs(handoff): 2026-07-24 audit-review remediation handoff for the next agent
Condenses the adversarial review's binding findings (uncapped-capture provenance, frame-thread vs process-wide allocation attribution split, cache-undersizing reality, unattributed lock contention), the eight landed commits (both render changes user-accepted via visual pass), the ordered next-action list (baselines -> Slice A remainder -> Slice B; M4 main line wins; F/G stays user-gated), deferred issues #236-#244, and the worktree-agent base-skew gotcha. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
7b456b49d6
commit
7cb64ac2c7
1 changed files with 170 additions and 0 deletions
170
docs/research/2026-07-24-audit-review-remediation-handoff.md
Normal file
170
docs/research/2026-07-24-audit-review-remediation-handoff.md
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
# 2026-07-24 — Runtime-audit adversarial review + remediation: HANDOFF
|
||||||
|
|
||||||
|
**For:** the next agent/session picking up this work.
|
||||||
|
**State when written:** all remediation commits landed on local `main`
|
||||||
|
(`7b456b49` tip), full solution test suite green (Debug + Release build,
|
||||||
|
`dotnet test AcDream.slnx` exit 0), **user visual pass PASSED 2026-07-24**
|
||||||
|
for both render-affecting changes. Remotes deliberately not pushed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. What happened today
|
||||||
|
|
||||||
|
An independent adversarial review (43 verification agents against pinned
|
||||||
|
commit `e627d9a4`) audited both `docs/research/2026-07-24-runtime-performance-audit.md`
|
||||||
|
and `docs/plans/2026-07-24-modern-runtime-architecture.md`. Verdict:
|
||||||
|
**APPROVE WITH CHANGES for both** — the audit's code-level diagnosis was
|
||||||
|
almost entirely correct (12/12 spot-checked file:line citations accurate),
|
||||||
|
but its measurement provenance was not, and the plan inherited gates its
|
||||||
|
tooling could not measure plus one governance hole. The user then approved
|
||||||
|
executing the five headline recommendations, which are now done.
|
||||||
|
|
||||||
|
## 2. Review findings that must not be re-litigated (all verified at file:line)
|
||||||
|
|
||||||
|
**Corrections to the audit (now recorded as audit §13 errata — read it
|
||||||
|
before citing the audit's §1/§2/§4 numbers):**
|
||||||
|
|
||||||
|
1. The capture ran **forced-uncapped** (`ACDREAM_UNCAPPED_RENDER=1` set
|
||||||
|
unconditionally by the soak script) with undisclosed
|
||||||
|
`ACDREAM_DUMP_MOVE_TRUTH=1`; "normal capped presentation" was false —
|
||||||
|
the 32 FPS ceiling was purely the RDP display path. Unresolved wrinkle:
|
||||||
|
the CPU trace's 6.44% `FramePacingController.CompleteFrame` should be a
|
||||||
|
no-op under those flags (launcher provenance is muddy).
|
||||||
|
2. The headline **203.6 MiB "single-frame allocation" is frame-thread-only**
|
||||||
|
(`GC.GetAllocatedBytesForCurrentThread`); worker-side `MeshExtractor`
|
||||||
|
decode structurally cannot be in it. The frame spike belongs to
|
||||||
|
main-thread publication/retirement (**Slice E owns it**); the pak
|
||||||
|
(**Slices B/C**) owns the process-wide 40.8 MB/s rate, Gen-2 pressure,
|
||||||
|
and 256 ms GC pauses. Win attribution must respect that split.
|
||||||
|
3. 65% LOH fragmentation (524 MB of 807 MB) sat unanalyzed in the audit's
|
||||||
|
own JSON — the best committed explanation of the committed-vs-live gap.
|
||||||
|
4. Exception figures: only the focused-trace 1,587 (1,335 AOOR + 252
|
||||||
|
socket) are verifiable; the plan's old "4,520 + 1,168" had no committed
|
||||||
|
derivation (plan §1 row corrected).
|
||||||
|
5. gen0=99 < gen1=105 is legal (.NET 10 meter reports per-generation
|
||||||
|
EXCLUSIVE counts; ≈242 total GCs); "38 Gen-2" stands.
|
||||||
|
6. GiB conversions were MiB/1000 (true peaks: 1.62 GiB WS / 2.22 GiB
|
||||||
|
private); committed-heap peak was 1,242–1,298 MiB, not 830.6.
|
||||||
|
|
||||||
|
**Pivotal confirmations (the audit was right):** the streaming
|
||||||
|
budget-bypass is real (`MaxCompletionsPerFrame=4` count budget; unloads +
|
||||||
|
teleport priority-ring apply uncapped; `BeginFullWindowRetirement` retires
|
||||||
|
~600 landblocks in one frame); `LandblockRetirementCoordinator.RunForEachEntity`
|
||||||
|
is unmetered; `LandblockStaticPresentationPublisher` rebuilds dicts/sets/sorts
|
||||||
|
per publication (plus a third dictionary + per-attempt re-sort the audit
|
||||||
|
missed); `ResolveActivation` probes every static id as Setup with a bare
|
||||||
|
catch and no negative cache anywhere; `InteriorEntityPartition.Partition`
|
||||||
|
walks all resident entities per frame with its AABB parameter unused
|
||||||
|
(nuance: far-tier blocks are entity-stripped, so the walk is bounded by
|
||||||
|
near-tier + live); `GpuFrameTimer` gpu_ms is boundary-to-boundary and
|
||||||
|
invalid under a cap; the `viewport-before-ready` barrier is real but
|
||||||
|
observational-only today (never gates reveal).
|
||||||
|
|
||||||
|
**Cache reality (correction to the audit's framing):** four bounded LRU
|
||||||
|
tiers already front the mesh/texture path (GPU render-data 1 GiB/50 obj;
|
||||||
|
CPU mesh 128 MiB/100; decoded-texture 64 MiB/128; DAT typed-object
|
||||||
|
64 MiB/256 ×4) — revisits rebuild because they are UNDERSIZED vs the
|
||||||
|
route's working set (~599 textures), not because caching is absent. Real
|
||||||
|
fence-gated eviction exists for atlases/composites/arena — the route never
|
||||||
|
pushed the ceilings. **Slice D = unify accounting + retune, not rebuild.**
|
||||||
|
|
||||||
|
**Lock contention (4,614) is unattributed** — no stacks were captured.
|
||||||
|
Leading candidates: `_datLock` (whole-landblock build vs render-thread
|
||||||
|
CreateObject hydration — a known 2026-06-23 campaign; portal windows are
|
||||||
|
exactly its worst case) and `ObjectMeshManager._pendingRequests`, not only
|
||||||
|
the DAT typed-object lock the audit named.
|
||||||
|
|
||||||
|
## 3. What was executed (all on local `main`, in order)
|
||||||
|
|
||||||
|
| Commit | Content |
|
||||||
|
|---|---|
|
||||||
|
| `38e14c6a` | **docs:** audit errata §13 + plan amendments — §0 governance (F/G user gate, side-track session discipline, freeze-exception scope for H-c/J, evidence corrections, baseline prerequisite blocking Slice C), Slice A/C/D/E/F/G/H/I/J/K contracts, §11 gate corrections, §12 adjudication protocol, §14 order incl. Slice I |
|
||||||
|
| `c2cb83d1` | **EnvCellRenderer prepare gate** — the dead `NeedsPrepare` wired into a real dirty gate (landblock changes, filter content, trim, new `ObjectMeshManager.RenderDataAvailabilityVersion`, camera = 1 mm ABSOLUTE eye epsilon + rows-1–3 relative 1e-5; a matrix-relative epsilon would mask sub-meter motion at AC's ~5e4 coords). Pool-cursor discipline verified safe. **USER-ACCEPTED (visual pass 2026-07-24).** |
|
||||||
|
| `cf253304` | **net:** receive-thread no longer dies on stray SocketException — `SIO_UDP_CONNRESET` suppression, per-iteration catch/continue+log, setsockopt hoist; deterministic loop-resilience tests |
|
||||||
|
| `a4b1214e` | **dead code:** ParticleBatcher/ParticleEmitterRenderer/ActiveParticleEmitter chain deleted (+ orphaned EmbeddedResourceReader + wb_particle shaders); production particle path untouched. **USER-ACCEPTED (visual pass).** |
|
||||||
|
| `60bc3139` | **MeshExtractor:** CellStruct clip-map clone guard (was unconditional), solid-color texture cache (clone-protect flag wired), redundant double `.ToList()` dropped (Portal-wins ordering untouched) |
|
||||||
|
| `1e9031e7` | **audio:** `DatSoundCache` 32 MiB LRU + negative set; OpenAL buffer 48 MiB budget with attachment-safe eviction; 19 tests |
|
||||||
|
| `bfc5e473` | **ISSUES #236–#244** — deferred P2 findings (see §5) |
|
||||||
|
| `7b456b49` | **measurement tooling:** `ACDREAM_FRAME_HISTORY=<path>` per-frame CSV export (zero frame-thread I/O, written at Dispose); checkpoint JSON gains LOH size/fragmentation, process-total-allocated, and hit/miss/evict counters for the CPU-mesh/decoded-texture/DAT caches; soak script gains `-Uncapped` switch (**default is now CAPPED**), 26 s dwell fix, per-run `env-disclosure.json` |
|
||||||
|
|
||||||
|
Memory updated: `feedback_agent_worktree_base` (new — see §6),
|
||||||
|
`project_mp_track_findings` (2026-07-24 update block; EnvCell rebuild gate
|
||||||
|
was its parked MP-Alloc item, now landed + accepted).
|
||||||
|
|
||||||
|
## 4. Next actions, in order (the incoming agent's decision space)
|
||||||
|
|
||||||
|
1. **Mint the baselines** (measurement, no code; plan §0.5 blocks Slice C on
|
||||||
|
these): one capped nine-stop soak (new script default) + one `-Uncapped`
|
||||||
|
soak; the AUTHORITATIVE uncapped-local run needs the user at the
|
||||||
|
physical display (not RDP). ACE was up on 127.0.0.1:9000. Command:
|
||||||
|
`.\tools\run-connected-r6-soak.ps1 -Repository (Get-Location).Path -SkipBuild [-Uncapped]`
|
||||||
|
with `ACDREAM_TEST_USER/PASS` set; artifacts land in the automation dir +
|
||||||
|
commit the JSON/CSV like the 2026-07-24 set. Set `ACDREAM_FRAME_HISTORY`
|
||||||
|
for the per-frame export.
|
||||||
|
2. **Slice A remainder** (small coding): pinned dense-town scene baseline
|
||||||
|
(pick Arwic or Fort Tethana, pin camera in a route file),
|
||||||
|
screenshot-diff tool + match rule, contention-stack capture
|
||||||
|
(`dotnet-trace` Contention keyword) on the route, a percentile script
|
||||||
|
over the per-frame CSV, the committed reference-config block.
|
||||||
|
3. **Then Slice B** (EnvCell geomId dedup + full pak bake) in dedicated MP
|
||||||
|
side-track sessions — first real plan slice.
|
||||||
|
4. **Main line always wins:** M4's six-slice world-interaction program is
|
||||||
|
the active milestone critical path; MP work is side-track-only (plan §0.2).
|
||||||
|
5. **Fillers (one commit each):** #236 UiText cache and #241 partition
|
||||||
|
frustum cull are the best value; #237 Transition pooling stays gated on
|
||||||
|
Slice I lifetime tests.
|
||||||
|
6. **Do NOT start Slices F/G** without the user's recorded go-ahead
|
||||||
|
(plan §0.1 — they resume the deferred 2026-07-05 MP3/ECS decision; the
|
||||||
|
prior "GPU-bound ~200fps" evidence is invalidated by the GpuFrameTimer
|
||||||
|
artifact, so the question stays open until the corrected uncapped-local
|
||||||
|
profile exists post-Slice-E).
|
||||||
|
|
||||||
|
## 5. Deferred, filed, and known-not-done
|
||||||
|
|
||||||
|
- **ISSUES #236–#244:** UiText per-frame re-wrap; Transition per-resolve
|
||||||
|
allocation graph; EquippedChildRenderController double-tick + ToArray
|
||||||
|
snapshots; inbound per-packet allocation chain; RetailAnimationLoader
|
||||||
|
unbounded cache; partition landblock frustum cull; publisher third
|
||||||
|
dictionary/per-attempt re-sort; `_boundsCache` bound; SequencerFactory
|
||||||
|
unguarded Setup probe + `[dat-miss]` under-lock logging.
|
||||||
|
- **Remotes:** local `main` is 30+ commits ahead of `origin` and `github`
|
||||||
|
(both at `20e2998a`). Deliberately not pushed — prior convention says
|
||||||
|
local main is the truth; push with `git push origin main github main`
|
||||||
|
(or per-remote) when the user wants the stack published.
|
||||||
|
- **No baseline soak was run yet** (held to avoid colliding with the
|
||||||
|
user's visual-pass session). The tooling is validated by contract tests
|
||||||
|
+ a clean PS1 parse only.
|
||||||
|
- The audit's raw artifacts remain uncommitted (by design); several §4
|
||||||
|
numbers stay reproducible-not-reviewed until the Slice A recapture.
|
||||||
|
|
||||||
|
## 6. Gotchas for the incoming agent
|
||||||
|
|
||||||
|
- **Worktree-agent base skew:** Agent-tool worktrees in this repo were
|
||||||
|
created from the REMOTE tip (`20e2998a`), ~90 commits behind local main.
|
||||||
|
Always have agents report their worktree HEAD, run
|
||||||
|
`git diff --name-only <agentBase> <target> -- <touched files>` before
|
||||||
|
cherry-picking, and re-run the full suite on the target tree. (Memory:
|
||||||
|
`feedback_agent_worktree_base`.)
|
||||||
|
- The four agent worktrees from this session
|
||||||
|
(`.claude/worktrees/agent-*`) were removed after their commits were
|
||||||
|
cherry-picked; `vigorous-joliot-f0c3ad` was detached from `main` so the
|
||||||
|
primary tree could check it out — it still exists, detached at `e627d9a4`.
|
||||||
|
- The soak script's route gating GREPS `move-truth OUT` lines —
|
||||||
|
`ACDREAM_DUMP_MOVE_TRUTH` must stay enabled for soak runs (now disclosed
|
||||||
|
via `env-disclosure.json`, not hidden).
|
||||||
|
- Plan §14's "landed post-review" notes mark work done today — do not
|
||||||
|
redo it when executing slices.
|
||||||
|
|
||||||
|
## 7. Pointers
|
||||||
|
|
||||||
|
- Audit + errata: `docs/research/2026-07-24-runtime-performance-audit.md` (§13)
|
||||||
|
- Amended plan: `docs/plans/2026-07-24-modern-runtime-architecture.md` (§0 first)
|
||||||
|
- Issues: `docs/ISSUES.md` #236–#244 (+ current queue block)
|
||||||
|
- Memory: `claude-memory/project_mp_track_findings.md` (2026-07-24 update),
|
||||||
|
`claude-memory/feedback_agent_worktree_base.md`,
|
||||||
|
`claude-memory/project_render_pipeline_digest.md` (unchanged, still the
|
||||||
|
render SSOT)
|
||||||
|
- Full review structure (A–G: verdict, findings, benchmark/architecture
|
||||||
|
assessments, revised execution order, acceptance matrix) was delivered
|
||||||
|
in-session 2026-07-24; its actionable content is fully folded into the
|
||||||
|
errata, the plan amendments, the issues above, and this handoff.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue