src/switcher/state/WindowEventReducerFocusSpecs.md
Two things, and only two, move MRU slot 0 inside the reducer: a decision from AttentionModel arriving as
.attentionCommitted, and a structural repair. window-tracking/AttentionOrderSpecs.md states the same rule
for the whole app; this covers the reducer's half of it. Everything the WindowServer says about order and
focus is kept for what it is authoritative about — a window exists, is on screen, moved, changed Space — and is
refused as a statement about the user.
Specs + Tests without a same-named kernel (like WindowEventReducerPhantom): the subject is a set of reducer
decisions, not a pure function of its own. Sequence-shaped scenarios are driven through TestReducerRunner;
rule-level ones drive WindowEventReducer.reduce directly.
Measured across twelve focus scenarios, all four signal sources on one clock:
So every rule that read an 808 or an 815 as "the user went here" was reconstructing, later and less reliably, something the app had already said. All of them are gone rather than gated: there is one engine, no mode and no runtime switch.
macOS never moves focus to another app because a window closed. When the removed window held slot 0, the front goes to the frontmost app's own next window, not to the global runner-up. The reporter's REAPER window stopped moving in the switcher because closing a dialog handed slot 0 to a Finder window they had left minutes ago, and nothing afterwards corrected it: re-focusing the already-focused window of the already-frontmost app emits nothing at all.
Mirrors WindowEventReducerFocusTests.swift 1:1.
.applyFocus names it.Pinned here rather than left implicit: the WindowServer's order and focus family keeps every physical and invalidation job it had and loses the one it was never entitled to. This is also why #5936 (a wake or Mission Control re-showing every window at once) and #5974 (an app raising all of its windows) need no rule of their own any more — both were bursts of 815s and 808s, and neither event can reach the order at all.
AttentionModel is what moves it, and it requests
an immediate repaint so an open switcher does not spend the structural-event throttle before showing it.lastLeftSpaceId proves the shared Space and carries the whole group to the destination.