acdream/docs/reviews/2026-08-18-r3-test-truth-ledger.md

372 lines
22 KiB
Markdown

# R3 test-truth and cleanup ledger
Status: **active**
Branch: `codex/release-stabilization`
Starting commit: `8e884679e0b6ce3dc1c84004ba9c5c8e3ff91d2a`
This is the cross-session authority for R3. The historical all-file audit remains
in [`test-quality-audit.md`](test-quality-audit.md); this ledger reconciles that
baseline against current source and records each cleanup decision before code is
removed. R3 does not change product behavior.
## Current executable baseline
The clean R2 gate at implementation commit `c38f6b88` built all 44 maintained
projects with zero warnings and ran every default test assembly once:
- 12 test assemblies;
- 14,742 passed;
- 77 reported skipped;
- 0 failed; and
- one redundant Core theory row discarded by xUnit discovery before the totals.
The six-case reduction from the earlier 14,748-pass headline is understood:
seven launcher editor-focus theory rows were consolidated into one fact that
still executes all seven variants in a single Avalonia application session.
## Fresh reproducible syntax inventory
`tools/audit-test-inventory.ps1` now regenerates the complete attributed-method
manifest from tracked C# test sources with Roslyn:
```powershell
pwsh ./tools/audit-test-inventory.ps1
```
The generated JSON lives under ignored `artifacts/test-audit/`; it is not a
second 6.8 MB checked-in source of truth. The script and this reviewed ledger
are durable, while paths and line numbers regenerate after every batch. The
inventory at commit `8f490240` reports:
| Syntax signal | Current count |
|---|---:|
| Tracked/parsed C# test files | 1,256 / 1,256 |
| Attributed test methods (not expanded theory cases) | 11,455 |
| Methods containing at least one empty `return;` | 399 |
| Empty-return sites | 426 |
| Prerequisite-return candidates | 282 |
| Mechanical output-only candidates | 47 |
| Methods directly using `Thread.Sleep` / `Task.Delay` | 20 / 23 |
| Methods directly reading environment variables | 47 |
| Methods directly reading `.cs` source text | 63 |
The 282 prerequisite-return count is intentionally a review candidate set, not
a claim that all 399 methods are broken. It comprises 109 App, 125 Core, 29
Content, 12 Launcher.Core, three Core.Net, three Bake, and one Headless method.
The classifier includes external-asset, opt-in, and platform gates; behavioral
early exits inside callback tests remain outside that candidate set. Every
candidate still requires source inspection because `Directory.Exists`, for
example, can also be the behavior under test.
The output-only classifier follows same-file helper calls, but it cannot decide
whether an assertion merely establishes probe setup. The reviewed diagnostic
set is therefore 51 methods: the 47 mechanical candidates plus
`OptionsPanelLiveMountProbeTests.ProbeLiveMountShapes`,
`DoorSetupGfxObjInspectionTests.HoltburgCottage_CellPortals_DatInspection`, and
the two already classified tower diagnostics. Relative to T-011's historical
51-method table, delete the removed PVS scaffold and add
`TowerAscentReplayTests.Diagnostic_TowerAscent_PerStepTable`; all other entries
remain. Those 51 methods expand to 70 discovered cases (28 App, 42 Core).
## Exact 77-skip reconciliation
The latest clean-gate TRX files account for every reported skip:
| Classification | Count | Current source | R3 decision |
|---|---:|---|---|
| Installed retail DAT lane | 73 | `InstalledDatFactAttribute` across nine files | Retain the contracts, replace the campaign-specific shared reason with prerequisite- and suite-specific identity, and report this lane separately. Batch B assigns all nine classes to `Lane=InstalledDat`. |
| Manual fixture generation | 2 | `ChatLayoutFixtureGenerator.GenerateChatFixture`; `RadarLayoutFixtureGenerator.GenerateRadarFixture` | Delete both redundant generators: the existing comprehensive `RetailLayoutFixtureGenerator` already owns their chat and radar outputs. Assign that generator to the explicit Manual lane. |
| Empty future scaffold | 1 | `PvsConformanceTests.Pvs_CottageInterior_MatchesRetailCellDrawList` | Delete the test. Preserve its retail oracle and capture recipe here and in the existing P0 plan. |
| Known product failure | 1 | `TowerAscentReplayTests.TowerAscent_StaircaseStaysConeVisible_EveryStep` | Do not pretend this is unavailable coverage. Keep the oracle and move it to an explicitly reported known-failure/non-blocking lane until #119 is fixed. |
Installed-DAT skip distribution:
| Test class | Count |
|---|---:|
| `ChargenPreviewControllerTests` | 10 |
| `CharacterCreationLiveDatTests` | 42 |
| `CharacterManagementLiveDatTests` | 3 |
| `DatStringEscapeSweepTests` | 1 |
| `LayoutImporterMediaBearingChildSweepTests` | 3 |
| `MapHousePanelLiveDatMountTests` | 1 |
| `MapNoteLiveDatTests` | 3 |
| `TooltipLiveDatTests` | 7 |
| `UiButtonCorpusSweepTests` | 3 |
There are also 11 source sites that throw `SkipException.ForSkip` conditionally.
They are not part of the current 77 because their prerequisites happened to be
available on the R2 gate machine. R3 must retain their per-test reason and
assign them to the installed-DAT, prepared-package, system-font, or other
explicit prerequisite lane; a future machine may report them as additional
skips.
The lane vocabulary is deliberately orthogonal:
- `Lane` states the execution environment (`InstalledDat`, `PreparedPackage`,
`Live`, or `Manual`);
- `Purpose=Diagnostic` marks output/investigation apparatus that cannot add to
the contract-test pass count; and
- `Status=KnownFailure` keeps a named executable oracle visible without making
a green release claim.
The default gate excludes all three dimensions. An explicitly selected lane
must fail clearly when its prerequisite is missing; it may not pass through an
empty return. The 73 custom installed-DAT facts retain discovery-time skips
when their opt-in is absent so each unavailable contract and reason remains
identifiable in the lane report.
## Finding disposition
| Finding | Current disposition | Evidence / next action |
|---|---|---|
| T-001 launcher lock inversion | resolved in R1 | Deterministic captured-callback regression and bounded full gate. |
| T-002 physics tautology | high-confidence cleanup batch A | Compare old-model and new-model reflection decisions, as the surrounding contract states. |
| T-003 duplicate theory row | high-confidence cleanup batch A | Remove literal `0x41000012`, which is identical to `MotionCommand.Crouch`; remove the temporary analyzer suppression. |
| T-004 warning mismatches | resolved in R2 | Clean rebuild is zero-warning with repository-wide warnings-as-errors. |
| T-005 unreachable panel stack | requires production reachability proof | Do not delete 52 meaningful tests until the dead presentation surface and any supported plugin compatibility promise are verified together. |
| T-006 misleading installed-DAT reason | resolved in batch B | Shared opt-in is now `ACDREAM_RUN_INSTALLED_DAT_TESTS=1` (legacy switch retained), the reason names the lane, and all nine owners carry `Lane=InstalledDat`. |
| T-007 271 silent passing gates | lane classification complete in batch D; body cleanup active | Of 282 current candidates, 280 are true prerequisite gates and now have an explicit lane. The two unlaned methods are reviewed false positives that assert the current Windows/Linux branch before returning. Empty-return removal remains, lane by lane. |
| T-008 incapable-of-failing diagnostics | batch A plus diagnostic lane work | Delete the literal wiring smoke test; repair the GPU contract tautology; later re-home output-only apparatus. |
| T-009 wall-clock double-click tests | resolved in batch E | Four sleeps were replaced by a deterministic test clock behind an internal factory overload. The production factory still reads `Environment.TickCount64` exactly as before. |
| T-010 two useless cases | high-confidence cleanup batch A | Delete `SmokeTest.TestProject_IsWired` and `ChaseCameraTests.ImplementsICamera`; compilation already proves both claims. |
| T-011 51 output-only methods | classified in batch C | The reviewed current set is 51 methods / 70 cases. All carry `Purpose=Diagnostic`, preserving the apparatus while removing it from release pass totals. Contract-shaped names remain explicitly flagged until a stable oracle exists. |
| T-012 source-text freezes | requires semantic replacement map | Retain whole-tree dependency rules; remove exact-text freezes only when an equivalent semantic/behavioral guard is identified. |
| T-013 controller self-comparison | high-confidence cleanup batch A | Capture the first controller next to the first body and compare every retry with that reference. |
| T-014 seven load-sensitive tests | six mechanisms repaired in batch F; one product defect classified | Virtual/wall-clock mixing, tiered-JIT allocation noise, a live controller clock, and a ThreadPool-start timing oracle were removed without weakening behavioral contracts. `DatSoundCache` #321 is a real in-flight-entry race and now runs as `Status=KnownFailure` pending a product fix. |
| T-015 four non-prerequisite skips | resolved in batches A/B | PVS scaffold deleted with rationale preserved; redundant chat/radar generators deleted in favor of the comprehensive Manual lane; tower oracle is `Status=KnownFailure`. |
| T-016 historical test taxonomy | open | Rename/re-home only after each test's durable owner and oracle are established. |
| T-017 Avalonia ownership | reopened and closed in batch D | The full gate exposed the same compositor ownership class between six newer `MainWindowViewTests` facts. Their six named assertion phases now run in one owned Avalonia application session; 25 fresh-process stress iterations and the complete gate pass. |
| T-018 stderr observer race | resolved in R2 | Live reader shares writes/deletes; 25 focused repetitions plus the complete gate. |
## Preserved rationale for removals in batch A
### PVS scaffold
The empty PVS fact has no executable oracle and must not remain a permanent
skip. Its useful note is preserved here: retail
`PView::ConstructView(CEnvCell*)` at `0x005a57b0` produces the ordered
`cell_draw_list` for a `(viewer_cell, eye)` input. A future conformance test
requires a retail trace captured around `PView::DrawCells`/`cell_draw_list`.
The intended invariants were: the PVS root equals `physics CurrCell.Id`; a cell
seen through two portals appears once per slice; and dungeon
`outside_view == 0`. The complete original scaffold and capture plan remain in
`docs/superpowers/plans/2026-06-03-p0-conformance-apparatus.md`.
### Compile-only smoke cases
`SmokeTest.TestProject_IsWired` contains only `Assert.True(true)`.
`ChaseCameraTests.ImplementsICamera` assigns `ChaseCamera` to `ICamera` and
calls `ToString()` without an oracle. Removing them discards no runtime
contract: the test project build and the remaining camera behavior tests are
strictly stronger evidence.
## Batch protocol
Each cleanup batch must:
1. update this ledger before or with the change;
2. preserve useful historical rationale in a plan, issue, or this ledger;
3. run the directly affected test projects without retries;
4. run a clean warning-as-error build when analyzer/discovery shape changes;
5. commit one coherent classification/fix group; and
6. run the complete local Release gate before R3 closeout.
Ambiguous cases stay open in this ledger and are presented to the user rather
than being deleted by inference.
## Batch A verification
The first high-confidence batch was verified before commit:
- complete non-incremental Release rebuild: 44 projects, 0 warnings, 0 errors;
- Core: 4,795 passed / 0 skipped / 0 failed;
- App: 5,511 passed / 76 skipped / 0 failed; and
- Runtime: 1,756 passed / 0 skipped / 0 failed.
The count delta is intentional and classified: Core removed the two useless
compile-only cases and the skipped PVS scaffold; App gained one case by
splitting the old mixed/tautological depth-stencil test into two independently
named contracts. Core emitted no duplicate-case discovery warning.
## Preserved rationale for removals in batch B
The chat- and radar-only fixture generators were not the sole way to recreate
their committed JSON. `RetailLayoutFixtureGenerator` already includes retail
layout IDs `0x2100006F` and `0x21000074` and writes the same
`chat_2100006f.json` and `radar_21000074.json` destinations as part of its
complete 20-layout run. Deleting the two permanently skipped duplicates removes
two false test entries without losing the regeneration recipe or retail notes;
the comprehensive generator and `docs/release-gate.md` now own that workflow.
The tower staircase oracle is not unavailable or useless. Its former static
skip documents issue #119 and the exact failing steps. Batch B keeps the
executable assertion under `Status=KnownFailure`, separates two output-only
methods with `Purpose=Diagnostic`, and makes missing installed DATs a clear lane
prerequisite failure instead of a passing early return.
## Batch B verification
The lane-classification batch was verified without changing product code:
- App Release build: 0 warnings, 0 errors;
- hermetic App lane, isolated: 5,505 passed / 0 skipped / 0 failed;
- Installed-DAT contract lane without opt-in: 3 passed / 73 individually named
skips / 0 failed (the local tower DAT prerequisite was available);
- known-failure discovery: exactly one tower staircase oracle; and
- Manual discovery: exactly one comprehensive fixture generator.
One concurrent three-host verification attempt reproduced T-014 rather than
being hidden: the hermetic host failed the portal-clipping zero-allocation test
at 6,904 bytes while the Installed-DAT and discovery hosts ran beside it. The
same unmodified hermetic command then passed 5,505/5,505 in isolation. This is
evidence for removing cross-host allocation sensitivity; it is not grounds to
weaken the assertion or claim a clean concurrent result.
## Batch C diagnostic classification
Batch C assigns the reviewed 51-method diagnostic set to
`Purpose=Diagnostic`. No body, output, historical comment, or fixture is
removed. This resolves the misleading release accounting without pretending
that every investigation has a stable regression oracle.
The 15 contract-shaped methods called out by T-011 now have a `Diagnostic_`
prefix: four facility-hub scenarios, six stair/camera sweeps, two ambient-slot
inventories, production-emission replication, and two drawn-polygon reports.
Their current output and historical method references are preserved, while the
new names no longer imply an asserted oracle. Promoting them back into the
hermetic lane requires an asserted expected result; R3 will not invent those
values.
Batch C verification:
- App Release build: 0 warnings, 0 errors;
- Core Release build, serialized after App: 0 warnings, 0 errors;
- hermetic App: 5,479 passed / 0 skipped / 0 failed;
- hermetic Core: 4,753 passed / 0 skipped / 0 failed; and
- diagnostic discovery: 28 App + 42 Core = 70 cases from 51 methods.
An attempted parallel App/Core build collided on the shared
`AcDream.Plugin.Abstractions` intermediate DLL. The repository gate serializes
projects, so the authoritative verification is the two isolated clean builds
above; no code or assertion was changed in response to that tooling collision.
## Batch D prerequisite lanes and Avalonia ownership
The reviewed prerequisite map classifies every true candidate without deleting
its existing guard:
| Lane | Attributed methods | Prerequisite |
|---|---:|---|
| `InstalledDat` | 336 | Installed retail DAT directory; includes the 73 custom installed-DAT facts and whole DAT-backed investigation classes. |
| `PreparedPackage` | 2 | Installed DATs plus validated `acdream.pak`. |
| `Live` | 3 | Explicit live handshake opt-in and reachable service. |
| `Manual` | 1 | Explicit fixture-regeneration opt-in. |
| `Windows` | 7 | Windows-only filesystem/process/timer behavior. |
| `Linux` | 10 | Linux permission/signal/monotonic-clock behavior. |
| `SystemFont` | 2 | A host system TTF available to the BitmapFont path. |
Class-level traits legitimately cover some additional methods that share the
same fixture owner, so the 336 installed-DAT method count is larger than the
280 syntax candidates. The only candidate methods without a lane are
`GraphicalHostPlatformServicesTests.CurrentPlatformOwnsPathsPacingAndNativeClosure`
and
`LinuxMonotonicFramePacingWaiterTests.PlatformFactorySelectsCurrentOperatingSystem`.
Both are hermetic cross-platform branch tests: on Windows or Linux they assert
the matching branch and return only after the assertion. They are not silent
prerequisite passes.
The 11 conditional `SkipException.ForSkip` source sites are also reconciled.
They serve 12 test methods: installed-DAT asset contracts, one prepared-package
contract, and two system-font contracts. xUnit v2 reports that exception shape
as a failure rather than a dynamic skip, but the owning lanes now keep them out
of the hermetic total. A later body-cleanup batch will replace the misleading
skip wording/exception with explicit prerequisite failure or discovery-time
lane behavior.
The first complete Batch D gate correctly failed in Launcher cleanup after
14,396 passes: the six `MainWindowViewTests` Avalonia facts could start and
destroy isolated thread-affine compositors on different xUnit workers. The
assertion bodies were preserved as six named private phases under one
`CompiledMarkupAndEveryModalFocusPathRunInOneOwnedAvaloniaSession` fact. The
focused two-case class then passed in 25 consecutive fresh processes (50/50
results), and the same full-gate context passed.
Batch D verification:
- complete 44-project Release build: 0 warnings, 0 errors;
- final syntax manifest: 11,450 attributed methods, 51 diagnostics, one known
failure, 282 prerequisite-return candidates, and only the two reviewed
cross-platform false positives unlaned;
- complete hermetic Release gate: 14,392 passed / 0 skipped / 0 failed across
all 12 test assemblies in 131.518 seconds; and
- Launcher view stress: 25 fresh processes, 2/2 cases per process, no cleanup
or ownership failures.
The 350-pass reduction from the clean R2 headline is exactly explained: batch A
netted minus one case; batch B removed six non-hermetic passes; batch C removed
68 newly classified diagnostic cases; batch D removed 270 prerequisite-lane
passes; and consolidating the six Avalonia sessions into one removed five case
IDs without removing any assertion phase. All 77 former default skips are also
accounted for by the PVS deletion and batch-B lane/deletion decisions.
## Batch E indirect gates and deterministic input time
The inventory now follows same-file helper calls when looking for prerequisite
returns. It found one additional path:
`LauncherSelfUpdateProcessTests.BackupJunctionOrSymlinkAfterCanonicalCrashCannotMutateOutsideOrLaunch`
calls `CreateDirectoryLink`, whose non-Windows branch creates the symbolic link
and then returns before the Windows `mklink /J` implementation. This is a
reviewed cross-platform control-flow branch, not a prerequisite gate or silent
pass. The combined direct/indirect candidate count is therefore 283: 280 true
lane-owned gates and three reviewed branch false positives.
The four `InputDispatcherDoubleClickTests` no longer sleep for 10 or 600 real
milliseconds. `InputDispatcher` has an internal, test-assembly-only factory
overload accepting the same millisecond tick delegate used by double-click
recognition. The public production factory remains wired directly to
`Environment.TickCount64`; only the tests use a manually advanced counter.
The focused class passes 4/4 in 17 ms with exact 10 ms and 600 ms virtual
intervals. The complete Release build then passed with 0 warnings/errors, and
the no-retry hermetic gate passed 14,392/14,392 with zero skips or failures.
## Batch F load-sensitive contracts
The seven cases in T-014 have now been separated into six unreliable test
mechanisms and one real product defect:
- #308 `NakEmissionTests.LossSoak...` no longer mixes its virtual transport
clock with a 60-second `DateTime.UtcNow` cutoff and fixed sleeps. Its two
convergence phases each permit exactly 120 half-second virtual steps and
yield to the background receiver. The full 10,000-message oracle is intact;
25 fresh-process repetitions pass.
- #302 and #346, the two `PortalProjectionTests` allocation contracts, now
cross tiered-JIT/PGO thresholds before measuring and take the minimum of five
warmed 1,000-operation batches. A linear result-array regression would
allocate in every batch and still fail far above the existing ceilings.
- #336 `RuntimeCollisionReportingStateTests.WarmedSteadyContactRefreshDoesNotAllocate`
now earns the word "warmed": it performs one complete 10,000-refresh warmup
and requires at least one of five subsequent 10,000-refresh batches to
allocate exactly zero bytes. It passes in 25 fresh processes.
- #340 `StreamingWorkBudgetTests.DestinationAndEmptyUnloadPriorityNeverBypassPublicationBudget`
now supplies a frozen meter clock through an internal test-only constructor.
The public production constructor still supplies `Stopwatch.GetTimestamp`
and `Stopwatch.Frequency` exactly as before.
- #402 `LandblockBuildFactoryTests.Build_UsesTheSuppliedSharedReaderGate` now
starts a dedicated thread and observes it in `WaitSleepJoin` on the held
monitor before checking that no DAT read occurred. It no longer treats a
ThreadPool start within two seconds or an arbitrary 100 ms wait as evidence.
- #321 `DatSoundCacheTests.GetWave_ConcurrentSameId_PublishesOneCanonicalWaveAndDecodesOnce`
exposes a real race. A caller can pass the resident-cache check, pause, and
reach `_inflight` after the winning caller has admitted the wave and removed
its `Lazy`, producing a second decode. The assertion and rationale are
preserved under `Status=KnownFailure`; R3 makes no cache behavior change.
The four changed App cases pass 100/100 across 25 fresh processes. The Runtime
allocation case passes 25/25, and the Core.Net loss soak passes 25/25. Complete
batch verification then passed: the 44-project Release build reports zero
warnings/errors, the refreshed inventory reports two explicit known-failure
methods and 15 remaining direct `Thread.Sleep` methods, and the no-retry
hermetic gate passed 14,391/14,391 with zero skips or failures. The one-pass
reduction is exactly #321 leaving the release lane.