From 9c6b143a03cf4b96a593c53764393b7932323f2d Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 18 Aug 2026 12:25:00 +0200 Subject: [PATCH] test: replace campaign labels with behavior names --- .../retail-divergence-register.md | 2 +- .../2026-08-18-r3-test-truth-ledger.md | 46 +++++++++++++++++- .../Rendering/FramebufferResizeController.cs | 2 +- .../Gameplay/RuntimeCharacterState.cs | 2 +- ...> ConnectedWorldSoakRouteContractTests.cs} | 2 +- ...ityNetworkOnPositionCollapseMatrixTests.cs | 9 ++-- .../Rendering/GameWindowCrashStatusTests.cs | 2 +- ...ests.cs => GameWindowHostBoundaryTests.cs} | 14 +++--- ...veEntityCreateSupersessionRecoveryTests.cs | 2 +- .../Runtime/CurrentGameRuntimeAdapterTests.cs | 6 +-- .../Layout/ChatOptionsPageControllerTests.cs | 4 +- ...reateAuthorityDriftModelSourcePinTests.cs} | 5 +- .../LiveEntityHydrationControllerTests.cs | 10 ++-- ...StaticSpherePopulationMeasurementTests.cs} | 2 +- ...eTests.cs => EntryRestrictionGateTests.cs} | 2 +- .../Physics/Motion/ConstraintManagerTests.cs | 6 +-- ...gerHarness.cs => PhysicsManagerHarness.cs} | 6 +-- .../Motion/PositionManagerFacadeTests.cs | 8 ++-- .../Physics/Motion/StickyManagerTests.cs | 48 +++++++++---------- .../Physics/Motion/TargetManagerTests.cs | 22 ++++----- .../MotionInterpreterDoMotionFamilyTests.cs | 2 +- .../MotionInterpreterJumpFamilyTests.cs | 4 +- ... => SortingSphereFloodMeasurementTests.cs} | 2 +- ...manticsTests.cs => WaterSemanticsTests.cs} | 2 +- .../HeadlessProcessResourceEnvelopeTests.cs | 2 +- .../LauncherOrchestratorTests.cs | 2 +- .../GameRuntimeContractTests.cs | 4 +- .../Gameplay/RuntimeGameplayOwnershipTests.cs | 2 +- .../RuntimeSimulationFixtureHostTests.cs | 2 +- .../Input/KeyBindingsTests.cs | 10 ++-- 30 files changed, 135 insertions(+), 97 deletions(-) rename tests/AcDream.App.Tests/Diagnostics/{ConnectedR6SoakContractTests.cs => ConnectedWorldSoakRouteContractTests.cs} (99%) rename tests/AcDream.App.Tests/Rendering/{GameWindowSlice8BoundaryTests.cs => GameWindowHostBoundaryTests.cs} (98%) rename tests/AcDream.App.Tests/World/{C3cR1F3DriftModelSourcePinTests.cs => CreateAuthorityDriftModelSourcePinTests.cs} (94%) rename tests/AcDream.Content.Tests/{Ap155StaticSpherePopulationMeasurementTests.cs => StaticSpherePopulationMeasurementTests.cs} (98%) rename tests/AcDream.Core.Tests/Physics/{Ap71EntryRestrictionGateTests.cs => EntryRestrictionGateTests.cs} (99%) rename tests/AcDream.Core.Tests/Physics/Motion/{R5ManagerHarness.cs => PhysicsManagerHarness.cs} (95%) rename tests/AcDream.Core.Tests/Physics/{Ap157SortingSphereFloodMeasurementTests.cs => SortingSphereFloodMeasurementTests.cs} (99%) rename tests/AcDream.Core.Tests/Physics/{Ap10WaterSemanticsTests.cs => WaterSemanticsTests.cs} (99%) diff --git a/docs/architecture/retail-divergence-register.md b/docs/architecture/retail-divergence-register.md index c10d51cb..a12386d0 100644 --- a/docs/architecture/retail-divergence-register.md +++ b/docs/architecture/retail-divergence-register.md @@ -252,7 +252,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps. | AP-154 | **Filed 2026-08-06 at the AP-152 retirement (contract §11.6) — an undeclared dependency on a specific server implementation.** Retail COMPUTES `HAS_PHYSICS_BSP_PS` itself from its own part array (AP-153's anchors). acdream's query-time guard `Transition.BspOnlyDispatch` reads it out of the SERVER's wire `PhysicsState`: `LiveEntityCollisionBuilder.cs:161` copies `exactRecord.FinalPhysicsState` into `ShadowEntry.State`, and a repo-wide grep for `PhysicsStateFlags.HasPhysicsBsp` in `src/` returns only that predicate and one unrelated mover-state read. acdream never ORs the bit in client-side. It happens to be correct because ACE derives the same DAT bit (`WorldObject_Networking.cs:665-668` from `SetupFlags.HasPhysicsBSP`), overriding the weenie's authored value — which is why a 2018 weenie dump showing `PhysicsState = 0x8` for the cottage door does not contradict our own live capture of `0x10008`. | `src/AcDream.Core/Physics/TransitionTypes.cs:1348` (`BspOnlyDispatch`), call sites `:3911` / `:3954`; `src/AcDream.App/Physics/LiveEntityCollisionBuilder.cs:161` | Narrowed, not closed, by the AP-152 fix: the shape list no longer contains a primitive for a BSP-bearing object, so the guard has nothing left to skip and the OUTCOME is now independent of the wire. The guard itself still keys on the wire. Not bundled — changing `registration.State` touches every consumer of `FinalPhysicsState` (Hidden, Missile, ethereal layer 2, the `[setstate]` log) and needs its own gate. | Against a server that does not derive the bit from the DAT, a BSP-bearing object built by a producer other than `FromSetup` would have its primitive tested where retail tests only the BSP. | `CPartArray::CacheHasPhysicsBSP` 0x00518110 (derives) vs `LiveEntityCollisionBuilder.cs:161` (copies); `HAS_PHYSICS_BSP_PS` acclient.h:2833 | | AP-155 | **NARROWED AGAIN 2026-08-07 (Campaign S S2) — the Sphere-as-Cylinder emission half is FIXED; what survives is ONLY the has-BSP source split.** Both static publication sites now emit an authored Setup Sphere as `ShadowShape.Sphere`, mirroring the live path's emission exactly (route-independence asserted shape-for-shape incl. CylHeight; dispatch discriminated by a graze/through pair whose cylinder counterfactual verdicts differ numerically; both sites sabotage-reddened independently; population 3,506 of 5,935 installed Setups, structurally equal to AP-157's third-branch count). The flood centre rises by exactly r for this population — outdoor membership unaffected (XY rectangle), indoor EnvCell membership covered by the Session-B dungeon gate. **What remains:** the static paths derive has-BSP from `entity.MeshRefs` where the live path derives it from `setup.Parts` plus post-AnimPartChanged identities; the two sources can disagree, and that half keeps this row ACTIVE. A shared primitive-emitter refactor (compile-time route independence instead of empirical parity tests) is the filed follow-up. Original text: **Filed 2026-08-06 at the AP-152 retirement; NARROWED 2026-08-06 to its static-publication half alone.** Its flood half was bundled here with a different code path, a different population and a different gate — the exact fault the C4 handoff warns about — and its direction was recorded BACKWARDS; both are now split out as AP-156. **Static paths emit a Setup Sphere as a height-capped CYLINDER.** `LandblockPhysicsPublisher.cs:1030-1037` and `LandblockPhysicsContentBuilder.cs:683-690` both convert a Setup Sphere to `ShadowCollisionType.Cylinder` with `CylHeight = radius * 2f` and the origin shifted down by one radius; the live path emits a true `ShadowCollisionType.Sphere`, produced at exactly ONE site in `src/` (`ShadowShapeBuilder.cs`). Retail tests a Setup Sphere with `CSphere::intersects_sphere` @0x00537a80 / @0x00537fd0 (two overloads) in both cases — 3-D distance, no height clamp. The static paths also derive "has BSP" from `entity.MeshRefs` (the render mesh list) where the live path derives it from `setup.Parts` plus the effective post-`AnimPartChanged` identities; the two sources can disagree. | `src/AcDream.App/Streaming/LandblockPhysicsPublisher.cs:1030-1037`; `src/AcDream.Content/LandblockPhysicsContentBuilder.cs:683-690` | Affects static props only and changes their collision geometry over a much larger population than AP-152's 172, so it needs its own count and its own gate. Deliberately not folded into the AP-152 or AP-156 commits. | A static prop whose Setup carries a Sphere blocks over a height-clamped cylinder instead of a true sphere, and rests one radius lower than the authored origin. | `CSphere::intersects_sphere` 0x00537a80 / 0x00537fd0 | | AP-156 | **SCALE RESIDUAL DECIDED 2026-08-08 by the user: KEEP OURS — permanent, deliberate divergence in the SAFE direction.** acdream sizes the flood bubble to the object's actual placed scale; retail ignores the resize and floods at authored size, which under-registers ENLARGED objects (their real geometry pokes into neighbouring cells retail never lists them in — a walk-through edge case at cell boundaries). Copying retail would import that bug for byte-fidelity; the user chose not to. This row's scale question is CLOSED and must not be re-opened as a faithfulness cleanup. **Filed 2026-08-06, split out of AP-155(b) at the AP-152 retail-conformance review, WITH ITS DIRECTION CORRECTED — and its worst half FIXED in the same commit.** **CORRECTION.** AP-155(b) recorded the flood approximation as *over*-inclusive ("a sphere contains the box's inscribed extent but is larger in the diagonal"), and that recorded direction was the stated reason the residual was safe to defer. It was empirically inverted. `BuildFloodSpheres` took each physics-BSP part's ROOT BOUNDING SPHERE RADIUS (`FlatCollisionAssetBuilder.cs:393` -> `LiveEntityCollisionBuilder.cs:137`) and centred it on the PART ORIGIN (`ShadowShapeBuilder.cs:194`), discarding the root sphere's own `Origin`. Measured over the installed `client_portal.dat`, independently twice: 376 of 973 physics-BSP parts have `|origin| > radius/2`, worst 20.762 m on a 27.708 m sphere (gfx 0x010036DD, Setup 0x0200129A); **POPULATION CORRECTED 2026-08-06 at the fix review (finding R2).** The row as filed said the flood failed to contain the object's own BSP sphere for '170 of the 172 AP-152 Setups'. That understates it: 172 is AP-152's DISPATCH population (Setups carrying BOTH a primitive and a physics-BSP part). After AP-152 EVERY BSP-bearing Setup floods from its BSP shapes alone, so the discarded origin mis-placed the flood across all 530 of them. Re-measured against PHYSICS-POLYGON VERTICES — a different DAT field from the sphere, so the measurement is not circular — by an independent scratch program outside the repo: **525 of the 530** BSP-bearing Setups have at least one flood sphere move; **428** fail vertex-level containment at a 1 mm tolerance (412 at 1 cm, the figure the fix review quotes); **0** fail after the fix, at any tolerance down to zero. Worst shortfall 35.869 m at entity scale 1.75 on Setup 0x0200129A. The old figures — 170 of 172, worst 9.911 m on 0x02000255 — remain correct for what they measured (root-sphere containment over the 172), and 43 of them had a post-AP-152 flood strictly SMALLER than the pre-AP-152 one. Indoor floods are 3-D (`CellTransit.cs:601` routes every `id & 0xFFFF >= 0x0100` candidate through `FindTransitCellsSphere`), so a tall prop or door slab was simply absent from EnvCells it occupies and never a broadphase candidate there — UNDER-inclusive membership, the #98 / #168 class. **FIXED HERE.** `ShadowShape.BoundsCenter` carries the root sphere's own centre in the shape's local frame; `FromSetup` and `FromLandblockBspParts` fill it from the SAME resolver that supplies the radius, and `BuildFloodSpheres` places the sphere at `partWorldPos + rotate(BoundsCenter, partWorldRot)`. Retail does exactly this: `CGfxObj::physics_sphere` (`[gfxobj+0x74]`) is assigned `BSPTREE::GetSphere(physics_bsp)` @0x005397e0 (`mov eax,[ecx]; add eax,4` — the root `BSPNODE`'s `CSphere`, past its 4-byte vftable), and `CEnvCell::find_transit_cells` @0x0052cae0 — the part-array overload reached from `CPhysicsObj::find_bbox_cell_list` @0x00510fc0 through `CPartArray::calc_cross_cells_static` @0x00518160's `[vtbl+0x7c]` dispatch — loads it at `0x0052cb36 mov esi,[ecx+0x74]`, transforms its CENTRE through the part's own `Position` at `[part+0x30]` (`0x0052cb4c add eax,0x30` / `0x0052cb5a call Position::localtolocal`), and only then reads the radius at `0x0052cb65 fadd [esi+0xc]`. The same commit also retired the 10-sphere clamp on this branch: retail's clamp lives inside the CYLSPHERE overload alone (`CObjCell::find_cell_list` @0x0052b9f0, `0x0052ba21 cmp eax,0xa` / `0x0052ba28 mov ebp,0xa`) while the BSP walk has none — 7 installed Setups carry more than 10 physics-BSP parts (max 49, Setup 0x02001A91) and their tail parts were dropped from the flood entirely. **WHAT REMAINS OPEN.** acdream floods from the per-part spheres through its own sphere-vs-portal walk (`CellTransit.FindTransitCellsSphere`), where retail hands the part array to each cell's own `find_transit_cells` and tests every part's sphere against that cell's portal planes in cell-local space. The sphere SET is now exact; the TRAVERSAL is still acdream's. `find_bbox_cell_list`'s name notwithstanding, retail never forms a bounding box — AP-155(b)'s "acdream approximates retail's bounding BOX" was wrong as well. **SECOND RESIDUAL, added 2026-08-06 at the fix review (finding R4): acdream SCALES the flood sphere; retail does not.** `ShadowShapeBuilder` multiplies both the radius and (new in this commit) the centre by the entity/part scale. Retail's `CEnvCell::find_transit_cells` @0x0052cae0 reads only `CPhysicsPart::pos` (`[part+0x30]`) and never `CPhysicsPart::gfxobj_scale` (`[part+0x24]`), while `CPhysicsPart::find_obj_collisions` @0x0050d8d0 DOES thread `gfxobj_scale.z` into `SPHEREPATH::cache_localspace_sphere` — so retail's cross-cell walk is itself under-inclusive for scaled parts and acdream's is not. Over-inclusive for scale > 1 (safe), under-inclusive for scale < 1 (the #98/#168 direction). **ENFORCEMENT, added 2026-08-06 at the fix review (finding A1).** The invariant now lives at the TYPE, not only at the producer seam: `ShadowShape`'s constructor is private and BSP shapes are built only through `ShadowShape.Bsp(..., FlatCollisionSphere localBounds)`, which takes radius and centre as ONE value and scales them together. The former public 7-argument constructor with `BoundsCenter = default` let a future BSP producer reintroduce this exact bug silently and green. **CONNECTED-GATE NOTE (finding A2). A null result on tall props is EXPECTED until AP-158 / #333 lands, and is not evidence against this fix.** The geometry now lands in the right cell and is then discarded one layer down by acdream's own `maxReach` broadphase filter, which measures from the same part origin: 118 of the 477 unique installed physics-BSP GfxObjs have a root-sphere offset above that filter's roughly 2.5 m walking budget, and 46 above 5 m. | `src/AcDream.Core/Physics/ShadowShape.cs` (`BoundsCenter`); `src/AcDream.Core/Physics/ShadowShapeBuilder.cs` (`FromSetup` step 3, `FromLandblockBspParts`); `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` (`BuildFloodSpheres`); `src/AcDream.App/Physics/LiveEntityCollisionBuilder.cs` (single bounds resolver); tests `ShadowObjectRegistryMultiPartTests.BuildFloodSpheres_BspShape_CentresOnTheBoundsCentreNotThePartOrigin` / `_RotatesTheBoundsCentreByThePartRotation` / `_CapsCylSpheresAtTenButNeverTheBspParts`, `ShadowRegistrationOverflowTests.FromLandblockBspParts_CarriesTheScaledRootSphereCentre`, `InstalledSetupBspPrimitiveDispatchTests.InstalledSetups_BspFloodSpheres_ContainTheirOwnPhysicsPolygons` (oracle swapped to physics-polygon vertices at the fix review, finding R1: the shipped assertion compared two hand-copies of the same expression and was algebraically identically zero for any DAT input) | The traversal residual is a genuine approximation with its own gate, not a deferral of this fix. Closing it means porting the per-cell `find_transit_cells` part-array overload, which is different work from getting the sphere set right. **OUTDOOR HALF CLOSED 2026-08-06 by #334 (see AP-159 for what remains).** | **RISK COLUMN CORRECTED 2026-08-06 at the #334 fix — as written below it was FALSE, and its falsity is what let #334 sit unnoticed inside this row.** It generalised the INDOOR direction (sphere-vs-portal-plane, over-inclusive) to the whole residual. The OUTDOOR direction was the opposite and strictly worse: acdream routed BSP-bearing objects through `CObjCell::find_cell_list`, whose outdoor expansion is a hard-capped ±1-cell 3×3 for ANY radius, so every formation wider than one 24 m land cell was MISSED in its outer cells — a user-observed loss of collision, not extra candidates. Original text, retained for the record: *"A cell whose portal geometry a part's sphere overlaps in the sphere-vs-plane sense, but which the part's actual polygons do not reach, joins the object's shadow set: extra broadphase candidates, never a missed one. The under-inclusive direction is what the fix above removed."* That statement now holds only for the indoor half, which is AP-159. | `BSPTREE::GetSphere` 0x005397e0; `CGfxObj::physics_sphere` `[gfxobj+0x74]`; `CEnvCell::find_transit_cells` 0x0052cae0 (0x0052cb36 / 0x0052cb4c / 0x0052cb65); `CPhysicsObj::find_bbox_cell_list` 0x00510fc0; `CPartArray::calc_cross_cells_static` 0x00518160; `CObjCell::find_cell_list` 0x0052b9f0 (0x0052ba21) | -| AP-157 | **MEASURED AND RE-SCOPED 2026-08-07 (Campaign S S1A) — one half RETIRED as a non-divergence, the other half CONFIRMED against retail's registration set but PROVEN collision-unreachable; fix deferred.** **CylHeight half: RETIRED.** `CObjCell::find_cell_list`'s cylsphere overload @0x0052b9f0 (pseudo-C 309107) copies `Position::localtoglobal(low_pt)` + `radius` per cylsphere, capped at 10, and NEVER reads height — retail itself collapses a cylsphere to a base-point sphere of the cylinder radius. acdream's cylinder flood is exactly retail's behaviour; the row's implication that height matters was wrong. **Sorting-sphere half: measured over the installed DAT** (`Ap157SortingSphereFloodMeasurementTests`): third-branch population 3,506 of 5,935 Setups (cross-checked: 3,605 sphere-only-no-cylinder minus 99 BSP-dispatched, matching the independently-committed dispatch-test constants); 163 with a zero authored SortingSphere; of the 3,343 evaluated, **1,812 (54%) fail containment at 1 mm** (1,722 at 1 cm), worst shortfall 18.135 m (Setups 0x02000D7D / 0x020015B3), while max overshoot is only 1.900 m — overwhelmingly the under-inclusive direction relative to RETAIL'S REGISTRATION SET. **BUT: no collision outcome can differ.** For this branch the flood spheres and the collision-test geometry are the SAME per-part Sphere list, so every cell acdream omits is a cell the entity's test geometry cannot reach; retail's sorting-sphere flood is wider than ITS OWN per-sphere tests too, so its extra registrations are narrow-phase rejects. The divergence is a registration-set fidelity gap with a perf sign in acdream's favour, not a walk-through. **Fix deferred deliberately:** flooding from the authored sorting sphere needs `SortingSphere` plumbed through `FlatSetupCollision` and the bake schema (Slice I3 version protocol) — real risk for zero behavioural delta. Take it opportunistically at the next bake-schema revision. Original text: **Filed 2026-08-06 at the AP-152 retail-conformance review (finding F4) — an unregistered substitution that predates AP-152 and was stepped over when its neighbours were filed.** `CPhysicsObj::calc_cross_cells`' THIRD branch (`0x005152dc` -> `CPartArray::GetSortingSphere` @0x00518b00 -> `CObjCell::find_cell_list` @0x0052b990) floods from ONE authored whole-object sphere: `GetSortingSphere` returns `[partArray+0x54] + 0x70`, i.e. `CSetup::sorting_sphere` (acclient.h: `CSetup` carries `CSphere sorting_sphere` immediately after `step_up_height`), and that overload takes a single sphere with no cap. acdream's `only == null` branch floods from EVERY non-BSP, non-Cylinder shape instead — the Setup's per-part `Spheres` array. Different DAT field, different cardinality, different extent. 4,154 of 5,935 installed Setups carry a non-zero `SortingSphere` and `DatReaderWriter.Setup` already exposes it, so this is available rather than blocked. Same site, second item: `BuildFloodSpheres` collapses a Cylinder to one sphere at its BASE point with the cylinder radius and IGNORES `CylHeight` entirely, where retail's `CObjCell::find_cell_list` @0x0052b9f0 is handed the `CCylSphere` array as `(low_pt, radius, height)`. | `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` (`BuildFloodSpheres`, the `anyCyl` and `only == null` branches) | Deliberately NOT folded into the AP-156 fix. It is a different branch of `calc_cross_cells`, reached only by objects with neither a physics BSP nor a CylSphere, so its population is disjoint from the 172 AP-152 Setups and its live gate is a different set of objects. Bundling it would make the AP-156 connected gate un-attributable — which is exactly how AP-155 came to carry two lifecycles under one id. | Sorting-sphere half: an object with several authored Spheres floods from all of them rather than from the one authored whole-object sphere — usually wider (max 5 Spheres on any installed Setup, so retail's 10-cap is never the difference), but a `sorting_sphere` LARGER than every per-part Sphere would make acdream under-inclusive, the #98 / #168 direction. CylHeight half: a tall thin cylinder floods a sphere of its radius at its base and can miss the cells its upper half occupies. | `CPhysicsObj::calc_cross_cells` 0x00515230 (0x005152dc / 0x005152e3 / 0x005152fb); `CPartArray::GetSortingSphere` 0x00518b00 (`[+0x54]+0x70`); `CObjCell::find_cell_list` 0x0052b990 (sorting sphere) / 0x0052b9f0 (cylsphere, `(low_pt, radius, height)`) | +| AP-157 | **MEASURED AND RE-SCOPED 2026-08-07 (Campaign S S1A) — one half RETIRED as a non-divergence, the other half CONFIRMED against retail's registration set but PROVEN collision-unreachable; fix deferred.** **CylHeight half: RETIRED.** `CObjCell::find_cell_list`'s cylsphere overload @0x0052b9f0 (pseudo-C 309107) copies `Position::localtoglobal(low_pt)` + `radius` per cylsphere, capped at 10, and NEVER reads height — retail itself collapses a cylsphere to a base-point sphere of the cylinder radius. acdream's cylinder flood is exactly retail's behaviour; the row's implication that height matters was wrong. **Sorting-sphere half: measured over the installed DAT** (`SortingSphereFloodMeasurementTests`): third-branch population 3,506 of 5,935 Setups (cross-checked: 3,605 sphere-only-no-cylinder minus 99 BSP-dispatched, matching the independently-committed dispatch-test constants); 163 with a zero authored SortingSphere; of the 3,343 evaluated, **1,812 (54%) fail containment at 1 mm** (1,722 at 1 cm), worst shortfall 18.135 m (Setups 0x02000D7D / 0x020015B3), while max overshoot is only 1.900 m — overwhelmingly the under-inclusive direction relative to RETAIL'S REGISTRATION SET. **BUT: no collision outcome can differ.** For this branch the flood spheres and the collision-test geometry are the SAME per-part Sphere list, so every cell acdream omits is a cell the entity's test geometry cannot reach; retail's sorting-sphere flood is wider than ITS OWN per-sphere tests too, so its extra registrations are narrow-phase rejects. The divergence is a registration-set fidelity gap with a perf sign in acdream's favour, not a walk-through. **Fix deferred deliberately:** flooding from the authored sorting sphere needs `SortingSphere` plumbed through `FlatSetupCollision` and the bake schema (Slice I3 version protocol) — real risk for zero behavioural delta. Take it opportunistically at the next bake-schema revision. Original text: **Filed 2026-08-06 at the AP-152 retail-conformance review (finding F4) — an unregistered substitution that predates AP-152 and was stepped over when its neighbours were filed.** `CPhysicsObj::calc_cross_cells`' THIRD branch (`0x005152dc` -> `CPartArray::GetSortingSphere` @0x00518b00 -> `CObjCell::find_cell_list` @0x0052b990) floods from ONE authored whole-object sphere: `GetSortingSphere` returns `[partArray+0x54] + 0x70`, i.e. `CSetup::sorting_sphere` (acclient.h: `CSetup` carries `CSphere sorting_sphere` immediately after `step_up_height`), and that overload takes a single sphere with no cap. acdream's `only == null` branch floods from EVERY non-BSP, non-Cylinder shape instead — the Setup's per-part `Spheres` array. Different DAT field, different cardinality, different extent. 4,154 of 5,935 installed Setups carry a non-zero `SortingSphere` and `DatReaderWriter.Setup` already exposes it, so this is available rather than blocked. Same site, second item: `BuildFloodSpheres` collapses a Cylinder to one sphere at its BASE point with the cylinder radius and IGNORES `CylHeight` entirely, where retail's `CObjCell::find_cell_list` @0x0052b9f0 is handed the `CCylSphere` array as `(low_pt, radius, height)`. | `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` (`BuildFloodSpheres`, the `anyCyl` and `only == null` branches) | Deliberately NOT folded into the AP-156 fix. It is a different branch of `calc_cross_cells`, reached only by objects with neither a physics BSP nor a CylSphere, so its population is disjoint from the 172 AP-152 Setups and its live gate is a different set of objects. Bundling it would make the AP-156 connected gate un-attributable — which is exactly how AP-155 came to carry two lifecycles under one id. | Sorting-sphere half: an object with several authored Spheres floods from all of them rather than from the one authored whole-object sphere — usually wider (max 5 Spheres on any installed Setup, so retail's 10-cap is never the difference), but a `sorting_sphere` LARGER than every per-part Sphere would make acdream under-inclusive, the #98 / #168 direction. CylHeight half: a tall thin cylinder floods a sphere of its radius at its base and can miss the cells its upper half occupies. | `CPhysicsObj::calc_cross_cells` 0x00515230 (0x005152dc / 0x005152e3 / 0x005152fb); `CPartArray::GetSortingSphere` 0x00518b00 (`[+0x54]+0x70`); `CObjCell::find_cell_list` 0x0052b990 (sorting sphere) / 0x0052b9f0 (cylsphere, `(low_pt, radius, height)`) | | ~~AP-158~~ | **RETIRED 2026-08-06 — the filter is DELETED, not re-centred, and this row's own disassembly is why.** The minimal fix this row proposed (carry `BoundsCenter` on `ShadowEntry` and measure from the true centre) was deliberately NOT taken: it would have preserved an invention retail does not have, kept a `+ 2f` slack and a `movement.Length()` term with no retail counterpart, and left a second reach budget to be tuned forever. `Transition.FindObjCollisionsInCell` now walks the cell's shadow list with no distance pre-check at all, as `CObjCell::find_obj_collisions` @0x0052b750 does. Cell membership is retail's broad phase, and the BSP walk's own root-node bounding-sphere test — centred correctly, which is precisely what this filter was not — is the early-out that made a second one unnecessary. **This retirement closes #333 and #337** (the Neftet plateau: wedged at the top, jumps sinking into the mesh, corpses falling through), whose mechanism it was. **The row's predicted symptom was observed live before it was fixed**, which is the strongest confirmation a register row gets: it predicted a tall prop AP-156 had just placed correctly would still not block, and the user reported exactly that at Neftet. **PERF, MEASURED rather than assumed** (Release, synthetic all-BSP cell, per `ResolveWithTransition`): at 38 candidates — the live maximum — 10.61 µs → 16.68 µs (+6.07, 1.57×); at a deliberately unreachable 200, 17.34 µs → 39.48 µs (2.28×); ≈ 0.16 µs per additional candidate tested. Over 19,701 live `[reach-q]` samples the in-cell candidate count is p50 = 9, p99 = 32, max 38, so the first row is the bound that matters. **Original text, retained for the record:** **Filed 2026-08-06 at the AP-156 fix review (finding A2) — an UNREGISTERED INVENTION, not a port, that predates AP-156 and is issue #333.** The shadow broadphase discards a candidate outright when `distToCurr > sphereRadius + obj.Radius + movement.Length() + 2f`. **Retail has no distance pre-filter at all.** `CObjCell::find_obj_collisions` @0x0052b750, disassembled from the PDB-paired binary for this row rather than inherited: it early-returns `OK_TS` only when `sphere_path.insert_type == INITIAL_PLACEMENT_INSERT` (`0x0052b759 cmp dword [ebx+0x174],2` / `0x0052b765 je 0x52b7a0`), then walks `shadow_object_list` (`[cell+0xc8]`, count `[cell+0xc4]`) and calls `CPhysicsObj::FindObjCollisions` (`0x0052b78b call 0x50f050`) on every entry whose `physobj` is unparented (`[physobj+0x40] == 0`) and is not the mover itself — UNCONDITIONALLY. There is no distance test in the function. Neither the `+ 2f` slack nor the `movement.Length()` term has a retail counterpart; retail's own cross-cell slack constant is `F_EPSILON` = 1.9999999e-4 m (`0x0052cb5f fld dword [0x7c8c70]`), 0.0002 m and not 2 m. **Second half of the defect:** the filter measures `currPos - obj.Position`, i.e. from the PART ORIGIN, while `obj.Radius` is the BSP root bounding-sphere radius measured about a centre that AP-156 established is frequently metres away — `ShadowEntry` does not carry the `BoundsCenter` that `ShadowShape` now does. A mover touching the geometry is up to `d + R + r` from the part origin and is admitted only when `d <= movement + 2`, roughly 2.5 m for a walking player. | `src/AcDream.Core/Physics/TransitionTypes.cs:3757-3765`; `ShadowEntry` (`src/AcDream.Core/Physics/ShadowObjectRegistry.cs:2735`) carries no `BoundsCenter`; **RETIRED:** the pre-check is gone from `FindObjCollisionsInCell` and `ShadowEntry` needs no `BoundsCenter`. Tests `Issue333BroadphaseReachFilterTests.OffCentreBspFloorStopsAFallingMover` (production path end-to-end, DAT-free, sabotage-verified against its `CentredBspFloorStopsAFallingMover` control — restore the pre-check and the mover falls straight through to the unobstructed 37.800 while the control still blocks) and `Issue337NeftetRockGeometryInspectionTests.TheOldBroadphaseMeasuredToTheOriginAndSoRejectedGeometryItStoodOn` (installed-DAT evidence, both halves of the diagnosis) | Deliberately NOT folded into the AP-156 commit: different code path (collision query, not cell membership) and it needed its own retail question answered, which this row answers. The minimal fix is mechanical — carry `BoundsCenter` on `ShadowEntry` and measure from `obj.Position + rotate(obj.BoundsCenter, obj.Rotation)`; only whether to keep the `+ 2f` slack at all is genuinely open. | **RETIRED — no residual.** The `rejectedReach` column of the `ACDREAM_PROBE_REACH` family is kept and is now structurally 0, precisely so a post-fix capture is directly comparable with the pre-fix one that recorded 7,225 rejections on a single owner, every one with `wouldAcceptAtCenter=True`. Original risk text, retained for the record: **This is the gate immediately downstream of AP-156, and it can mask AP-156's entire visible benefit.** 118 of the 477 unique installed physics-BSP GfxObjs have a root-sphere offset above the ~2.5 m budget and 46 above 5 m; at a test scale of 1.75 those become 4.4 m and 8.75 m against an unchanged budget. Worked case: Setup 0x02000255, one part, root sphere origin (0.000, -0.007, 9.911), radius 10.522 — a player against its upper half is ~20.4 m from the part origin while `maxReach` is ~13.5 m. Discarded before `BSPQuery` ever runs. A tall prop that still does not block after AP-156 is THIS row, not a failure of AP-156. | `CObjCell::find_obj_collisions` 0x0052b750 (0x0052b759 / 0x0052b765 / 0x0052b788 / 0x0052b78b), pseudo-C 308916-308940; `CEnvCell::find_transit_cells` 0x0052cae0 (`F_EPSILON` at 0x0052cb5f -> 0x7c8c70); issue #333 | | AP-159 | **NARROWED 2026-08-07 (Campaign S S1B) — the INDOOR part-array arm is PORTED; what remains is the BUILDING BRIDGE plus a one-ULP boundary tie.** `CellTransit.FindTransitCellsBox` now runs retail's per-portal x per-part walk (`CEnvCell::find_transit_cells` @0x0052cae0): sphere cheap-reject at F_EPSILON+radius, BOX admit via the 8-corner classification, leads-outside after the admit, destination `box_intersects_cell` gate through the flat-authoritative dispatcher with a graph referee (20,000 installed comparisons pinned by assertion, zero mismatch). Dual-review PASS; sabotage discriminating; installed direction sweep: rigged population shrinks 978 cells/0 added across 1,520 placements; production-ratio population (box >= sphere, the real relationship — the box is the whole-vertex AABB while the sphere bounds only physics polygons) measured 1 ADD through the loaded-neighbour gate in 950 placements, which is RETAIL-CORRECT direction, so the old 'over-inclusive only, never a missed one' severity line is retired with the port. **REMAINDER 1 — the building bridge:** `CheckBuildingTransit` still admits on the sphere test; its retail counterpart is the part-array `check_building_transit` @0x0052c680 (NOT @0x0052c5d0 — D0 disentangled the function boundaries), whose portal_side convention is INVERTED relative to find_transit_cells (byte table in the retail review §6) and whose admit accepts `eax == 3 || eax == side`; the in-plane early exit of `Plane::intersect_box` is byte-confirmed to return CROSSING(3) (jp @0x005aa1bc -> mov eax,3 @0x005aa2e2), so that porter inherits both traps settled. **REMAINDER 2 — one-ULP tie:** our `WhichSide` returns Positive at exactly dist==eps where retail's strict `>` says IN_PLANE (byte-decoded @0x00444720); measure-zero, float-exact-equality only. Original text: **Filed 2026-08-06 at the #334 fix - the INDOOR half of AP-156's traversal residual, now the whole of it.** #334 ported retail's `CPhysicsObj::find_bbox_cell_list` @0x00510fc0 path so a physics-BSP object's OUTDOOR membership is the filled land-cell rectangle its authored `CGfxObj::gfx_bound_box` spans (`CLandCell::add_all_outside_cells` @0x00533360 -> `add_cell_block` @0x005331d0). The INDOOR arm of that same walk is NOT ported: retail's part-array `CEnvCell::find_transit_cells` @0x0052cae0 admits a neighbour cell on a BOX test - `CPhysicsPart::GetBoundingBox` @0x0050d600 -> `BBox::LocalToLocal` @0x005b1e60 (`0x0052cbf9`) -> `Plane::intersect_box` @0x005aa170 (`0x0052cc05`), then `BBox::LocalToLocal` into the destination and `CCellStruct::box_intersects_cell` @0x00533910 -> `BSPTREE` @0x0053c880 - where acdream keeps `CellTransit.FindTransitCellsSphere`'s sphere-vs-portal-plane test, fed from the SAME per-part `CGfxObj::physics_sphere` values retail uses for its cheap `eps = F_EPSILON + radius` pre-reject at `0x0052cb65`. The outdoor building bridge (`CEnvCell::check_building_transit` @0x0052c5d0) is on the same sphere input for the same reason. Deferred deliberately: closing it needs a new BOX traversal of the containment BSP in BOTH the graph (`BSPQuery`) and the production flat (`FlatBspQuery`) representations plus their exact referee, which is a separately gateable change with no bearing on #334's outdoor defect. Filed as issue #335. | `src/AcDream.Core/Physics/CellTransit.cs` (`BuildShadowCellSetFromParts`, indoor arm); `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` (`BuildBspPartSpheres`) | The sphere set is exact (AP-156) and the sphere is a strictly LOOSER admitter than the box for a convex part, so the indoor set is a superset of retail's. Retail is itself conservative here in four compounding ways (render-mesh AABB over physics hull, axis-aligned re-fit after rotation, filled rectangle over per-cell test, one rectangle unioned across parts), so an over-inclusive indoor set is the same direction retail errs in. | A cell whose portal plane a part's sphere straddles but whose box does not joins the object's shadow set: extra broadphase candidates, never a missed one. This is AP-156's original risk statement, which is true of the indoor half and was false of the outdoor half. | `CEnvCell::find_transit_cells` 0x0052cae0 (0x0052cbdd / 0x0052cbf9 / 0x0052cc05 / 0x0052cc5a); `Plane::intersect_box` 0x005aa170; `CCellStruct::box_intersects_cell` 0x00533910; `CEnvCell::check_building_transit` 0x0052c5d0 | | ~~AP-152~~ | **RETIRED 2026-08-06 (the commit that filed it is one day old; this retirement corrects four statements in it).** `ShadowShapeBuilder.FromSetup` now DISPATCHES instead of unioning: a step-0 gate derived from the parts suppresses steps 1 and 2 whenever any part's EFFECTIVE GfxObj carries a physics BSP. Retail's priority, re-disassembled from the PDB-paired binary for this commit rather than inherited: `CPhysicsObj::FindObjCollisions` @0x0050f050 tests `HAS_PHYSICS_BSP_PS` FIRST (`0x0050f165 test dword [esi+0xa8],0x10000` / `0x0050f16f je 0x50f1a2`) and leaves the BSP branch through the UNCONDITIONAL `0x0050f19d jmp 0x50f2b0`, which is past the CylSphere loop at 0x50f1a2 AND the Sphere loop at 0x50f21d; a CylSphere-bearing object that survives its loop RETURNS (`0x0050f1d6 jae 0x50f317`); a Setup with zero spheres returns the seeded OK_TS (`0x0050f22f je 0x50f31b`). **BSP wins.** **CORRECTION 1 — the row's risk statement was FALSE as written.** It predicted "catching or stopping on a doorway sill". acdream did not test the extra primitive either: `Transition.BspOnlyDispatch` (`TransitionTypes.cs:1348`, landed 2026-05-25 as A6.P7) already skipped BOTH primitive branches (`:3911`, `:3954`) whenever the target's wire `PhysicsState` carries 0x10000, and ACE sets that bit from `CSetup.HasPhysicsBSP` (`WorldObject_Networking.cs:665-668`). The row's own anchor column cites the flag it failed to notice acdream was already keying on. So this retirement is NOT a collision-response change; the live half was CELL MEMBERSHIP, which had no such guard (see AP-155). **CORRECTION 2 — "the affected primitives are small and centred at the part origin" was FALSE in both halves.** The largest is `0x02001741`'s CylSphere at **r = 6.714 m**; `0x0200086E`'s Sphere is r = 5.842 m with origin (0.759, 0.165, 5.842), nowhere near the part origin. **CORRECTION 3 — the cottage door's "~14 cm base Sphere" was the wrong field.** `0x020019FF`'s Sphere radius is **0.100 m** at origin (0, 0, 0.018); `0.141` is `Setup.Radius`, which AP-22 had just finished proving is never collision geometry. **CORRECTION 4 — the row named ONE pinning test where TWO existed.** `FromSetup_DoorSetup_SphereAtExpectedLocalOffset` also failed under the exclusive rule; both are corrected, neither deleted. Population re-measured independently at 172 of 5,935 (73 CylSphere+BSP, 99 Sphere+BSP; 530 carry a physics-BSP part), agreeing exactly with the filing commit's separate sweep, and now pinned by an installed-DAT test with external bucket controls. | RETIRED — `src/AcDream.Core/Physics/ShadowShapeBuilder.cs` (`FromSetup` step 0 gate + `EffectivePartGfxObjId`, shared with step 3 so the two can never read different identities); `tests/AcDream.Core.Tests/Physics/ShadowShapeBuilderTests.cs` (`FromSetup_DoorSetup_EmitsBspPartsOnly`, `FromSetup_DoorSetup_SphereAtExpectedLocalOffset` re-hosted on `_ => false`, `FromSetup_DispatchGateReadsTheEffectivePartIdentities`); `tests/AcDream.App.Tests/Physics/LiveEntityCollisionBuilderTests.cs` (`CylSphereAndPhysicsBspPart_EmitsOnlyTheScaledBspShape` — no App fixture combined a primitive with a BSP part before); `tests/AcDream.Content.Tests/InstalledSetupBspPrimitiveDispatchTests.cs` (population). `Transition.BspOnlyDispatch` is deliberately KEPT: retail genuinely dispatches at the query site too, and it guards against a future additive producer. | — | — | `CPhysicsObj::FindObjCollisions` 0x0050f050 (0x0050f165 / 0x0050f16f / 0x0050f19d / 0x0050f1d6 / 0x0050f22f); `CPhysicsObj::calc_cross_cells` 0x00515230 (0x00515285 / 0x0051528f) -> `CPhysicsObj::find_bbox_cell_list` 0x00510fc0; `CPhysicsPart::find_obj_collisions` 0x0050d8d0; `CPartArray::CacheHasPhysicsBSP` 0x00518110; evidence `docs/research/2026-08-06-ap152-contract.md` | diff --git a/docs/reviews/2026-08-18-r3-test-truth-ledger.md b/docs/reviews/2026-08-18-r3-test-truth-ledger.md index d93a7550..77712980 100644 --- a/docs/reviews/2026-08-18-r3-test-truth-ledger.md +++ b/docs/reviews/2026-08-18-r3-test-truth-ledger.md @@ -136,7 +136,7 @@ identifiable in the lane report. | 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-016 historical test taxonomy | first descriptive-identity batch active in batch J | Remove opaque AP/R/J/K/Slice codes from current test/type names while preserving provenance in comments and ledgers. The 47 `Issue###` files remain an explicit user-decision set because their IDs still connect tests to retail evidence. | | 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. | | T-019 remaining explicit waits | classified in batch H; nine fixed-delay negative oracles need cleanup | Five of the 38 methods are deterministic cancellation stubs, not wall-clock tests. Preserve four intentional real-time contracts and bounded integration polling; replace the nine tests that infer “still blocked” from a fixed delay with observable synchronization state. | @@ -465,7 +465,7 @@ of three dispositions: | Disposition | Methods | Owning test files | |---|---:|---| -| Campaign-era implementation-shape freeze; replace in stages | 46 | `ContentEffectsAudioCompositionTests`, `FrameRootCompositionTests`, `HostInputCameraCompositionTests`, `InteractionRetainedUiCompositionTests`, `LivePresentationCompositionTests`, `SessionPlayerCompositionTests`, `WorldRenderCompositionTests`, `GameWindowLiveSessionOwnershipTests`, `GameWindowRenderLeafCompositionTests`, `GameWindowSlice8BoundaryTests`, `ResourceCleanupGroupTests`, `RetailPViewPassExecutorTests`, `WorldRenderFrameBuilderTests`, `WorldSceneRendererTests`, `LandblockBuildOriginTests`, `LandblockPhysicsPublisherTests`, `LandblockRenderPublisherTests`, `GameWindowLiveEntityCompositionTests`, `UpdateFrameOrchestratorTests` | +| Campaign-era implementation-shape freeze; replace in stages | 46 | `ContentEffectsAudioCompositionTests`, `FrameRootCompositionTests`, `HostInputCameraCompositionTests`, `InteractionRetainedUiCompositionTests`, `LivePresentationCompositionTests`, `SessionPlayerCompositionTests`, `WorldRenderCompositionTests`, `GameWindowLiveSessionOwnershipTests`, `GameWindowRenderLeafCompositionTests`, `GameWindowHostBoundaryTests`, `ResourceCleanupGroupTests`, `RetailPViewPassExecutorTests`, `WorldRenderFrameBuilderTests`, `WorldSceneRendererTests`, `LandblockBuildOriginTests`, `LandblockPhysicsPublisherTests`, `LandblockRenderPublisherTests`, `GameWindowLiveEntityCompositionTests`, `UpdateFrameOrchestratorTests` | | Whole-tree architecture policy; retain, then make syntax/metadata-aware | 12 | `LinuxPlatformBoundaryTests`, `RenderSceneArchitectureTests`, `RuntimePhysicsOwnershipTests`, `RuntimeEntityOwnershipTests` | | Source/project/artifact text is the actual cross-artifact contract; retain | 5 | `ParticleBindlessInstanceTests`, `PerformanceToolsTests`, `LauncherProjectBoundaryTests` | @@ -496,3 +496,45 @@ text is appropriate there. No source-freeze fact is removed in this classification batch. The 46 staged facts are an ambiguous architecture decision and will be presented for user approval in behavior-owner groups rather than deleted from a numeric heuristic. + +## Batch J descriptive test identities + +The first T-016 naming batch changes no oracle or production behavior. It +renames eight opaque type/file identities and fifteen test methods whose AP, +R, J, K, C3c, or Slice labels described the implementation campaign rather +than the contract a maintainer needs to find: + +| Former identity family | Durable identity | +|---|---| +| `GameWindowSlice8BoundaryTests` | `GameWindowHostBoundaryTests` | +| `Ap10WaterSemanticsTests`, `Ap71EntryRestrictionGateTests`, `Ap155StaticSpherePopulationMeasurementTests`, `Ap157SortingSphereFloodMeasurementTests` | `WaterSemanticsTests`, `EntryRestrictionGateTests`, `StaticSpherePopulationMeasurementTests`, `SortingSphereFloodMeasurementTests` | +| `ConnectedR6SoakContractTests` | `ConnectedWorldSoakRouteContractTests` | +| `C3cR1F3DriftModelSourcePinTests` | `CreateAuthorityDriftModelSourcePinTests` | +| `R5Host` / `R5ManagerHarness.cs` | `PhysicsObjHostStub` / `PhysicsManagerHarness.cs` | +| J4/J5 Runtime methods | gameplay-view, gameplay-command, checkpoint, simulation, and ownership-ledger names | +| K4/Slice-L/K1c/J9 methods | multi-session profile, unsupported-platform explanation, legacy keymap difference, and stop-speed behavior names | +| AP-135/AP-195 method names | placement-bookkeeping and authored-LED-sprite names | + +Provenance is not discarded. AP-157 remains the row key in the retail +divergence register, the connected route keeps its established artifact name, +and historical audit/plan documents retain the old identifiers. Current +cross-references and test comments point to the new descriptive names. The +source-freeze class summary now states its R3 replacement status instead of +claiming to be a temporary Slice 8 checkpoint. + +This batch intentionally does not rename the 47 `Issue###` files. Their +descriptive suffixes are often useful, and the issue number can be the shortest +path to a retail trace or reproduction. Re-homing those contracts by component +while retaining `Issue` provenance is an architecture/taxonomy choice for user +approval, not a mechanical cleanup. + +Verification before the complete gate: + +- all 44 maintained projects build in Release with 0 warnings and 0 errors; +- 102 focused App cases, 203 Core cases, 17 Runtime cases, 5 Headless cases, + 1 Launcher.Core case, and 10 UI.Abstractions cases pass; and +- the renamed installed-DAT population measurement passes 1/1 against the + local retail DAT. + +The no-retry complete hermetic Release gate passed 14,391/14,391 with zero +skips or failures across all 12 test assemblies. diff --git a/src/AcDream.App/Rendering/FramebufferResizeController.cs b/src/AcDream.App/Rendering/FramebufferResizeController.cs index 84759f27..b9eac40d 100644 --- a/src/AcDream.App/Rendering/FramebufferResizeController.cs +++ b/src/AcDream.App/Rendering/FramebufferResizeController.cs @@ -115,7 +115,7 @@ internal sealed class FramebufferResizeController // the only trace of whether the native event fired at all). Lives here // rather than in GameWindow.OnFramebufferResize because the window // callback is contractually a one-line typed-owner handoff - // (GameWindowSlice8BoundaryTests.FramebufferResize_IsOneTypedOwnerHandoff). + // (GameWindowHostBoundaryTests.FramebufferResize_IsOneTypedOwnerHandoff). Console.WriteLine($"window: framebuffer resize event {width}x{height}"); // Frozen order: GL viewport, shared aspect publication, camera, then diff --git a/src/AcDream.Runtime/Gameplay/RuntimeCharacterState.cs b/src/AcDream.Runtime/Gameplay/RuntimeCharacterState.cs index a3a4850b..4e5a86fa 100644 --- a/src/AcDream.Runtime/Gameplay/RuntimeCharacterState.cs +++ b/src/AcDream.Runtime/Gameplay/RuntimeCharacterState.cs @@ -651,7 +651,7 @@ public sealed class RuntimeCharacterOptionsState /// 480.0 (wire research §3.3): the batched module flushes 480 /// seconds after it FIRST went dirty, not after the last change. A /// property (not a field) so this type keeps zero static mutable state - /// — see GameRuntimeContractTests.J4GameplayOwnersHaveNoStaticMutableSessionState. + /// — see GameRuntimeContractTests.GameplayOwnersHaveNoStaticMutableSessionState. /// public static TimeSpan AutoSaveDelay => TimeSpan.FromSeconds(480); diff --git a/tests/AcDream.App.Tests/Diagnostics/ConnectedR6SoakContractTests.cs b/tests/AcDream.App.Tests/Diagnostics/ConnectedWorldSoakRouteContractTests.cs similarity index 99% rename from tests/AcDream.App.Tests/Diagnostics/ConnectedR6SoakContractTests.cs rename to tests/AcDream.App.Tests/Diagnostics/ConnectedWorldSoakRouteContractTests.cs index e778775a..72050d2c 100644 --- a/tests/AcDream.App.Tests/Diagnostics/ConnectedR6SoakContractTests.cs +++ b/tests/AcDream.App.Tests/Diagnostics/ConnectedWorldSoakRouteContractTests.cs @@ -1,6 +1,6 @@ namespace AcDream.App.Tests.Diagnostics; -public sealed class ConnectedR6SoakContractTests +public sealed class ConnectedWorldSoakRouteContractTests { private static readonly string[] ExpectedCheckpointNames = [ diff --git a/tests/AcDream.App.Tests/Physics/LiveEntityNetworkOnPositionCollapseMatrixTests.cs b/tests/AcDream.App.Tests/Physics/LiveEntityNetworkOnPositionCollapseMatrixTests.cs index 2e6e8b2b..91b1a9ff 100644 --- a/tests/AcDream.App.Tests/Physics/LiveEntityNetworkOnPositionCollapseMatrixTests.cs +++ b/tests/AcDream.App.Tests/Physics/LiveEntityNetworkOnPositionCollapseMatrixTests.cs @@ -310,7 +310,7 @@ public sealed class LiveEntityNetworkOnPositionCollapseMatrixTests [Theory] [InlineData(PlayerGuid)] [InlineData(CreatureGuid)] - public void WireAirborneNullClassified_BothGuids_WritesOnlyAP135Bookkeeping( + public void WireAirborneNullClassified_BothGuids_WritesOnlyPlacementBookkeeping( uint guid) { using var fixture = new Fixture(guid, nullClassification: true); @@ -334,8 +334,7 @@ public sealed class LiveEntityNetworkOnPositionCollapseMatrixTests // lazily created only on a genuine arm). Assert.Null(host.PositionManager.Constraint); - // Positive half (round-2 B1's lesson): AP-135's two writes DID - // happen. + // Positive half: the placement bookkeeping writes did happen. Assert.Equal(SourceCell, fixture.Remote.CellId); Assert.Equal(wirePos, fixture.Remote.LastServerPos); Assert.NotEqual(0d, fixture.Remote.LastServerPosTime); @@ -346,7 +345,7 @@ public sealed class LiveEntityNetworkOnPositionCollapseMatrixTests [Theory] [InlineData(PlayerGuid)] [InlineData(CreatureGuid)] - public void AirborneNoOperation_BothGuids_WritesOnlyAP135BookkeepingNoArm( + public void AirborneNoOperation_BothGuids_WritesOnlyPlacementBookkeepingNoArm( uint guid) { using var fixture = new Fixture(guid); @@ -933,7 +932,7 @@ public sealed class LiveEntityNetworkOnPositionCollapseMatrixTests // IsConstrained rather than nulling the manager back out (it was // lazily CREATED by the ConstrainTo test-setup call above, and // creation is one-way) — this is the exact discriminator - // WireAirborneNullClassified_BothGuids_WritesOnlyAP135Bookkeeping's + // WireAirborneNullClassified_BothGuids_WritesOnlyPlacementBookkeeping's // own comment names ("Constraint is lazily created only on a // genuine arm"). Assert.NotNull(host.PositionManager.Constraint); diff --git a/tests/AcDream.App.Tests/Rendering/GameWindowCrashStatusTests.cs b/tests/AcDream.App.Tests/Rendering/GameWindowCrashStatusTests.cs index 779aa6d8..7436ae21 100644 --- a/tests/AcDream.App.Tests/Rendering/GameWindowCrashStatusTests.cs +++ b/tests/AcDream.App.Tests/Rendering/GameWindowCrashStatusTests.cs @@ -8,7 +8,7 @@ namespace AcDream.App.Tests.Rendering; /// of an exception that escaped Run()'s Silk.NET frame loop and was /// about to crash the process via the CLR's unhandled-exception path. /// GameWindow cannot be constructed without a live GPU/window (see -/// the established pattern in GameWindowSlice8BoundaryTests), so +/// the established pattern in GameWindowHostBoundaryTests), so /// this pins the fix as a source-shape test exactly like that file does /// for the surrounding shutdown machinery. /// diff --git a/tests/AcDream.App.Tests/Rendering/GameWindowSlice8BoundaryTests.cs b/tests/AcDream.App.Tests/Rendering/GameWindowHostBoundaryTests.cs similarity index 98% rename from tests/AcDream.App.Tests/Rendering/GameWindowSlice8BoundaryTests.cs rename to tests/AcDream.App.Tests/Rendering/GameWindowHostBoundaryTests.cs index f6ce4c9c..7a6243f1 100644 --- a/tests/AcDream.App.Tests/Rendering/GameWindowSlice8BoundaryTests.cs +++ b/tests/AcDream.App.Tests/Rendering/GameWindowHostBoundaryTests.cs @@ -1,12 +1,11 @@ namespace AcDream.App.Tests.Rendering; /// -/// Temporary source-shape freeze for the Slice 8 cutover. Each later checkpoint -/// replaces the corresponding assertion with functional tests on the extracted -/// owner; this file prevents a mechanical move from silently reordering host -/// behavior before that owner exists. +/// Source-level architecture guards for the narrow graphical-host composition +/// boundary. R3 tracks these literal source-shape checks for staged replacement +/// with semantic owner and lifecycle contracts. /// -public sealed class GameWindowSlice8BoundaryTests +public sealed class GameWindowHostBoundaryTests { [Fact] public void Run_PreservesNativeAttributeAndCallbackOrder() @@ -18,9 +17,8 @@ public sealed class GameWindowSlice8BoundaryTests "RuntimeSettingsSnapshot startup = _runtimeSettings.Startup", "_displayFramePacing.InitializeStartup(startup.Display.VSync)", "VSync = startupPacing.UseVSync", - // Campaign V slice V11: the raw-GL "Samples = ..." window option - // is gone — Vulkan takes MSAA as an RHI attachment property, not - // a window attribute. _startupQuality carries it forward instead. + // Vulkan takes MSAA as an RHI attachment property rather than a + // window attribute. _startupQuality carries it forward instead. "_startupQuality = startup.Quality;", "Window.Create(options)", "_displayFramePacing.BindSurface(", diff --git a/tests/AcDream.App.Tests/Rendering/LiveEntityCreateSupersessionRecoveryTests.cs b/tests/AcDream.App.Tests/Rendering/LiveEntityCreateSupersessionRecoveryTests.cs index 39ef45da..36b3e5e6 100644 --- a/tests/AcDream.App.Tests/Rendering/LiveEntityCreateSupersessionRecoveryTests.cs +++ b/tests/AcDream.App.Tests/Rendering/LiveEntityCreateSupersessionRecoveryTests.cs @@ -83,7 +83,7 @@ public sealed class LiveEntityCreateSupersessionRecoveryTests // covered. // C3c-R1 F3: honest MODEL of the executor drain's advance // (ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests); a + // source-pinned by CreateAuthorityDriftModelSourcePinTests); a // nested production OnCreate can no longer reach it — // post-residence registration is description-only // (RuntimeEntityObjectLifetime :660-665, diff --git a/tests/AcDream.App.Tests/Runtime/CurrentGameRuntimeAdapterTests.cs b/tests/AcDream.App.Tests/Runtime/CurrentGameRuntimeAdapterTests.cs index 45fa4043..d35b5bf3 100644 --- a/tests/AcDream.App.Tests/Runtime/CurrentGameRuntimeAdapterTests.cs +++ b/tests/AcDream.App.Tests/Runtime/CurrentGameRuntimeAdapterTests.cs @@ -463,7 +463,7 @@ public sealed class CurrentGameRuntimeAdapterTests } [Fact] - public void AdapterBorrowsExactJ4ViewsAndCheckpointState() + public void AdapterBorrowsExactGameplayViewsAndCheckpointState() { using var harness = new Harness(); harness.Character.Options.Replace(0x04000000u, 0x00948700u); @@ -502,7 +502,7 @@ public sealed class CurrentGameRuntimeAdapterTests } [Fact] - public void J4StateCommandsAreGenerationGatedAndReachCurrentTransport() + public void GameplayStateCommandsAreGenerationGatedAndReachCurrentTransport() { using var harness = new Harness(); var trace = new RuntimeTraceRecorder(); @@ -668,7 +668,7 @@ public sealed class CurrentGameRuntimeAdapterTests } [Fact] - public void GraphicalAndNoWindowJ4CommandsProduceIdenticalCanonicalState() + public void GraphicalAndNoWindowGameplayCommandsProduceIdenticalCanonicalState() { using var directEntities = new RuntimeEntityObjectLifetime(); using var directInventory = diff --git a/tests/AcDream.App.Tests/UI/Layout/ChatOptionsPageControllerTests.cs b/tests/AcDream.App.Tests/UI/Layout/ChatOptionsPageControllerTests.cs index f1341cfd..a324ea31 100644 --- a/tests/AcDream.App.Tests/UI/Layout/ChatOptionsPageControllerTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/ChatOptionsPageControllerTests.cs @@ -276,9 +276,9 @@ public sealed class ChatOptionsPageControllerTests } [Fact] - public void Bind_FilterBlocks_ResolveTheAP195LedSprites() + public void Bind_FilterBlocks_ResolveTheAuthoredLedSprites() { - // AP-195 end-to-end: the regenerated fixture now carries dat properties + // The regenerated fixture carries DAT properties // 0x10000082/0x10000083 on template consumer 0x10000520 // (0x06004D17/0x06004D19), and DatWidgetFactory threads them into the // constructed UiCheckboxBitfield64 — every one of the five blocks shares diff --git a/tests/AcDream.App.Tests/World/C3cR1F3DriftModelSourcePinTests.cs b/tests/AcDream.App.Tests/World/CreateAuthorityDriftModelSourcePinTests.cs similarity index 94% rename from tests/AcDream.App.Tests/World/C3cR1F3DriftModelSourcePinTests.cs rename to tests/AcDream.App.Tests/World/CreateAuthorityDriftModelSourcePinTests.cs index 80de6162..68659a9a 100644 --- a/tests/AcDream.App.Tests/World/C3cR1F3DriftModelSourcePinTests.cs +++ b/tests/AcDream.App.Tests/World/CreateAuthorityDriftModelSourcePinTests.cs @@ -3,8 +3,7 @@ using System.Text.RegularExpressions; namespace AcDream.App.Tests.World; /// -/// C3c-R1 F3 (coordinator resolution, 2026-08-02): the create-authority -/// drift probes in the expectation-item 6/8 tests +/// The create-authority drift probes in the expectation-item 6/8 tests /// (LiveEntityHydrationControllerTests + LiveEntityCreateSupersessionRecoveryTests) /// hand-call record.Canonical.AdvanceCreateAuthority() as an HONEST /// MODEL of the executor drain's advance — the SOLE remaining production @@ -19,7 +18,7 @@ namespace AcDream.App.Tests.World; /// STALE if the production site ever moves or loses the advance — the /// item 6/8 probes must be re-derived from wherever it goes. /// -public sealed class C3cR1F3DriftModelSourcePinTests +public sealed class CreateAuthorityDriftModelSourcePinTests { [Fact] public void HandCalledDriftProbe_StillModelsTheExecutorDrainAdvance() diff --git a/tests/AcDream.App.Tests/World/LiveEntityHydrationControllerTests.cs b/tests/AcDream.App.Tests/World/LiveEntityHydrationControllerTests.cs index 0a123d66..8fcdceaf 100644 --- a/tests/AcDream.App.Tests/World/LiveEntityHydrationControllerTests.cs +++ b/tests/AcDream.App.Tests/World/LiveEntityHydrationControllerTests.cs @@ -1371,7 +1371,7 @@ public sealed class LiveEntityHydrationControllerTests // honest MODEL of the executor drain's advance // (RuntimeInitialCreateContinuationExecutor // .ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests). A nested + // source-pinned by CreateAuthorityDriftModelSourcePinTests). A nested // production OnCreate can no longer reach it here: // post-residence ExistingGeneration registration is // description-only (RuntimeEntityObjectLifetime gates the @@ -1509,7 +1509,7 @@ public sealed class LiveEntityHydrationControllerTests // honest MODEL of the executor drain's advance // (RuntimeInitialCreateContinuationExecutor // .ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests). A nested + // source-pinned by CreateAuthorityDriftModelSourcePinTests). A nested // production OnCreate can no longer reach it here: // post-residence ExistingGeneration registration is // description-only (RuntimeEntityObjectLifetime gates the @@ -1864,7 +1864,7 @@ public sealed class LiveEntityHydrationControllerTests // revalidation guard stays covered. // C3c-R1 F3: honest MODEL of the executor drain's advance // (ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests); a + // source-pinned by CreateAuthorityDriftModelSourcePinTests); a // nested production OnCreate can no longer reach it — // post-residence registration is description-only // (RuntimeEntityObjectLifetime :660-665, @@ -1983,7 +1983,7 @@ public sealed class LiveEntityHydrationControllerTests // WeenieDescription stage; model that advance directly. // C3c-R1 F3: honest MODEL of the executor drain's advance // (ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests); a + // source-pinned by CreateAuthorityDriftModelSourcePinTests); a // nested production OnCreate can no longer reach it — // post-residence registration is description-only // (RuntimeEntityObjectLifetime :660-665, @@ -2019,7 +2019,7 @@ public sealed class LiveEntityHydrationControllerTests // (AdvanceCreateAuthority), not at registration; model it directly. // C3c-R1 F3: honest MODEL of the executor drain's advance // (ApplyWeenieDescriptionAction — the sole production site, - // source-pinned by C3cR1F3DriftModelSourcePinTests); a nested + // source-pinned by CreateAuthorityDriftModelSourcePinTests); a nested // production OnCreate can no longer reach it — post-residence // registration is description-only (RuntimeEntityObjectLifetime // :660-665, !beginInitialResidence gate) and ConsumeExecuted diff --git a/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs b/tests/AcDream.Content.Tests/StaticSpherePopulationMeasurementTests.cs similarity index 98% rename from tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs rename to tests/AcDream.Content.Tests/StaticSpherePopulationMeasurementTests.cs index 5348178b..21ec8b23 100644 --- a/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs +++ b/tests/AcDream.Content.Tests/StaticSpherePopulationMeasurementTests.cs @@ -24,7 +24,7 @@ namespace AcDream.Content.Tests; /// already counted fall into exactly that trap. /// [Trait("Lane", "InstalledDat")] -public sealed class Ap155StaticSpherePopulationMeasurementTests +public sealed class StaticSpherePopulationMeasurementTests { [Fact] public void InstalledSetups_SphereOnlyStaticPopulation_Measured() diff --git a/tests/AcDream.Core.Tests/Physics/Ap71EntryRestrictionGateTests.cs b/tests/AcDream.Core.Tests/Physics/EntryRestrictionGateTests.cs similarity index 99% rename from tests/AcDream.Core.Tests/Physics/Ap71EntryRestrictionGateTests.cs rename to tests/AcDream.Core.Tests/Physics/EntryRestrictionGateTests.cs index 27129b7e..584dc89c 100644 --- a/tests/AcDream.Core.Tests/Physics/Ap71EntryRestrictionGateTests.cs +++ b/tests/AcDream.Core.Tests/Physics/EntryRestrictionGateTests.cs @@ -41,7 +41,7 @@ namespace AcDream.Core.Tests.Physics; /// suite's "resolved" scenarios are what prevents that regression. /// /// -public sealed class Ap71EntryRestrictionGateTests +public sealed class EntryRestrictionGateTests { private const uint RestrictionObjGuid = 0x80001234u; private const uint MoverGuid = 0x50000001u; diff --git a/tests/AcDream.Core.Tests/Physics/Motion/ConstraintManagerTests.cs b/tests/AcDream.Core.Tests/Physics/Motion/ConstraintManagerTests.cs index 2e844c60..0317aaf0 100644 --- a/tests/AcDream.Core.Tests/Physics/Motion/ConstraintManagerTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Motion/ConstraintManagerTests.cs @@ -12,10 +12,10 @@ namespace AcDream.Core.Tests.Physics.Motion; /// public sealed class ConstraintManagerTests { - private static (R5Host host, ConstraintManager cm) Setup() + private static (PhysicsObjHostStub host, ConstraintManager cm) Setup() { - var world = new Dictionary(); - var host = new R5Host(10u, world); + var world = new Dictionary(); + var host = new PhysicsObjHostStub(10u, world); return (host, new ConstraintManager(host)); } diff --git a/tests/AcDream.Core.Tests/Physics/Motion/R5ManagerHarness.cs b/tests/AcDream.Core.Tests/Physics/Motion/PhysicsManagerHarness.cs similarity index 95% rename from tests/AcDream.Core.Tests/Physics/Motion/R5ManagerHarness.cs rename to tests/AcDream.Core.Tests/Physics/Motion/PhysicsManagerHarness.cs index 6dd2acbe..8af4f8f6 100644 --- a/tests/AcDream.Core.Tests/Physics/Motion/R5ManagerHarness.cs +++ b/tests/AcDream.Core.Tests/Physics/Motion/PhysicsManagerHarness.cs @@ -20,11 +20,11 @@ namespace AcDream.Core.Tests.Physics.Motion; /// receive_target_update seams forward to the owned /// exactly as retail's CPhysicsObj does. /// -internal sealed class R5Host : IPhysicsObjHost +internal sealed class PhysicsObjHostStub : IPhysicsObjHost { - public readonly Dictionary World; + public readonly Dictionary World; - public R5Host(uint id, Dictionary world) + public PhysicsObjHostStub(uint id, Dictionary world) { Id = id; World = world; diff --git a/tests/AcDream.Core.Tests/Physics/Motion/PositionManagerFacadeTests.cs b/tests/AcDream.Core.Tests/Physics/Motion/PositionManagerFacadeTests.cs index 6e2bdc62..55a1b30e 100644 --- a/tests/AcDream.Core.Tests/Physics/Motion/PositionManagerFacadeTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Motion/PositionManagerFacadeTests.cs @@ -14,11 +14,11 @@ namespace AcDream.Core.Tests.Physics.Motion; /// public sealed class PositionManagerFacadeTests { - private static (R5Host self, R5Host target, PositionManager pm) Setup() + private static (PhysicsObjHostStub self, PhysicsObjHostStub target, PositionManager pm) Setup() { - var world = new Dictionary(); - var self = new R5Host(10u, world); - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world); + var target = new PhysicsObjHostStub(20u, world); return (self, target, new PositionManager(self)); } diff --git a/tests/AcDream.Core.Tests/Physics/Motion/StickyManagerTests.cs b/tests/AcDream.Core.Tests/Physics/Motion/StickyManagerTests.cs index 4c8bd59f..2f9769af 100644 --- a/tests/AcDream.Core.Tests/Physics/Motion/StickyManagerTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Motion/StickyManagerTests.cs @@ -13,18 +13,18 @@ namespace AcDream.Core.Tests.Physics.Motion; /// public sealed class StickyManagerTests { - private static (R5Host self, R5Host target, StickyManager sticky) Setup( + private static (PhysicsObjHostStub self, PhysicsObjHostStub target, StickyManager sticky) Setup( uint targetId = 20u, float targetRadius = 0.5f) { - var world = new Dictionary(); - var self = new R5Host(10u, world); - var target = new R5Host(targetId, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world); + var target = new PhysicsObjHostStub(targetId, world); var sticky = new StickyManager(self); return (self, target, sticky); } private static StickyManager StuckAndInitialized( - R5Host self, R5Host target, Vector3 targetOrigin, float targetRadius = 0.5f) + PhysicsObjHostStub self, PhysicsObjHostStub target, Vector3 targetOrigin, float targetRadius = 0.5f) { var sticky = new StickyManager(self); sticky.StickTo(target.Id, targetRadius, targetHeight: 1.0f); @@ -130,10 +130,10 @@ public sealed class StickyManagerTests [Fact] public void ReStick_TearsDownPreviousBeforeSettingNew() { - var world = new Dictionary(); - var self = new R5Host(10u, world); - var a = new R5Host(20u, world); - var b = new R5Host(21u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world); + var a = new PhysicsObjHostStub(20u, world); + var b = new PhysicsObjHostStub(21u, world); var sticky = new StickyManager(self); sticky.StickTo(a.Id, 0.5f, 1.0f); @@ -159,9 +159,9 @@ public sealed class StickyManagerTests [Fact] public void AdjustOffset_SteersTowardTarget_ClampedToStep() { - var world = new Dictionary(); - var self = new R5Host(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; + var target = new PhysicsObjHostStub(20u, world); var sticky = StuckAndInitialized(self, target, new Vector3(5f, 0f, 0f)); var frame = new MotionDeltaFrame(); @@ -178,9 +178,9 @@ public sealed class StickyManagerTests [Fact] public void AdjustOffset_TooClose_BacksOff_SignedDistance() { - var world = new Dictionary(); - var self = new R5Host(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; + var target = new PhysicsObjHostStub(20u, world); // centerDist 0.9, cyl = 0.9-0.5-0.5 = -0.1, minus 0.3 → dist = -0.4. var sticky = StuckAndInitialized(self, target, new Vector3(0.9f, 0f, 0f)); @@ -194,9 +194,9 @@ public sealed class StickyManagerTests [Fact] public void AdjustOffset_DeepOverlap_BacksOff_RateLimited() { - var world = new Dictionary(); - var self = new R5Host(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; + var target = new PhysicsObjHostStub(20u, world); // centerDist 0.1 → cyl = 0.1-0.5-0.5 = -0.9, minus 0.3 → dist = -1.2 // (overlap DEEPER than one tick's step). var sticky = StuckAndInitialized(self, target, new Vector3(0.1f, 0f, 0f)); @@ -214,9 +214,9 @@ public sealed class StickyManagerTests [Fact] public void AdjustOffset_UsesCachedPosition_WhenTargetUnresolvable() { - var world = new Dictionary(); - var self = new R5Host(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world) { Radius = 0.5f, MinterpMaxSpeed = 1.0f }; + var target = new PhysicsObjHostStub(20u, world); var sticky = new StickyManager(self); target.Resolvable = false; sticky.StickTo(target.Id, 0.5f, 1.0f); @@ -233,9 +233,9 @@ public sealed class StickyManagerTests [Fact] public void AdjustOffset_NoMinterp_UsesFallbackSpeed() { - var world = new Dictionary(); - var self = new R5Host(10u, world) { Radius = 0.5f, MinterpMaxSpeed = null }; - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world) { Radius = 0.5f, MinterpMaxSpeed = null }; + var target = new PhysicsObjHostStub(20u, world); var sticky = StuckAndInitialized(self, target, new Vector3(50f, 0f, 0f)); var frame = new MotionDeltaFrame(); diff --git a/tests/AcDream.Core.Tests/Physics/Motion/TargetManagerTests.cs b/tests/AcDream.Core.Tests/Physics/Motion/TargetManagerTests.cs index 549e9b04..98b30e4f 100644 --- a/tests/AcDream.Core.Tests/Physics/Motion/TargetManagerTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Motion/TargetManagerTests.cs @@ -14,11 +14,11 @@ namespace AcDream.Core.Tests.Physics.Motion; /// public sealed class TargetManagerTests { - private static (R5Host self, R5Host target, Dictionary world) TwoHosts() + private static (PhysicsObjHostStub self, PhysicsObjHostStub target, Dictionary world) TwoHosts() { - var world = new Dictionary(); - var self = new R5Host(10u, world); - var target = new R5Host(20u, world); + var world = new Dictionary(); + var self = new PhysicsObjHostStub(10u, world); + var target = new PhysicsObjHostStub(20u, world); return (self, target, world); } @@ -122,7 +122,7 @@ public sealed class TargetManagerTests var (self, originalTarget, world) = TwoHosts(); self.TargetManager.SetTarget(0, originalTarget.Id, 1.0f, 0.0); self.HandleUpdateTargetCalls.Clear(); - var replacement = new R5Host(originalTarget.Id, world); + var replacement = new PhysicsObjHostStub(originalTarget.Id, world); var p = new Position(1u, new Vector3(99f, 0f, 0f), Quaternion.Identity); self.ReceiveTargetUpdate( @@ -143,7 +143,7 @@ public sealed class TargetManagerTests self.SetOrigin(Vector3.Zero); originalTarget.SetOrigin(new Vector3(5f, 0f, 0f)); self.PositionManager.StickTo(originalTarget.Id, 0.5f, 1f); - var replacement = new R5Host(originalTarget.Id, world); + var replacement = new PhysicsObjHostStub(originalTarget.Id, world); replacement.SetOrigin(new Vector3(10f, 0f, 0f)); originalTarget.SetOrigin(new Vector3(-5f, 0f, 0f)); var delta = new MotionDeltaFrame(); @@ -260,7 +260,7 @@ public sealed class TargetManagerTests watcher.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0); watcher.HandleUpdateTargetCalls.Clear(); watcher.Resolvable = false; - var replacement = new R5Host(watcher.Id, world); + var replacement = new PhysicsObjHostStub(watcher.Id, world); target.TargetManager.NotifyVoyeurOfEvent(TargetStatus.Teleported); @@ -273,10 +273,10 @@ public sealed class TargetManagerTests [Fact] public void NotifyVoyeurOfEvent_BroadcastsToAll_NoDistanceGate() { - var world = new Dictionary(); - var target = new R5Host(20u, world); - var w1 = new R5Host(10u, world); - var w2 = new R5Host(11u, world); + var world = new Dictionary(); + var target = new PhysicsObjHostStub(20u, world); + var w1 = new PhysicsObjHostStub(10u, world); + var w2 = new PhysicsObjHostStub(11u, world); // both watch the target (each gets a target_info via SetTarget) w1.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0); w2.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0); diff --git a/tests/AcDream.Core.Tests/Physics/MotionInterpreterDoMotionFamilyTests.cs b/tests/AcDream.Core.Tests/Physics/MotionInterpreterDoMotionFamilyTests.cs index cd9950d5..34d814d3 100644 --- a/tests/AcDream.Core.Tests/Physics/MotionInterpreterDoMotionFamilyTests.cs +++ b/tests/AcDream.Core.Tests/Physics/MotionInterpreterDoMotionFamilyTests.cs @@ -463,7 +463,7 @@ public sealed class MotionInterpreterDoMotionFamilyTests } [Fact] - public void StopCompletely_DoesNotTouchSidestepOrTurnSpeeds_J9() + public void StopCompletely_DoesNotTouchSidestepOrTurnSpeeds() { // A9/J9: retail touches ONLY forward cmd/speed + sidestep/turn // COMMANDS — it does NOT write sidestep_speed or turn_speed. The diff --git a/tests/AcDream.Core.Tests/Physics/MotionInterpreterJumpFamilyTests.cs b/tests/AcDream.Core.Tests/Physics/MotionInterpreterJumpFamilyTests.cs index 7271439a..008b99de 100644 --- a/tests/AcDream.Core.Tests/Physics/MotionInterpreterJumpFamilyTests.cs +++ b/tests/AcDream.Core.Tests/Physics/MotionInterpreterJumpFamilyTests.cs @@ -705,8 +705,8 @@ public sealed class MotionInterpreterJumpFamilyTests [Fact] public void JumpIsAllowed_LeashArmedAndOverstrained_ReturnsGeneralMovementFailure() { - var world = new System.Collections.Generic.Dictionary(); - var host = new R5Host(10u, world); + var world = new System.Collections.Generic.Dictionary(); + var host = new PhysicsObjHostStub(10u, world); const uint outdoorCell = 0x12340007u; // low16 < 0x0100 -> outdoor host.Position = new Position(outdoorCell, Vector3.Zero, Quaternion.Identity); diff --git a/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs b/tests/AcDream.Core.Tests/Physics/SortingSphereFloodMeasurementTests.cs similarity index 99% rename from tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs rename to tests/AcDream.Core.Tests/Physics/SortingSphereFloodMeasurementTests.cs index 7f7d2f59..3fe64cfd 100644 --- a/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs +++ b/tests/AcDream.Core.Tests/Physics/SortingSphereFloodMeasurementTests.cs @@ -60,7 +60,7 @@ namespace AcDream.Core.Tests.Physics; /// /// [Trait("Lane", "InstalledDat")] -public sealed class Ap157SortingSphereFloodMeasurementTests +public sealed class SortingSphereFloodMeasurementTests { /// Arbitrary non-zero landblock id — only its prefix matters for /// seeding the outdoor flood; the entity is placed at the landblock's own diff --git a/tests/AcDream.Core.Tests/Physics/Ap10WaterSemanticsTests.cs b/tests/AcDream.Core.Tests/Physics/WaterSemanticsTests.cs similarity index 99% rename from tests/AcDream.Core.Tests/Physics/Ap10WaterSemanticsTests.cs rename to tests/AcDream.Core.Tests/Physics/WaterSemanticsTests.cs index 6ed9ea69..e1325c4a 100644 --- a/tests/AcDream.Core.Tests/Physics/Ap10WaterSemanticsTests.cs +++ b/tests/AcDream.Core.Tests/Physics/WaterSemanticsTests.cs @@ -30,7 +30,7 @@ namespace AcDream.Core.Tests.Physics; /// /// /// -public class Ap10WaterSemanticsTests +public class WaterSemanticsTests { // ── §1: TerrainSurface.SampleWaterDepth golden values ────────────────── diff --git a/tests/AcDream.Headless.Tests/HeadlessProcessResourceEnvelopeTests.cs b/tests/AcDream.Headless.Tests/HeadlessProcessResourceEnvelopeTests.cs index 4d04b384..35e635f1 100644 --- a/tests/AcDream.Headless.Tests/HeadlessProcessResourceEnvelopeTests.cs +++ b/tests/AcDream.Headless.Tests/HeadlessProcessResourceEnvelopeTests.cs @@ -6,7 +6,7 @@ namespace AcDream.Headless.Tests; public sealed class HeadlessProcessResourceEnvelopeTests { [Fact] - public void K4ProfileScalesOnlyPerSessionDimensions() + public void MultiSessionProfileScalesOnlyPerSessionDimensions() { HeadlessProcessResourceCeilings ceilings = HeadlessProcessResourceCeilings.K4Linux; diff --git a/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherOrchestratorTests.cs b/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherOrchestratorTests.cs index 83ad5402..3c54a23f 100644 --- a/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherOrchestratorTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherOrchestratorTests.cs @@ -380,7 +380,7 @@ public sealed class LauncherOrchestratorTests : IDisposable } [Fact] - public async Task LinuxRejectsBothGraphicalModesBeforeCompositionOrSpawnWithSliceLExplanation() + public async Task LinuxRejectsBothGraphicalModesBeforeCompositionOrSpawnWithUnsupportedPlatformExplanation() { var config = new RecordingConfigService(); var supervisors = new FakeSupervisorFactory(); diff --git a/tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs b/tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs index e8592713..ebce0499 100644 --- a/tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs +++ b/tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs @@ -143,7 +143,7 @@ public sealed class GameRuntimeContractTests } [Fact] - public void TraceRecorderIncludesJ4GameplayStateInCheckpoint() + public void TraceRecorderIncludesGameplayStateInCheckpoint() { var recorder = new RuntimeTraceRecorder(); var stamp = new RuntimeEventStamp(new(3), 1, 8); @@ -222,7 +222,7 @@ public sealed class GameRuntimeContractTests } [Fact] - public void J4GameplayOwnersHaveNoStaticMutableSessionState() + public void GameplayOwnersHaveNoStaticMutableSessionState() { Type[] owners = [ diff --git a/tests/AcDream.Runtime.Tests/Gameplay/RuntimeGameplayOwnershipTests.cs b/tests/AcDream.Runtime.Tests/Gameplay/RuntimeGameplayOwnershipTests.cs index c8e62246..de62c8e8 100644 --- a/tests/AcDream.Runtime.Tests/Gameplay/RuntimeGameplayOwnershipTests.cs +++ b/tests/AcDream.Runtime.Tests/Gameplay/RuntimeGameplayOwnershipTests.cs @@ -10,7 +10,7 @@ namespace AcDream.Runtime.Tests.Gameplay; public sealed class RuntimeGameplayOwnershipTests { [Fact] - public void J5LedgerConvergesEntityPhysicsAndGameplayAsOneLifetime() + public void GameplayOwnershipLedgerConvergesEntityPhysicsAndGameplayAsOneLifetime() { var entities = new RuntimeEntityObjectLifetime(); var inventory = new RuntimeInventoryState(entities); diff --git a/tests/AcDream.Runtime.Tests/RuntimeSimulationFixtureHostTests.cs b/tests/AcDream.Runtime.Tests/RuntimeSimulationFixtureHostTests.cs index e64c145f..deb747fe 100644 --- a/tests/AcDream.Runtime.Tests/RuntimeSimulationFixtureHostTests.cs +++ b/tests/AcDream.Runtime.Tests/RuntimeSimulationFixtureHostTests.cs @@ -14,7 +14,7 @@ namespace AcDream.Runtime.Tests; public sealed class RuntimeSimulationFixtureHostTests { [Fact] - public void RuntimeOnlyHostDrivesCompleteJ5SimulationWithoutPresentation() + public void RuntimeOnlyHostDrivesCompleteGameplaySimulationWithoutPresentation() { var host = new RuntimeOnlySimulationFixtureHost(); diff --git a/tests/AcDream.UI.Abstractions.Tests/Input/KeyBindingsTests.cs b/tests/AcDream.UI.Abstractions.Tests/Input/KeyBindingsTests.cs index 9cf82274..ddf66633 100644 --- a/tests/AcDream.UI.Abstractions.Tests/Input/KeyBindingsTests.cs +++ b/tests/AcDream.UI.Abstractions.Tests/Input/KeyBindingsTests.cs @@ -101,7 +101,7 @@ public class KeyBindingsTests [Fact] public void AcdreamCurrentDefaults_binds_shift_as_hold_for_run() { - // K.1b: when ShiftLeft is held the OS keyboard delivers + // When ShiftLeft is held the OS keyboard delivers // CurrentModifiers=Shift, so the chord must be (ShiftLeft, Shift). // Lookup with the matching modifier mask succeeds. var b = KeyBindings.AcdreamCurrentDefaults(); @@ -111,11 +111,11 @@ public class KeyBindingsTests } [Fact] - public void RetailDefaults_diverges_from_AcdreamCurrentDefaults_in_K1c() + public void RetailDefaults_differs_from_legacy_AcdreamCurrentDefaults() { - // K.1c flips RetailDefaults() to the retail-faithful preset. - // The acdream-current map remains accessible (for tests pinning - // the older WASD-only behavior), but RetailDefaults is now the + // RetailDefaults is the retail-faithful preset. The acdream-current + // map remains accessible for tests pinning the older WASD-only + // behavior, but RetailDefaults is now the // canonical startup source. The two MUST differ — at minimum // RetailDefaults binds X to Backup (retail) where AcdreamCurrent // bound X to StrafeRight, and RetailDefaults binds Tab to