docs: the overnight consolidation report, open questions first
Adds `docs/reports/2026-07-29-overnight-report.md` and brings the Campaign V report page's status section in line with what is actually true. The report leads with what needs the user, because most of it is genuinely blocked rather than merely unfinished: the #259 reboot and the five V11 runtime gates behind it, the enum campaign's three decisions (adopt `WeenieError` wholesale? adopt retail's `SoundId` table or record our subset as a divergence? re-clone the reference repos), the wire audit's one instrumented session, and the walked-portal follow-up for #256/#257. Then what landed, with numbers, then Campaign V's final state. Two notes worth surfacing rather than burying. `references/` is empty **in the main checkout**, not just in a worktree — which is why 456 of the enum campaign's 864 property members are single-sourced, and why CLAUDE.md's "cross-reference at least two of them" is currently unexecutable as written. And two `MEMORY.md` entries index research documents that exist nowhere: not in the tree, not under any ref, and the memory directory has no `research/` folder at all. Two separate sessions hit that wall tonight and both regenerated from scratch. User-level memory is out of my reach, so it is recorded as a needs-user item with the two documents that supersede them. The Campaign V page said V8 was running, V9 pending and V10/V11 ahead. All four have landed. Its status section now records the deletion (204 files, +1,870 / -27,607), the three findings worth keeping — Chorizite survives on the pak format rather than on `IUniformBuffer`, `Studio/SampleData.cs` was production code, and `WbMeshAdapter.Dispose()`'s GPU-work wait had been silently dead since V6a — and, plainly, that the runtime gates did not run because this machine cannot create a Win32 Vulkan surface for any process. A gate that could not run is not a gate that passed. The #248 and #250 entries are updated to DONE with their outstanding halves named. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
200f19ce47
commit
b023ac95f0
2 changed files with 477 additions and 27 deletions
|
|
@ -238,31 +238,57 @@ that mattered. That's the campaign's per-slice discipline working as intended:
|
||||||
|
|
||||||
## Current status
|
## Current status
|
||||||
|
|
||||||
- **V8 (performance gate)** is **running**. Its first commit landed the
|
> **Updated 2026-07-29.** The campaign is **complete**. V8 through V11 have all
|
||||||
missing instrument: the Vulkan arm had been silently wired to
|
> landed; the tree is statically green and OpenGL is gone. What remains is
|
||||||
`NullRenderFrameGpuMeasurement` and emitted no `[frame-prof]` line at all, so
|
> runtime evidence for V11, which is blocked by a **machine fault rather than a
|
||||||
the campaign's own performance tooling had nothing to point at it. GPU
|
> campaign result** — see below and
|
||||||
timestamp measurement now brackets identically on both arms. The acceptance
|
> [`2026-07-29-overnight-report.md`](2026-07-29-overnight-report.md) §1.1.
|
||||||
table (CPU frame p50 ≤ 1.60 ms, GPU p50 ≤ 1.00 ms, working set ≤ 600 MiB,
|
|
||||||
private set ≤ 860 MiB, 0 B/frame managed allocation, CPU/GPU p99 ≤ GL) is the
|
- **V8 (performance gate)**, **V9 (Linux CI)** and **V10 (cutover)** are
|
||||||
next thing this slice measures against the RX 9070 XT.
|
**complete**. V8's first commit landed the missing instrument: the Vulkan arm
|
||||||
- **V9 (Linux CI)** is **implemented, first CI run pending**. A `linux-vulkan`
|
had been silently wired to `NullRenderFrameGpuMeasurement` and emitted no
|
||||||
job now runs the probe on lavapipe under Xvfb, asserts a clean accepting
|
`[frame-prof]` line at all, so the campaign's own performance tooling had
|
||||||
verdict, checks the forced-unsupported exit-4 path, and verifies committed
|
nothing to point at it. V9's `linux-vulkan` job runs the probe on lavapipe
|
||||||
`.spv` binaries are byte-identical to a fresh compile. lavapipe satisfies
|
under Xvfb, asserts a clean accepting verdict, checks the forced-unsupported
|
||||||
every one of the seventeen gated features, including `samplerAnisotropy`,
|
exit-4 path, and verifies committed `.spv` binaries are byte-identical to a
|
||||||
which V7 made load-bearing. The physical Linux GPU row and Wayland stay
|
fresh compile. V10 made Vulkan the default backend behind the user's visual
|
||||||
deferred on the same precedent as Slice L.
|
sign-off; the one open finding from that session is #253 below. The physical
|
||||||
- **V10 (cutover)** is **ahead**: Vulkan becomes the default backend, GL stays
|
Linux GPU row and Wayland stay deferred on the same precedent as Slice L.
|
||||||
reachable by environment variable for one further slice, and **user visual
|
- **V11 (closeout)** is **deleted and statically green; runtime gates
|
||||||
sign-off** is the gate — the same kind of connected session the user already
|
outstanding.** Five commits (`844cf092` → `c265b52d`) removed **27,607 lines
|
||||||
ran once mid-campaign (six targeted checks, all passed with merits: the AD-46
|
against 1,870 added** across 204 files. `Gpu/Gl`, `OpenGLGraphicsDevice`, the
|
||||||
treeline judged invisible in practice, dyed-gear composites, doorway
|
`ManagedGL*` stack, `GLHelpers`, `GLStateScope`, both render-state caches,
|
||||||
look-out/threshold crossing, stacked translucency, icon/text crispness, and
|
`BindlessSupport`, `GraphicalGlFunctionProbe`, the ImGui project, the Studio
|
||||||
motion feel — the one open finding from that session is #253 below).
|
tree, the `ui-studio` verb, `RenderBackendKind` and the
|
||||||
- **V11 (closeout)** deletes `Gpu/Gl`, `OpenGLGraphicsDevice`, the
|
`ACDREAM_RENDER_BACKEND` escape hatch are all gone. `Silk.NET.OpenGL` and
|
||||||
`ManagedGL*` stack, the ImGui developer stack, and UI Studio, and re-measures
|
`.Extensions.ARB` are dropped — **final reference count zero**. 9/9 shader
|
||||||
working set one final time.
|
pairs recompile.
|
||||||
|
|
||||||
|
**Three findings from the deletion.** *Chorizite could not be dropped*, and not
|
||||||
|
for the reason the risk register predicted: `TextureFormat` sits in the
|
||||||
|
`IWorldTextureArray.CreateClampedArray` signature the **Vulkan** path
|
||||||
|
implements, and `BoundingBox` is a **serialized type in the pak format**, so
|
||||||
|
removing it touches the on-disk format and is its own slice.
|
||||||
|
*`Studio/SampleData.cs` was production code*, not devtools —
|
||||||
|
`InteractionRetainedUiComposition` uses it as the character sheet's fallback —
|
||||||
|
so it was moved, not deleted. And *one real bug fell out*:
|
||||||
|
`WbMeshAdapter.Dispose()` was still pattern-matching the deleted
|
||||||
|
`GpuFrameFlightController` to decide whether to wait for submitted GPU work.
|
||||||
|
`VulkanFrameFlightController` replaced that type at V6a and the site was never
|
||||||
|
updated, so **the wait had been silently dead on every Vulkan run since V6a**.
|
||||||
|
Deleting the GL type is what turned a no-op into a compile error.
|
||||||
|
|
||||||
|
**Why the runtime gates did not run.** The offline pixel gate died at startup in
|
||||||
|
`vkGetPhysicalDeviceSurfaceCapabilitiesKHR`. Bisecting put the fault outside the
|
||||||
|
tree — the client fails identically at a pre-V11 commit whose offline capture had
|
||||||
|
succeeded three hours earlier — and `vulkaninfo --summary`, a Khronos tool
|
||||||
|
containing no acdream code, fails at the same call. Win32 surface creation is
|
||||||
|
broken process-wide on this machine ([#259](../ISSUES.md)); Vulkan itself is
|
||||||
|
healthy and both adapters report 1.4. Nothing was relaxed to manufacture a pass
|
||||||
|
and nothing was declared green on a prediction — a gate that could not run is not
|
||||||
|
a gate that passed. The outstanding commands are listed in the overnight report;
|
||||||
|
the pre-deletion baseline for the self-differential is already on disk at
|
||||||
|
`artifacts/v11-pre`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -271,7 +297,10 @@ that mattered. That's the campaign's per-slice discipline working as intended:
|
||||||
- **[#248](../ISSUES.md)** — `FrustumCuller` extracts its near plane with the
|
- **[#248](../ISSUES.md)** — `FrustumCuller` extracts its near plane with the
|
||||||
GL `[-1,1]`-NDC formula against a `[0,1]`-NDC projection; harmless today
|
GL `[-1,1]`-NDC formula against a `[0,1]`-NDC projection; harmless today
|
||||||
(makes culling strictly more permissive near the eye) but wrong hygiene.
|
(makes culling strictly more permissive near the eye) but wrong hygiene.
|
||||||
OPEN.
|
**DONE 2026-07-29** — `near = Normalize(col3)`, pinned by a theory asserting
|
||||||
|
the extracted near distance equals the camera's near value across four
|
||||||
|
near/far pairs; the old formula fails all four. The gate half of its
|
||||||
|
acceptance (offline pixel gate + connected route) is outstanding under #259.
|
||||||
- **#249** — Released bindless texture slots never call `MakeNonResident`
|
- **#249** — Released bindless texture slots never call `MakeNonResident`
|
||||||
before the texture is deleted, which `GL_ARB_bindless_texture` leaves
|
before the texture is deleted, which `GL_ARB_bindless_texture` leaves
|
||||||
undefined, and leaks a resident handle for the process lifetime per release.
|
undefined, and leaks a resident handle for the process lifetime per release.
|
||||||
|
|
@ -279,7 +308,14 @@ that mattered. That's the campaign's per-slice discipline working as intended:
|
||||||
- **#250** — Four "zero managed allocation" tests fail intermittently, roughly
|
- **#250** — Four "zero managed allocation" tests fail intermittently, roughly
|
||||||
one run in three, from tiered-JIT/GC measurement noise rather than a real
|
one run in three, from tiered-JIT/GC measurement noise rather than a real
|
||||||
regression — but an acceptance-gating test that flakes trains everyone to
|
regression — but an acceptance-gating test that flakes trains everyone to
|
||||||
re-run until green. OPEN.
|
re-run until green. **DONE 2026-07-29**, and it was not noise: in all four the
|
||||||
|
measured window was never the warmed path — two measured a thousand-iteration
|
||||||
|
loop written inline (which on-stack replacement rewrites mid-flight, on the
|
||||||
|
measuring thread), and two measured a code path the warmup had never taken.
|
||||||
|
Fixed with a shared `ZeroAllocationProbe` that measures already-warmed batches
|
||||||
|
and reports their minimum; **the zero bound is unchanged and the apparatus has
|
||||||
|
its own tests proving it can still fail.** The family turned out to be ten
|
||||||
|
tests, not four. 20/20 clean App-suite runs.
|
||||||
- **#251** — `glClientWaitSync` returned a fence status of `0` (not a value
|
- **#251** — `glClientWaitSync` returned a fence status of `0` (not a value
|
||||||
the API is specified to return) and crashed the render loop once in nine
|
the API is specified to return) and crashed the render loop once in nine
|
||||||
connected runs; possibly the same below-the-API driver family the
|
connected runs; possibly the same below-the-API driver family the
|
||||||
|
|
|
||||||
414
docs/reports/2026-07-29-overnight-report.md
Normal file
414
docs/reports/2026-07-29-overnight-report.md
Normal file
|
|
@ -0,0 +1,414 @@
|
||||||
|
# Overnight consolidation — 2026-07-29
|
||||||
|
|
||||||
|
**Branch:** `claude/git-sync-status-5fb1d2`
|
||||||
|
**Started at:** `d312bd2f` (Campaign V slice V11 landed; OpenGL deleted)
|
||||||
|
**Sessions merged:** the enum verification campaign and the wire-stack audit
|
||||||
|
**Machine constraint:** [#259](../ISSUES.md) — Win32 Vulkan surface creation is
|
||||||
|
broken process-wide, so **no client was launched**. Everything below is build,
|
||||||
|
test and documentation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. What needs you
|
||||||
|
|
||||||
|
Open questions first, because several of them gate work that is otherwise ready
|
||||||
|
to start. Nothing here is blocked on more analysis — each one needs a decision or
|
||||||
|
a machine that can make a window.
|
||||||
|
|
||||||
|
### 1.1 Reboot the machine, then run five gates
|
||||||
|
|
||||||
|
`vulkaninfo --summary` — a Khronos tool containing no acdream code — fails at
|
||||||
|
`vkGetPhysicalDeviceSurfaceCapabilitiesKHR` with `ERROR_UNKNOWN`. Vulkan itself
|
||||||
|
is healthy (both adapters enumerate and report 1.4); Win32 *surface* creation is
|
||||||
|
what is broken, and it is broken for every process on the box. It was bisected
|
||||||
|
to a pre-V11 commit whose offline capture had succeeded three hours earlier, so
|
||||||
|
it is transient driver/compositor state of the class a reboot clears.
|
||||||
|
|
||||||
|
V11 is committed and statically green. Its runtime evidence is outstanding, and
|
||||||
|
this is the exact outstanding list from campaign §5.5.24:
|
||||||
|
|
||||||
|
| Gate | Command |
|
||||||
|
|---|---|
|
||||||
|
| Offline pixel gate (VK self-differential) | `tools/run-offline-pixel-gate.ps1 -Out artifacts/v11-post -Baseline artifacts/v11-pre -SkipBuild` |
|
||||||
|
| Repeat connected gate | `tools/run-repeat-connected-gate.ps1 -Runs 3` |
|
||||||
|
| Connected world-lifecycle route | `tools/run-connected-world-lifecycle-gate.ps1` |
|
||||||
|
| Validation proven-loaded, zero errors | any connected launch with `ACDREAM_DEVTOOLS=1` |
|
||||||
|
| Working-set re-measure | the offline scene, once it renders |
|
||||||
|
|
||||||
|
The pre-deletion baseline for the self-differential is **already on disk** at
|
||||||
|
`artifacts/v11-pre`, captured before the deletion. The left-hand side of the
|
||||||
|
comparison survived the fault; only the right-hand side is missing.
|
||||||
|
|
||||||
|
**Also now runtime-outstanding:** [#248](../ISSUES.md)'s near-plane fix landed
|
||||||
|
tonight with a unit test, but its other acceptance criterion — unchanged culling
|
||||||
|
in the offline pixel gate and the connected route — needs the same window. The
|
||||||
|
change can only tighten culling toward the true frustum, which the issue had
|
||||||
|
already established is the safe direction, but it has not been seen running.
|
||||||
|
|
||||||
|
### 1.2 Three decisions the enum campaign could not make
|
||||||
|
|
||||||
|
The campaign explicitly refused to guess on these and recorded them rather than
|
||||||
|
inventing an answer. All three are yours.
|
||||||
|
|
||||||
|
1. **`WeenieError` — adopt 362 server-side status codes wholesale?** acdream has
|
||||||
|
16 members; the catalog's `StatusMessage` has 372, with 10 shared and **zero
|
||||||
|
conflicts**. Retail's `charError` (26 members) is a *different* enum —
|
||||||
|
character-creation errors only — so retail cannot arbitrate this one. Register
|
||||||
|
row AP-15 already tracks that our translation table covers only ~30 common
|
||||||
|
codes. Ideally paired with retail's `string_table.bin` for the real sentences.
|
||||||
|
2. **`SoundId` — adopt retail's table, or record the subset as a divergence?**
|
||||||
|
Ours is a curated 23-member local subset of retail's `SoundType` (206), with
|
||||||
|
acdream-local names (`FootstepGrass`, `BuffApplied`) that do not correspond
|
||||||
|
1:1 to retail members. Either adopt wholesale, or give it a register row.
|
||||||
|
Neither was done.
|
||||||
|
3. **Re-clone the reference repos.** Five of six are empty — **and this is true
|
||||||
|
of the main checkout, not just a worktree.** It has two concrete costs. The
|
||||||
|
enum campaign left **456 of 864 property members single-sourced** (transcribed
|
||||||
|
from the catalog, no independent attestation) that ACE and Chorizite would
|
||||||
|
promote to two-oracle confirmed. And CLAUDE.md's "cross-reference at least two
|
||||||
|
of them" is currently unexecutable as written, so every session re-solves it
|
||||||
|
privately — four duplicate ACE copies under `%TEMP%` are the evidence. Working
|
||||||
|
copies exist at `C:\Users\erikn\source\repos\client\ACE` and
|
||||||
|
`C:\Users\erikn\source\repos\holtburger`; **Chorizite.ACProtocol was not found
|
||||||
|
anywhere on disk** and needs a genuine re-clone.
|
||||||
|
|
||||||
|
A fourth, cheaper lead the campaign flagged but could not pursue: the client
|
||||||
|
DAT's own `EnumMapper` file type is a genuinely *retail* oracle for property
|
||||||
|
names, and `acclientlib` already has a reader for it. That is the most promising
|
||||||
|
unexplored route to attesting the single-sourced members without any re-clone.
|
||||||
|
|
||||||
|
### 1.3 One instrumented connected session
|
||||||
|
|
||||||
|
The wire audit's highest-leverage next action, and it needs a connected client:
|
||||||
|
|
||||||
|
```
|
||||||
|
ACDREAM_DUMP_OPCODES=1
|
||||||
|
```
|
||||||
|
|
||||||
|
on an otherwise normal Coldeve session. The audit catalogued all 349 opcodes but
|
||||||
|
could not *rank* the 128 MISSING rows, because nothing tells it which of them the
|
||||||
|
server actually sends during play. One environment variable converts "128 missing
|
||||||
|
parsers, unknown priority" into a real work order. This is the cheapest
|
||||||
|
high-value item on the board.
|
||||||
|
|
||||||
|
### 1.4 Walked-portal follow-up for #256 and #257
|
||||||
|
|
||||||
|
Both were observed in the same long live Coldeve session with repeated
|
||||||
|
town-portal-network transits, and both are HIGH:
|
||||||
|
|
||||||
|
- **#256** — server-spawned signs and portals go *visually* missing after
|
||||||
|
repeated transits while remaining interactive, so the entity is alive in the
|
||||||
|
object table and only its render projection is gone.
|
||||||
|
- **#257** — working set balloons to ~1.5 GB against the ~930 MiB neighborhood
|
||||||
|
the campaign baselines measured, suggesting per-transit accumulation.
|
||||||
|
|
||||||
|
Neither has been reproduced since, and neither can be worked without a client.
|
||||||
|
Both are marked "backend attribution pending" — whether they are Vulkan-era or
|
||||||
|
pre-existing is unknown, and a walked portal-network session is the only thing
|
||||||
|
that settles it. Worth doing in the same sitting as §1.1, since the machine will
|
||||||
|
already be up.
|
||||||
|
|
||||||
|
### 1.5 Two `MEMORY.md` entries point at documents that do not exist
|
||||||
|
|
||||||
|
Out of my reach to fix — user-level memory lives outside this repo — so flagging
|
||||||
|
it here instead.
|
||||||
|
|
||||||
|
`claude-memory/MEMORY.md` indexes `research/2026-06-04-property-enum-divergence.md`
|
||||||
|
(the "929 values across 7 enums" ledger) and
|
||||||
|
`research/2026-06-04-magic-number-audit.md`. **Neither exists** — not in the
|
||||||
|
working tree, not under any ref (`git log --all --diff-filter=A` finds no add),
|
||||||
|
and the memory directory has no `research/` subfolder at all. The same pattern
|
||||||
|
holds for the 2026-06-04 combat-math and wire-catalog drops.
|
||||||
|
|
||||||
|
This has a real cost, already paid twice tonight. The enum campaign could not
|
||||||
|
reproduce or audit the 929 figure and regenerated from scratch, arriving at 864
|
||||||
|
property members; the wire audit hit the identical wall. A link that silently
|
||||||
|
resolves to nothing is worse than no link, because a future session plans around
|
||||||
|
a document that does not exist. Suggest either restoring them or repointing those
|
||||||
|
index entries at the two documents that landed tonight, which supersede them:
|
||||||
|
|
||||||
|
- `docs/research/2026-07-29-enum-verification-campaign.md`
|
||||||
|
- `docs/research/2026-07-29-wire-stack-audit.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. What landed overnight
|
||||||
|
|
||||||
|
Six commits on `claude/git-sync-status-5fb1d2`, `d312bd2f` → `HEAD`.
|
||||||
|
|
||||||
|
### 2.1 The enum verification campaign (merged)
|
||||||
|
|
||||||
|
`github/overnight/enums` (`c19680fd`, 5 commits) merged **with no conflicts**.
|
||||||
|
It was cut at `b70b9832`, before the deletion, and its subject turned out to be
|
||||||
|
disjoint from V11's: the campaign lives entirely in `AcDream.Core` and its tests,
|
||||||
|
while V11 emptied `AcDream.App`. Not one file was touched by both.
|
||||||
|
|
||||||
|
- 17 files, **+3,767 / −27** lines
|
||||||
|
- **+597 tests**, verified exactly — the `Properties` namespace alone runs 597
|
||||||
|
- Names for AC's seven property tables, verified against two oracles
|
||||||
|
- Corrections to `DamageType`'s rotated bits and `ItemType`'s shifted craft ladder
|
||||||
|
- The retail members the equipment and physics enums were missing
|
||||||
|
- Names for `AmmoType`, `CombatUse` and `ItemUseable`
|
||||||
|
|
||||||
|
### 2.2 The wire-stack audit (merged)
|
||||||
|
|
||||||
|
`github/overnight/wire-audit` (`41f74fcd`, 6 commits), same base, **one conflict**
|
||||||
|
— see §2.3.
|
||||||
|
|
||||||
|
- 14 files, **+2,068 / −38** lines
|
||||||
|
- **+59 tests**; `AcDream.Core.Net.Tests` went 600 → 659
|
||||||
|
- **Three real parser fixes:** ranged speech carries a range float the parser was
|
||||||
|
eating; a chat type that is never sent was silently dropping every transient
|
||||||
|
string on it; `xpSpent` is a dword on the wire where we were writing eight bytes
|
||||||
|
- The transport flag word pinned against ACE across all 23 bits
|
||||||
|
- Golden fixtures generated from ACE's own writer rather than hand-typed hex
|
||||||
|
- The audit document, covering all 349 opcodes
|
||||||
|
|
||||||
|
### 2.3 The one merge conflict: #255, reconciled
|
||||||
|
|
||||||
|
Both branches reopened **#255** — the `RetailDatLoader` concurrency tests that
|
||||||
|
measure the thread pool rather than the loader — on the same day, from different
|
||||||
|
trees, without knowing about each other.
|
||||||
|
|
||||||
|
Neither is a duplicate. The V11 closeout saw **2 failures in 5** complete-solution
|
||||||
|
Release runs on the post-deletion tree; the wire-audit session saw **2 in 4** on
|
||||||
|
the pre-deletion tree; both saw **124/124 in isolation every time**. They
|
||||||
|
independently reached the same conclusion — `TaskCreationOptions.LongRunning` is
|
||||||
|
a hint, not a guarantee — and independently proposed the same fix, a rendezvous
|
||||||
|
inside the read stub.
|
||||||
|
|
||||||
|
Resolved by merging the two notes into one issue with **both evidence sets kept**
|
||||||
|
as labelled subsections, rather than one overwriting the other. Four failures
|
||||||
|
across nine runs on two trees is a materially stronger case than either half, and
|
||||||
|
the agreement between two blind observations is the part worth preserving. No
|
||||||
|
assertion was weakened; the fix itself remains open.
|
||||||
|
|
||||||
|
My own 20-run baseline tonight independently reproduced it a third time —
|
||||||
|
**4 failures in 20** complete-solution runs — which is consistent with both.
|
||||||
|
|
||||||
|
### 2.4 #248 — the near plane is `col3`, not `col4 + col3`
|
||||||
|
|
||||||
|
`FrustumPlanes.FromViewProjection` extracted the near plane with the
|
||||||
|
Gribb-Hartmann form written for OpenGL's `[-1,1]` clip-space z range, against
|
||||||
|
projections from `Matrix4x4.CreatePerspectiveFieldOfView`, whose range is `[0,1]`.
|
||||||
|
Under `[-1,1]` the near plane is `clip.z = -clip.w`, which is `col4 + col3`;
|
||||||
|
under `[0,1]` it is `clip.z = 0`, which is `col3` alone.
|
||||||
|
|
||||||
|
The error put the effective near threshold at `-n·f/(2f-n)` — about 0.5 m where
|
||||||
|
the retail chase camera asks for 1.0 m — which only ever *kept* geometry the true
|
||||||
|
frustum would have dropped. Harmless, and still wrong; it is the same mistake
|
||||||
|
that *was* visible in `PortalProjection`, where it culled the cell behind a
|
||||||
|
doorway the camera stood close to.
|
||||||
|
|
||||||
|
Pinned by a theory over four near/far pairs asserting the extracted plane is unit
|
||||||
|
length, faces down -Z, and stands off the eye by exactly the camera's near value.
|
||||||
|
**The test was run against the old formula before commit and fails all four
|
||||||
|
cases**, so it measures the fix rather than merely accompanying it. The far plane
|
||||||
|
is unchanged under both conventions and is pinned alongside so a later edit
|
||||||
|
cannot drift it.
|
||||||
|
|
||||||
|
Status: DONE for the unit-test half of its acceptance criterion; the gate half is
|
||||||
|
in §1.1.
|
||||||
|
|
||||||
|
### 2.5 #250 — fixed at the measurement, and the family was larger than four
|
||||||
|
|
||||||
|
**The four named members shared one root: the measured window was never the
|
||||||
|
warmed path.** This had been dismissed as inherent noise in
|
||||||
|
`GC.GetAllocatedBytesForCurrentThread` three separate times. It is not noise.
|
||||||
|
|
||||||
|
| Test | Warmup | Measured window |
|
||||||
|
|---|---|---|
|
||||||
|
| `UiDatFontTests` | 1 call | a **10,000-iteration loop** written inline |
|
||||||
|
| `RenderFrameProductTests` | **8** calls | a **1,000-iteration loop** written inline |
|
||||||
|
| `CurrentRenderSceneOracleTests` | 1 call | a 10,000-iteration loop written inline |
|
||||||
|
| `ArchRenderSceneTests` | `Apply(registrations)` | `Apply(**updates**)` — a different switch arm |
|
||||||
|
|
||||||
|
Two mechanisms follow. A test method is JIT-compiled at tier 0 like anything
|
||||||
|
else, and a long-running loop in tier-0 code is replaced mid-flight by **on-stack
|
||||||
|
replacement**, which compiles on the thread running the loop — so its bookkeeping
|
||||||
|
is charged to the window being measured. That is the loop-shaped ones. And
|
||||||
|
`ArchRenderSceneTests` warmed one arm of a switch and measured the other, so the
|
||||||
|
measured call was the first ever into `ApplyUpdate` and paid that arm's tier-0
|
||||||
|
JIT, type loads and static initialisation inside the window;
|
||||||
|
`RenderFrameProductTests` warmed 8 times, below the tier-0 call-counting
|
||||||
|
threshold of **30**, so promotion was still pending when measurement began.
|
||||||
|
|
||||||
|
That also explains the signature nobody could account for — clean in isolation,
|
||||||
|
failing about one run in three. Alone, the process is quiet and the runtime has
|
||||||
|
finished before the assertion arrives. Alongside eight other test assemblies,
|
||||||
|
tier-0 compilation never stops, the call-counting delay is re-armed continually,
|
||||||
|
and the work slides into the window.
|
||||||
|
|
||||||
|
**The fix** is `tests/AcDream.App.Tests/ZeroAllocationProbe.cs`. It invokes the
|
||||||
|
step many times before measuring anything, then measures windows that run the
|
||||||
|
same already-warmed loop over the same already-taken path. Each window is a
|
||||||
|
**batch** of 32 invocations and it reports the **minimum** across 4 of them. Both
|
||||||
|
halves are load-bearing: the minimum excludes a one-time cost, and the batch is
|
||||||
|
what keeps the assertion as strong as the loops it replaces — minimising over
|
||||||
|
*single* invocations would report zero for a path that allocates every tenth
|
||||||
|
call. I had written it that way first and the apparatus test caught it.
|
||||||
|
|
||||||
|
**The bound is untouched: exactly zero, no tolerance, no retry, no assertion
|
||||||
|
relaxed.** `ZeroAllocationProbeTests` proves the apparatus can still fail — a
|
||||||
|
step allocating every call reads above zero and does throw, a first-invocation
|
||||||
|
cost reads as zero, a cost every tenth call is caught, and the one stated limit
|
||||||
|
(the batch must cover the period) is pinned as a test rather than left as prose.
|
||||||
|
|
||||||
|
**The family was larger than four.** The first pass converted only the named four.
|
||||||
|
A 20-run baseline disproved "none of the others has been observed failing" within
|
||||||
|
minutes — `LiveEntityRuntimeTests` failed in run 2, `StaticRenderProjection`
|
||||||
|
`JournalTests` in runs 14 and 18, both the same shape, neither previously
|
||||||
|
recorded. Run 19 was sharper still: the issue named
|
||||||
|
`SurfaceOverrideFingerprint_DictionaryHotPathAllocatesNothing`, and the first
|
||||||
|
pass had converted a *different* test in that same file. Matching by file was not
|
||||||
|
matching by test.
|
||||||
|
|
||||||
|
All ten strict-zero sites are now on the probe. **Two came out stricter rather
|
||||||
|
than merely steadier:**
|
||||||
|
|
||||||
|
- `StaticRenderProjectionJournalTests` was measuring a synchronise whose journal
|
||||||
|
**does not coalesce**. Repeating it grew the journal by 1,000 entries per call
|
||||||
|
— 192,000 by the end of a probe run — so the steady state it claimed to test
|
||||||
|
did not exist, and the single-call window had been hiding that. Its step is now
|
||||||
|
the whole frame cycle, synchronise *and* drain, putting `DrainTo` inside the
|
||||||
|
measured window for the first time.
|
||||||
|
- `RetailInboundEventDispatcherTests` asserted a hard-coded 1,001 callbacks; it
|
||||||
|
now counts its own dispatches and pins the callback count against them.
|
||||||
|
|
||||||
|
Four sites asserting a *tolerance* rather than zero were deliberately left alone
|
||||||
|
(`CellViewDedupTests` ×2, `PortalProjectionTests` ×2) — their ceilings already
|
||||||
|
absorb this noise and none has flaked. `PortalProjectionTests` is worth
|
||||||
|
revisiting: its ceiling exists explicitly to tolerate "a tiered-JIT/ArrayPool
|
||||||
|
bookkeeping transition ... to the first measured batch", which is exactly what
|
||||||
|
the probe removes, so it could probably be tightened to zero now.
|
||||||
|
|
||||||
|
**Acceptance:** the issue asks for 20 consecutive clean Release runs of the App
|
||||||
|
suite. See §4 for the count actually achieved and how to read it.
|
||||||
|
|
||||||
|
### 2.6 Worktree sweep
|
||||||
|
|
||||||
|
Removed **9** finished worktrees — the two temp ones
|
||||||
|
(`%TEMP%\claude\prerevert`, `%TEMP%\claude\v4a-verify-base`) and seven
|
||||||
|
`agent-a*` paths including the two whose branches were merged tonight. Pruned
|
||||||
|
afterward. `codex/*`, `.worktrees/*` and the named `claude/*` worktrees were not
|
||||||
|
touched.
|
||||||
|
|
||||||
|
**Two were deliberately left in place**, because "finished" is load-bearing and
|
||||||
|
neither is:
|
||||||
|
|
||||||
|
- `agent-a1589ee2f5360c7a2` — has an **unresolved merge conflict** (`UU
|
||||||
|
src/AcDream.Core/Physics/TransitionTypes.cs`), three other modified physics
|
||||||
|
files, and an untracked new `EdgeSlideTests.cs`. This is in-progress L.2.3
|
||||||
|
step-up/step-down work belonging to some other session, not tonight's.
|
||||||
|
- `agent-af83539515c87d43e` — has an uncommitted **1,073-line** edit to
|
||||||
|
`WbDrawDispatcher.cs` (−961/+112), an in-progress GL-removal pass. V11 has
|
||||||
|
since landed the equivalent, so this is probably superseded scratch — but it is
|
||||||
|
a thousand lines of uncommitted work and deleting it is not reversible.
|
||||||
|
|
||||||
|
Both are yours to keep or discard.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Campaign V — final state
|
||||||
|
|
||||||
|
**The campaign is complete and the tree is statically green. Its runtime
|
||||||
|
evidence is outstanding, and that is a machine fault rather than a campaign
|
||||||
|
result.**
|
||||||
|
|
||||||
|
V11 removed the GL backend across 5 commits (`844cf092` → `c265b52d`): 204 files,
|
||||||
|
**+1,870 / −27,607** lines. Gone are `Gpu/Gl`, `ManagedGL*`, `GLHelpers`,
|
||||||
|
`GLStateScope`, both render-state caches, `BindlessSupport`,
|
||||||
|
`GraphicalGlFunctionProbe`, the ImGui project, the Studio tree, the `ui-studio`
|
||||||
|
verb, `RenderBackendKind` and the `ACDREAM_RENDER_BACKEND` escape hatch.
|
||||||
|
`Silk.NET.OpenGL` and `.Extensions.ARB` are dropped — **final reference count
|
||||||
|
zero**. 9/9 shader pairs recompile.
|
||||||
|
|
||||||
|
Three findings from the deletion are worth keeping:
|
||||||
|
|
||||||
|
- **Chorizite could not be dropped, and not for the reason the risk register
|
||||||
|
predicted.** It was assumed to survive only via `IUniformBuffer`. In fact
|
||||||
|
`TextureFormat` sits in the `IWorldTextureArray.CreateClampedArray` signature
|
||||||
|
that the **Vulkan** path implements, and `BoundingBox` is a **serialized type
|
||||||
|
in the pak format**. Dropping it touches the on-disk format and is its own
|
||||||
|
slice.
|
||||||
|
- **`Studio/SampleData.cs` was production code**, not devtools —
|
||||||
|
`InteractionRetainedUiComposition` uses it as the character sheet's fallback.
|
||||||
|
Moved, not deleted.
|
||||||
|
- **One real bug fell out.** `WbMeshAdapter.Dispose()` was still pattern-matching
|
||||||
|
the deleted `GpuFrameFlightController` to decide whether to wait for submitted
|
||||||
|
GPU work. `VulkanFrameFlightController` replaced that type at V6a and the site
|
||||||
|
was never updated, so **the wait had been silently dead on every Vulkan run
|
||||||
|
since V6a**. Deleting the GL type is what turned a no-op into a compile error.
|
||||||
|
|
||||||
|
Nothing was relaxed to manufacture a pass and nothing was declared green on a
|
||||||
|
prediction. A gate that could not run is not a gate that passed — the outstanding
|
||||||
|
list is §1.1.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Numbers
|
||||||
|
|
||||||
|
### Complete solution suite
|
||||||
|
|
||||||
|
| | Passed | Skipped | Total |
|
||||||
|
|---|---|---|---|
|
||||||
|
| V11 baseline (`d312bd2f`) | 8,999 | 5 | 9,004 |
|
||||||
|
| **Tonight (`HEAD`)** | **9,666** | **5** | **9,671** |
|
||||||
|
|
||||||
|
The **+667** decomposes exactly, with nothing unaccounted for:
|
||||||
|
|
||||||
|
| Source | Tests |
|
||||||
|
|---|---|
|
||||||
|
| Enum verification campaign | +597 |
|
||||||
|
| Wire-stack audit | +59 |
|
||||||
|
| #248 near-plane theory (4 near/far pairs) + far-plane pin | +5 |
|
||||||
|
| #250 `ZeroAllocationProbe` apparatus guards | +6 |
|
||||||
|
| **Total** | **+667** |
|
||||||
|
|
||||||
|
Per project at `HEAD`: App 3,941/3 · Core 3,898/2 · Core.Net 659 · UI.Abstractions
|
||||||
|
543 · Runtime 415 · Content 124 · Headless 67 · Bake 15 · Cli 4. **Zero failures.**
|
||||||
|
|
||||||
|
Release build: **0 errors.** 21 warnings, all pre-existing — one `xUnit1025`
|
||||||
|
(duplicate `InlineData` in `MotionInterpreterTests`) and a family of `CS8767`
|
||||||
|
nullability mismatches in the App test composition fakes. None cites a file
|
||||||
|
touched tonight; the count is unchanged from the V11 baseline.
|
||||||
|
|
||||||
|
### The #250 acceptance gate
|
||||||
|
|
||||||
|
The issue asks for 20 consecutive clean Release runs of the **App suite**, and
|
||||||
|
that is the right scope: it isolates #250 from #255, which lives in
|
||||||
|
`AcDream.Content.Tests` and is still open.
|
||||||
|
|
||||||
|
**Result: 20 / 20 clean, 3,941 passed / 3 skipped every run.**
|
||||||
|
|
||||||
|
For contrast, the pre-fix 20-run **complete-solution** baseline taken earlier the
|
||||||
|
same night, on the same machine:
|
||||||
|
|
||||||
|
| Failure | Runs |
|
||||||
|
|---|---|
|
||||||
|
| #250 family (3 distinct tests) | 2, 14, 18, 19 |
|
||||||
|
| #255 `RetailDatLoaderTests` | 7, 14, 17, 18 |
|
||||||
|
|
||||||
|
So the #250 family went from 4 failing runs in 20 to 0 in 20, and the three tests
|
||||||
|
involved were each converted. **#255 is untouched and still flakes** — it is a
|
||||||
|
different issue with an open fix, and it will keep appearing in
|
||||||
|
complete-solution runs until the rendezvous lands.
|
||||||
|
|
||||||
|
One caveat, stated plainly: 20 consecutive App-suite runs is what the acceptance
|
||||||
|
criterion asks for and what was delivered, but the App suite alone applies less
|
||||||
|
parallel pressure than a complete-solution run. The strongest evidence would be
|
||||||
|
20 clean complete-solution runs, and that is not currently obtainable while #255
|
||||||
|
flakes independently. Re-running this gate after #255 is fixed would close that
|
||||||
|
gap.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Where to pick up
|
||||||
|
|
||||||
|
1. Reboot, then §1.1's five gates and §1.4's walked portal session — one sitting.
|
||||||
|
2. Answer §1.2's three enum decisions; they unblock adoption commits that are
|
||||||
|
otherwise ready.
|
||||||
|
3. One `ACDREAM_DUMP_OPCODES=1` session (§1.3) turns the wire audit's 128 MISSING
|
||||||
|
rows into a ranked work order.
|
||||||
|
4. #255's rendezvous fix — the diagnosis is settled from three independent
|
||||||
|
observations and the fix direction is agreed; it is only unwritten.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue