diff --git a/docs/release-gate.md b/docs/release-gate.md index 7294156d..4283c74f 100644 --- a/docs/release-gate.md +++ b/docs/release-gate.md @@ -88,9 +88,3 @@ Do not edit lock files by hand. To make an intentional dependency change: dotnet restore AcDream.slnx --locked-mode --force-evaluate pwsh ./tools/run-release-gate.ps1 ``` - -The one site-scoped `xUnit1025` suppression in -`MotionInterpreterTests.ContactAllowsMove_GroundedPosture_StillAllowsMove` -preserves a known redundant historical input until R3. It is deliberately not -in the central warning policy, so any new duplicate theory row still fails the -build. diff --git a/docs/reviews/2026-08-18-r3-test-truth-ledger.md b/docs/reviews/2026-08-18-r3-test-truth-ledger.md new file mode 100644 index 00000000..67c5b3fb --- /dev/null +++ b/docs/reviews/2026-08-18-r3-test-truth-ledger.md @@ -0,0 +1,132 @@ +# 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. + +## 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. | +| Manual fixture generation | 2 | `ChatLayoutFixtureGenerator.GenerateChatFixture`; `RadarLayoutFixtureGenerator.GenerateRadarFixture` | Remove from default discovery and expose documented explicit generator commands. | +| 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. + +## 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 | open | Replace the LA8-specific shared attribute reason with truthful suite/prerequisite identity. | +| T-007 271 silent passing gates | open | Re-run the syntax inventory against current source, then convert each to a hermetic fixture, explicit prerequisite skip, or non-default 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 | open | Introduce a behavior-preserving injectable monotonic clock and deterministic fake time. | +| 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 | open | Validate the historical 51-method list against current source; add stable oracles or move them outside default discovery. | +| 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 | open | Reproduce and classify each mechanism; no retries or blanket tolerances. | +| T-015 four non-prerequisite skips | batch A plus lane work | Delete the PVS scaffold now; move two generators and the known failure in later focused batches. | +| T-016 historical test taxonomy | open | Rename/re-home only after each test's durable owner and oracle are established. | +| T-017 Avalonia ownership | resolved in R2 | All seven editor variants now execute in one owned application session; 11 focused passes plus the complete gate. | +| 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. diff --git a/tests/AcDream.App.Tests/Rendering/Gpu/GpuContractTests.cs b/tests/AcDream.App.Tests/Rendering/Gpu/GpuContractTests.cs index ed7c1a90..02334fba 100644 --- a/tests/AcDream.App.Tests/Rendering/Gpu/GpuContractTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Gpu/GpuContractTests.cs @@ -2,6 +2,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using AcDream.App.Rendering.Gpu; +using AcDream.App.Rendering.Gpu.Vk; namespace AcDream.App.Tests.Rendering.Gpu; @@ -242,19 +243,28 @@ public sealed class GpuContractTests } [Fact] - public void TheDepthStencilAttachmentFormatCarriesAStencilAspect() + public void BackbufferClear_ClearsDepthAndStencil() { - // The punch has nowhere to mark without one. The V5 capability gate - // prefers D32_SFLOAT_S8_UINT and falls back to D24_UNORM_S8_UINT rather - // than taking a depth-only format for exactly this reason, and the - // backbuffer pass clears both aspects through one ClearDepthStencil. GpuPassDescription pass = GpuPassDescription.BackbufferClear( "world", Vector4.Zero, sampleCount: 4); Assert.Equal(0u, pass.Depth!.Value.ClearStencil); + Assert.Equal(1f, pass.Depth.Value.ClearDepth); Assert.Equal(GpuLoadOp.Clear, pass.Depth!.Value.Load); - Assert.Equal(GpuTextureFormat.Depth24Stencil8, GpuTextureFormat.Depth24Stencil8); + } + + [Fact] + public void DepthStencilTextureFormat_MapsToDepthAndStencilAspects() + { + // The punch has nowhere to mark without a stencil aspect. The V5 + // capability gate prefers D32_SFLOAT_S8_UINT and falls back to + // D24_UNORM_S8_UINT rather than accepting a depth-only format. + Silk.NET.Vulkan.ImageAspectFlags aspects = + VulkanTextureFormatMapping.AspectOf(GpuTextureFormat.Depth24Stencil8); + + Assert.True(aspects.HasFlag(Silk.NET.Vulkan.ImageAspectFlags.DepthBit)); + Assert.True(aspects.HasFlag(Silk.NET.Vulkan.ImageAspectFlags.StencilBit)); } [Fact] diff --git a/tests/AcDream.Core.Tests/Conformance/PvsConformanceTests.cs b/tests/AcDream.Core.Tests/Conformance/PvsConformanceTests.cs deleted file mode 100644 index a11718ec..00000000 --- a/tests/AcDream.Core.Tests/Conformance/PvsConformanceTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Xunit; - -namespace AcDream.Core.Tests.Conformance; - -/// -/// PVS (portal-visibility) conformance — P0 scaffold. The render visible-set -/// golden. Retail oracle: PView::ConstructView(CEnvCell*) @ 0x005a57b0 -/// (pc:433750) produces the ordered cell_draw_list for a given (viewer_cell, -/// eye); see docs/research/2026-06-02-retail-render-pipeline-full-reference.md §3. -/// -/// FILLED IN P4, not P0: a retail cell_draw_list trace is a P3/P4-coupled -/// capture (a new cdb script breakpointing PView::DrawCells / cell_draw_list, -/// sibling to find-cell-list-capture.cdb), and the PVS code itself -/// (PortalVisibilityBuilder) is REPLACED by the ConstructView port in P4. The -/// scaffold exists now so the structure + retail anchor are in place; P4 adds -/// the capture + the golden assertion (PVS root id == physics CurrCell.Id; -/// a cell seen through two portals appears once per slice; dungeon -/// outside_view==0). -/// -public class PvsConformanceTests -{ - [Fact(Skip = "P0 scaffold — filled in P4 with a captured retail cell_draw_list trace")] - public void Pvs_CottageInterior_MatchesRetailCellDrawList() { } -} diff --git a/tests/AcDream.Core.Tests/Physics/Issue265SteepSlopeCaptureBisectTests.cs b/tests/AcDream.Core.Tests/Physics/Issue265SteepSlopeCaptureBisectTests.cs index aefacc55..bc04f05d 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue265SteepSlopeCaptureBisectTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue265SteepSlopeCaptureBisectTests.cs @@ -917,7 +917,9 @@ public class Issue265SteepSlopeCaptureBisectTests // HandleAllCollisions's OWN decision (captured before the toggle can // touch it) must be identical regardless of the #265/#166 fix -- the // fix does not change the reflection math or its inputs. - Assert.Equal(newModelVelocityBeforeToggle.Z > 0.01f, newModelVelocityBeforeToggle.Z > 0.01f); + Assert.Equal( + oldModelVelocity.Z > 0.01f, + newModelVelocityBeforeToggle.Z > 0.01f); // Document (not silently assert away) whether retail's OWN ported // logic reflects this synthetic case. This is evidence for the diff --git a/tests/AcDream.Core.Tests/Physics/MotionInterpreterTests.cs b/tests/AcDream.Core.Tests/Physics/MotionInterpreterTests.cs index e25596af..e62e1065 100644 --- a/tests/AcDream.Core.Tests/Physics/MotionInterpreterTests.cs +++ b/tests/AcDream.Core.Tests/Physics/MotionInterpreterTests.cs @@ -488,16 +488,12 @@ public sealed class MotionInterpreterTests // links). Verified against the live retail-observer trace // (RetailObserverTraceConformanceTests, 183/183 dispatch conformant). - // R3 owns removal of the known redundant row. Keep this one historical - // input unchanged during R2 while ensuring any new duplicate still fails. -#pragma warning disable xUnit1025 [Theory] [InlineData(MotionCommand.Fallen)] [InlineData(MotionCommand.Dead)] [InlineData(MotionCommand.Crouch)] [InlineData(MotionCommand.Sitting)] [InlineData(MotionCommand.Sleeping)] - [InlineData(0x41000012u)] // inside the crouch range (0x41000011, 0x41000015) public void ContactAllowsMove_GroundedPosture_StillAllowsMove(uint postureCommand) { var body = MakeGrounded(); @@ -508,7 +504,6 @@ public sealed class MotionInterpreterTests Assert.True(allowed); } -#pragma warning restore xUnit1025 [Fact] public void ContactAllowsMove_AirborneCreature_AcceptsFallingAndTurns_BlocksWalk() diff --git a/tests/AcDream.Core.Tests/Rendering/ChaseCameraTests.cs b/tests/AcDream.Core.Tests/Rendering/ChaseCameraTests.cs index bd1ebfec..a91b3001 100644 --- a/tests/AcDream.Core.Tests/Rendering/ChaseCameraTests.cs +++ b/tests/AcDream.Core.Tests/Rendering/ChaseCameraTests.cs @@ -54,11 +54,4 @@ public class ChaseCameraTests Assert.True(z2 > z1, "Increasing pitch should raise the camera"); } - - [Fact] - public void ImplementsICamera() - { - ICamera camera = new ChaseCamera { Aspect = 16f / 9f }; - camera.ToString(); // just proves interface is implemented - } } diff --git a/tests/AcDream.Core.Tests/SmokeTest.cs b/tests/AcDream.Core.Tests/SmokeTest.cs deleted file mode 100644 index 3f711017..00000000 --- a/tests/AcDream.Core.Tests/SmokeTest.cs +++ /dev/null @@ -1,11 +0,0 @@ -// tests/AcDream.Core.Tests/SmokeTest.cs -namespace AcDream.Core.Tests; - -public class SmokeTest -{ - [Fact] - public void TestProject_IsWired() - { - Assert.True(true); - } -} diff --git a/tests/AcDream.Runtime.Tests/Gameplay/RuntimeLocalPlayerFirstEntryStateTests.cs b/tests/AcDream.Runtime.Tests/Gameplay/RuntimeLocalPlayerFirstEntryStateTests.cs index f76387cb..913a9048 100644 --- a/tests/AcDream.Runtime.Tests/Gameplay/RuntimeLocalPlayerFirstEntryStateTests.cs +++ b/tests/AcDream.Runtime.Tests/Gameplay/RuntimeLocalPlayerFirstEntryStateTests.cs @@ -425,6 +425,7 @@ public sealed class RuntimeLocalPlayerFirstEntryStateTests { using var fixture = new Fixture(residentWorld: false); PhysicsBody? body = null; + PlayerMovementController? controller = null; for (int i = 0; i < 3; i++) { @@ -435,7 +436,10 @@ public sealed class RuntimeLocalPlayerFirstEntryStateTests Assert.Equal(1, fixture.Publication.CaptureOwnership().PendingActivationCount); body ??= fixture.Record.PhysicsBody; Assert.Same(body, fixture.Record.PhysicsBody); - Assert.Same(fixture.Movement.Controller, fixture.Movement.Controller); + PlayerMovementController currentController = + Assert.IsType(fixture.Movement.Controller); + controller ??= currentController; + Assert.Same(controller, currentController); } }