From cb3346907dfcc25c0798b05cd9df8e9f569b05aa Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 11 Aug 2026 03:25:40 +0200 Subject: [PATCH] fix(ui): OP3 re-review residuals R1/R2/R3 (coordinator pass) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit R1: the gate script no longer promises a timestamp prefix on the Magic macro lines — acdream renders no chat timestamps yet (the Display Timestamps consumer is OP4 scope; no chat-log file exists, TS-69). A bare light-blue transcript line is the CORRECT gate outcome. R2: IsGrounded yields null (silent) for a NULL controller in player mode — the prior pattern returned false and fired the mid-air refusal retail cannot produce in that state; comments now match the code. R3: the dormant-ActivePageChanged pin now applies the real stimulus — every authored tab button on a dormant host must carry NO click handler (RetailTabBinding.SetClick never ran), which is AD-73's actual dormancy mechanism; SwitchTo deliberately has no guard. OP3 is CLOSED: dual APPROVE-WITH-FIXES -> fix round 386076af -> re-review REOPEN(narrow) -> this pass. Connected gate now READY. Full Release suite: 12,956 passed / 4 skipped / 0 failed. Co-Authored-By: Claude Fable 5 --- .../2026-08-11-campaign-op-test-script.md | 13 ++++++++----- .../InteractionRetainedUiComposition.cs | 12 +++++++++--- .../OP2ReworkBlastRadiusConformanceTests.cs | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/research/2026-08-11-campaign-op-test-script.md b/docs/research/2026-08-11-campaign-op-test-script.md index 902848a2..a5a48c9d 100644 --- a/docs/research/2026-08-11-campaign-op-test-script.md +++ b/docs/research/2026-08-11-campaign-op-test-script.md @@ -108,11 +108,14 @@ for this slice, not a bug. session sees zero lines (everything already at the macro's target). **These six lines are byte-verified `RetailLogTextType.Magic` (0x07), NOT the client-local refusal type** — expect LIGHT BLUE text in the - SCROLLING CHAT TRANSCRIPT (not the transient SpewBox overlay), with - a timestamp prefix, same as any other Magic-colored system line. If - you see bright red text in a transient 5-second overlay instead (the - ClientLocal/SpewBox look used by the mid-air refusal and UA/RA - above), that is the pre-fix-round bug — report it. + SCROLLING CHAT TRANSCRIPT (not the transient SpewBox overlay). Do + NOT expect a timestamp prefix: acdream renders no chat timestamps + yet (the Display Timestamps consumer is OP4 scope, and there is no + chat-log file — TS-69), so a bare light-blue line is CORRECT here + (OP3 re-review R1). If you see bright red text in a transient + 5-second overlay instead (the ClientLocal/SpewBox look used by the + mid-air refusal and UA/RA above), that is the pre-fix-round bug — + report it. **Known, registered gap (TS-74): acdream has no persistent "turn to face camera" mouse-turning MODE yet, so this button changes stored preferences and sends the wire bit, but you will not see the diff --git a/src/AcDream.App/Composition/InteractionRetainedUiComposition.cs b/src/AcDream.App/Composition/InteractionRetainedUiComposition.cs index 53e77251..e97f72e9 100644 --- a/src/AcDream.App/Composition/InteractionRetainedUiComposition.cs +++ b/src/AcDream.App/Composition/InteractionRetainedUiComposition.cs @@ -811,9 +811,15 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory // into "not grounded", which fired the mid-air message // outside player mode — the opposite of retail and the // opposite of what the old comment here claimed. - IsGrounded: () => !d.PlayerMode.IsPlayerMode - ? (bool?)null - : d.PlayerController.Controller is { IsAirborne: false }, + // R2 (OP3 re-review, 2026-08-11): a NULL controller in + // player mode must ALSO yield null (silent) — the prior + // `is { IsAirborne: false }` pattern returned false for + // null and fired the refusal retail cannot produce. + IsGrounded: () => + d.PlayerMode.IsPlayerMode + && d.PlayerController.Controller is { } liveController + ? !liveController.IsAirborne + : (bool?)null, IsUseMouseTurningEnabled: () => CharacterOptionTable.TryGet( CharacterOptionId.UseMouseTurning, diff --git a/tests/AcDream.App.Tests/UI/Layout/OP2ReworkBlastRadiusConformanceTests.cs b/tests/AcDream.App.Tests/UI/Layout/OP2ReworkBlastRadiusConformanceTests.cs index 35ee0b73..bcb3e98a 100644 --- a/tests/AcDream.App.Tests/UI/Layout/OP2ReworkBlastRadiusConformanceTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/OP2ReworkBlastRadiusConformanceTests.cs @@ -89,6 +89,22 @@ public class OP2ReworkBlastRadiusConformanceTests host.ActivePageChanged += (_, _) => raised++; Assert.False(host.BehaviorActive); + + // R3 (OP3 re-review, 2026-08-11): a subscribe-then-assert-zero pin + // passes even with dormancy fully broken. The REAL dormancy + // mechanism is that ActivateTabBehavior (via RetailTabBinding. + // SetClick) was never called, so the authored tab BUTTONS carry no + // click handler — clicking a dormant host's tab can invoke nothing. + // SwitchTo itself deliberately has no dormancy guard (a controller + // may drive it directly), so the button wiring IS the contract. + foreach (UiTabTableEntry tab in host.Tabs) + { + var button = layout.FindElement(tab.ButtonElementId); + Assert.NotNull(button); + Assert.False(button!.HandlesClick, + $"dormant tab button 0x{tab.ButtonElementId:X8} has a click " + + "handler — import-time activation regressed (AD-73)"); + } Assert.Equal(0, raised); }