docs(ui): pin retained widget retail oracles

This commit is contained in:
Erik 2026-07-10 17:55:16 +02:00
parent 5931a820ea
commit 44f9ec13d9
10 changed files with 2753 additions and 73 deletions

View file

@ -1576,22 +1576,22 @@ R5/R6 touches the action list. **Where:**
---
## #196Inventory window close never notifies the controller (NoLongerViewingContents skipped)
## #196External-container lifecycle and retained window events are missing
**Status:** OPEN
**Severity:** MEDIUM
**Filed:** 2026-07-02
**Component:** ui / net
**Description:** `UiRoot`'s window registry flips `Visible` with no event, and the inventory close button routes to `GameWindow.CloseRetailWindow` (HideWindow + toolbar sync only). `InventoryController` never learns the window closed: `NoLongerViewingContents (0x0195)` is not sent for the viewed side pack, `_openContainer` stays stale, and reopening shows the old bag grid without re-sending Use.
**Description:** `UiRoot`'s window registry flips `Visible` with no lifecycle event, toolbar-button sync is manually pushed at each mutation site, and acdream has no retained external/ground-container window. The original issue incorrectly assigned `NoLongerViewingContents (0x0195)` to closing or navigating the owned inventory's side bags. Named-retail evidence instead ties it to `ClientUISystem.groundObject`: replacing or closing an external container sends `0x0195` exactly once. The owned `gmInventoryUI` side-bag path has no corresponding static send.
**Root cause / status:** Review finding (theme T2). Fix direction: add `WindowShown`/`WindowHidden` events to the UiRoot window registry; InventoryController closes out the viewed container on hide; toolbar-button sync subscribes instead of the manual `SyncToolbarWindowButtons()` push at every mutation site.
**Root cause / status:** Review finding (theme T2), re-framed by the 2026-07-10 named-retail trace. Add typed retained-window lifecycle events and subscriber-driven toolbar state. Port a separate external-container owner whose ground-object replacement/close path emits one `0x0195`. Do not add that packet to owned side-bag navigation without a live packet trace.
**Files:** `src/AcDream.App/UI/UiRoot.cs:541-572`, `src/AcDream.App/UI/Layout/InventoryController.cs:404`, `src/AcDream.App/Rendering/GameWindow.cs` (`CloseRetailWindow`/`SyncToolbarWindowButtons`).
**Files:** `src/AcDream.App/UI/UiRoot.cs`, `src/AcDream.App/UI/Layout/InventoryController.cs`, `src/AcDream.App/Rendering/GameWindow.cs` (`CloseRetailWindow`/`SyncToolbarWindowButtons`); future external-container controller.
**Research:** `docs/research/2026-07-02-ui-architecture-review.md`.
**Research:** `docs/research/2026-07-02-ui-architecture-review.md`; correction oracle `docs/research/2026-07-10-retail-panel-behavior-pseudocode.md`.
**Acceptance:** closing the inventory window sends NoLongerViewingContents for the open side pack; reopening shows the main pack; no manual Sync call sites remain.
**Acceptance:** replacing/closing an external container sends `NoLongerViewingContents` exactly once; owned main/side-pack navigation and closing send nothing absent contrary trace evidence; lifecycle subscribers replace manual toolbar sync calls; repeat hiding is idempotent.
---
@ -1638,22 +1638,22 @@ states `0x28` and `0x29`.
---
## #199Character raise flow: determine and port authoritative/predicted reconciliation
## #199Port the server-authoritative character raise flow
**Status:** OPEN
**Severity:** MEDIUM
**Filed:** 2026-07-02
**Component:** ui / core
**Description:** Item moves reconcile optimistic state through `RecordPending`/`ConfirmMove`/`RollbackMove` (0x0022/0x0023/0x00A0); character raises currently apply optimistically (`CharacterSheetProvider.HandleRaiseRequest``ApplyLocalRaise`) with no pending snapshot and no rollback. First trace whether retail predicts or waits for authoritative state. Then either remove prediction or port a faithful pending/confirm/rollback path. Register row AP-73.
**Description:** Character raises currently mutate XP/credits/ranks optimistically (`CharacterSheetProvider.HandleRaiseRequest``ApplyLocalRaise`). Named retail does not predict: it permits one request in flight, ghosts the clicked button, and leaves displayed state unchanged until an authoritative quality-change element message supplies the new values.
**Root cause / status:** Review finding (theme T2); the spends now at least go through eventful store APIs (extraction commit). The old issue assumed retail predicts without evidence; Wave 8 requires the named/cdb behavior pin before choosing the reconciliation mechanism.
**Root cause / status:** Review finding (theme T2), resolved oracle question on 2026-07-10. Remove local mutation, add a one-in-flight owner, ghost the requested button, and clear awaiting state from the authoritative quality-change path. The exact rejection cleanup still needs a live ACE trace; do not mask it with a timer/retry.
**Files:** `src/AcDream.App/UI/Layout/CharacterSheetProvider.cs` (`HandleRaiseRequest`), `src/AcDream.Core/Player/LocalPlayerState.cs` (`Apply*Raise`).
**Research:** `docs/research/2026-07-02-ui-architecture-review.md`.
**Research:** `docs/research/2026-07-02-ui-architecture-review.md`; authoritative flow `docs/research/2026-07-10-retail-panel-behavior-pseudocode.md`.
**Acceptance:** a raise the server rejects (e.g. insufficient XP race) visibly reverts within one echo round-trip; a confirmed raise never flickers.
**Acceptance:** sending a raise does not change local XP/credits/ranks; a second request is blocked while one is awaiting; the matching authoritative update refreshes state and re-enables the button; rejection/relog cleanup follows captured server behavior without retry loops.
---