src/switcher/state/WindowEventReducerMinimizeSpecs.md
Covers the un-minimize branch of WindowEventReducer.movedResizedOrOrderedIn: a WindowServer order-in (815)
for a window the model believes is minimized clears isMinimized and earns the MRU front. Specs + Tests
without a same-named kernel (like WindowEventReducerFocus): the subject is a reducer decision, not a pure
function of its own.
A reporter (2026-08-04, log 09:24:56–09:25:15) unminimized a Chrome window from the Dock and then could not reach it with quick alt+tabs — each press just toggled between the two OTHER windows. A long press finally showed the panel and "the queue flashed", adding the window back. Their capture:
09:25:03.530 windowOrderedOut #30718 ← minimized
09:25:03.623 liveness #30718 result=0 verdict=alive (correctly kept, not a close)
09:25:03.580 windowFocused #16 | mru bump #16 from=2 ← Chrome focuses its other window
09:25:06.540 windowOrderedIn #30718 ← the Dock restore. NOTHING else.
09:25:07.914 mru bump #30767 Finder from=2 ← #30718 still holds rank 1
Two defects, one event.
The flag never cleared. MEASURED live on 2026-08-04 (macOS 26, AXPress on the Dock's
AXMinimizedWindowDockItem, 8/8): the Dock press emits the 815 within ~30ms, but the app keeps answering
kAXMinimized = true for ~530ms, and the WindowServer's own tags bit for ~644ms — later still. So on
this path NOTHING a query can ask is prompt: the window genuinely is still minimized until the animation
ends. The order-in's follow-up read landed inside that window and wrote the stale true straight back, and
nothing re-read it — manuallyRefreshAllWindows runs on windowDidBecomeKey, i.e. only when the panel
actually SHOWS, which a burst of quick presses never does. Restoring the same window through AX instead does
NOT reproduce it (there the flag flips in ~35ms), which is why every AX-driven test path stayed green.
This is why the un-minimize is derived from the EVENT and not from a better source: moving minimized onto
WsWindowState.minimizedTag (which did fix the minimize direction, and the phantom race with it) does not
help here, because that bit is late in this direction too. Both readers therefore apply the same rule — a
true is believed only while carried.offScreen still holds the wid.
With showMinimizedWindows == .showAtTheEnd (the reporter's setting) that stale flag drops the window into
the end bucket: their tile dump shows #30718 at display index 10 while the mru bump ... from=N lines
prove its rank is 2. Under the default .show the same staleness is invisible in the ordering, which is
why this went unreported for so long.
The restore took no front. When its app was already frontmost the restore emits ONLY the 815 — the same
shape as Cmd+— andcameBackOnScreenswallows the bump. That guard exists for Space re-shows (#5849) and cannot tell a Dock restore from one. When the app was NOT frontmost the restore activates it andappActivated→axFocusedWindowRead` fronts the window a beat later, which is why the bug only bites on a
same-app restore.
And the panel may be OPEN while all this happens (reported 2026-08-06). Minimizing from the switcher's
"m" shortcut does not close it, so the un-minimize that follows lands on a tile the user is looking at, and
clearing isMinimized in the model is only half the job. Nothing else on this event repaints: the WS query
it queues is a no-op (the window comes back to the frame it left, and its late isMinimized = true is
rejected the moment the wid leaves carried.offScreen), the title read reports no change, and the MRU bump
— the branch's only other .refreshUi — is gated on the restored window's app being frontmost, which it
never is while our own panel holds the key window. So the tile kept the minimized indicator until the panel
was closed and reopened. The un-minimize therefore asks for the repaint itself.
And it asks for no capture — it asks for the captures to WAIT. The other half of that same "m" press:
the restored window's tile became a mini window floating in transparent pixels. The OS draws a window scaled
down for the whole restore animation (~0.65s, the genie), and the un-minimize is precisely what sets off a
re-capture — the WindowServer geometry query the order-in queues comes back changed and asks for a fresh
screenshot ~200ms in, deep inside the animation. So a correct thumbnail is replaced by a partial frame, and
nothing later corrects it while the panel stays open. The reducer hands the wid to the shell
(WindowThumbnails.deferCaptureUntilRestoreEnds), which holds every capture of that window — the ones this
event sets off and anything else asking meanwhile — and takes a single one once the animation is over.
The rule: an order-in of a window we believe is minimized IS the un-minimize. A minimized window is
off-screen by definition, and the OS never orders one in for any other reason — a Space re-show brings back
the Space's on-screen windows and leaves its minimized ones minimized. So the event settles it with no
timing at all, and that same true → false transition is the one thing that distinguishes a restore from a
Space re-show. The follow-up query still runs; it just no longer gets to contradict the event.
Mirrors WindowEventReducerMinimizeTests.swift 1:1.
isMinimized=true at rank 2.isActive guard the un-minimize rides through is kept for exactly this.if.reconcile the background tabs stay flagged minimized behind a window plainly on screen.That the live Dock path emits the 815 at all, and that every queryable source lags it. Both are OS facts; they were established by measurement (above) and are re-checked by QA I-15 / I-16, not here.