Owner request (docs/plans/2026-09-06-plugin-shelf-and-dat-icons.md, Slice A):
the plugin shelf was pinned to the right screen edge every tick, had no drag
or hide affordance, and never persisted position. It is now a registered
retained window ("plugin-shelf") that gets drag, the UI lock, and
RetailWindowLayoutPersistence position/visibility/collapsed persistence for
free, the same way every other retained window does.
Design decisions where the plan left room:
- Grip + collapse toggle are drawn, not child elements. A real child for the
toggle would have to live outside any WindowMoveHandle grip subtree (nesting
it inside lets UiRoot's drag-handle promotion swallow the press before the
button ever sees a click - `handleWindow is not null` outranks
`HandlesClick` in UiRoot.OnMouseDown), and a grip element as a plain sibling
changes UiElement.Children's shape, which the pre-existing single-button
shelf tests assert directly (`Assert.Single(shelf.Children)`). Keeping the
whole shelf Draggable=true and excluding just the toggle's pixel rect from
an overridden HandlesClick (computed live from UiRoot.MouseX/MouseY, the
only call site) gets grip-drags/buttons-and-toggle-don't without adding any
child or touching the existing tests' shape assumptions.
- Availability (has plugin windows) vs the user's requested-visible intent
are split the same way PluginWindowVisibilityController already splits it
for individual plugin windows, but applied SYNCHRONOUSLY (not via
VisibleSource) so Visible updates immediately after Add()/unregister with
no dependency on a Tick ever running - required to keep the pre-Slice-A
unregistered-shelf test (ShelfAndMinimizeButtonsHideAndRestoreWithoutUnregisteringWindow)
green, since it never calls root.Tick().
- "The shelf was moved" (drag or a differing restored layout) is tracked via
the shelf's own RetailWindowHandle.Moved event, captured through
WindowManager.WindowRegistered the moment MountPlugins registers it - so
unregistered/legacy use (the two other pre-existing tests) never sets this
and behaves exactly as before.
- The one-time right-edge dock (no saved layout) fires on the first OnTick
with a real parent width, replacing the old per-tick pin; Reflow's
anchor math then preserves the top-right corner while still docked or the
top-left corner once positioned, on any width change (entry add/remove,
collapse, or a parent-height-driven column rewrap).
Caption finding: the Configure Keyboard row for InputAction.TogglePluginManager
resolves its label live from the installed DAT's action-map string table
(KeyboardConfigController.BuildActionRow, RetailActionMapRow.LabelHash) -
there is no "Plugin Manager" string literal anywhere in our code to rename to
"Plugin Shelf". The row keeps showing retail's own authored name; only the
acdream-side action semantics changed.
Tests added to PluginSidePanelTests.cs (all 7 fail to even compile against
the pre-Slice-A PluginSidePanel, verified by temporarily reverting the source
files and re-running): default right-edge dock; top-right corner preserved
across a Reflow-driven width change while docked; grip drag moves the shelf
and top-left survives the next reflow once positioned; drag refused under
UiLocked; collapse via the real toggle click round-trips through
CaptureWindowState/RestoreWindowState; Show/Hide toggle sequence and a hidden
shelf staying hidden when a new plugin window registers; a full
RetailWindowLayoutPersistence round trip of X/Y/Visible/Collapsed onto a
fresh shelf instance. All 3 pre-existing tests remain green unmodified.
Verified: dotnet build src/AcDream.App (Release) green; the full App test
suite passes 7294/97 skipped/36 pre-existing unrelated failures (identical
failure set confirmed present on HEAD before this change - installed-DAT
live-mount probes, Linux-only pacing/credential tests, and known alpha-flush
COUNT-only conformance divergences, none touching plugin UI).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Prepare the original unpinned witness with an explicit cathedral-shell non-vacuity gate. Write-only while the separate production bridge owns test execution; preserve the scratch and its failed diagnostics.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Use the existing InvalidDataException content-integrity boundary for a loaded destination's out-of-range positive reciprocal index. Preserve negative/unavailable skips; record the managed guard with AP-159 at implementation landing.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Port the proven missing box admission and immediate destination transit, preserving sphere callers and separate registered source/equality residuals. Keep the failed authored-input diagnostic and original golden untouched.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Preserve the three explicit diagnostic outcomes and all18 outgoing edges. Native box containment rejects the extra room; five later-part sphere-input alarms remain red and nondecisive for these edge results. Correct AD-117's disproven widening guarantee. No production geometry or golden change, FPS remains deferred, G4 unpassed.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Project the original Run failure with loaded build, cached GPU and cell context before unwind. Preserve crash status and rethrow; contain report failures and omit arbitrary messages, source paths and session data.
Focused 19/19, narrow production/privacy review and default Release 17044/0/0 pass. Preserve the wrong-package smoke failure and real emitted report; corrected recipe10 smoke exits gracefully with two provisional PNG passes. AMD initiating cause and G4 remain open; FPS deferred. No new retail behavior deviation.
Native-boundary injection: old code 9 pass / 6 expected Assert.Throws failures. Separate acquire and present sabotage each fail their 3 fatal cases; restored focused gate 82/82. One independent API/production review PASS. Lead locked Release 0W0E; literal-hermetic 17051/0/0, manifest32/32. No retirement, recovery, normal result policy or retail behavior changes. This is first-failure evidence preservation, not an AMD reset fix; extended reproduction and G4 remain open.
Retain building and object collision for available neighboring landcells when the terrain polygon does not cover the sphere center. Verified against named and paired retail dispatch. Add prepared-flat regressions and installed cathedral repro with sabotage proof. Full Release gate 17036/0/0 and graphical wall blocking, overlap correction and escape pass provisionally. Owner accepts functional collision; exact retail settle coordinates are not claimed. Retire UN-10; keep AP159, AMD stability and final G4 open.