src/switcher/state/RealWorldScenariosSpecs.md
A durable corpus of real data recorded from a live machine (macOS 26, 2026-07-06, #5830 investigation),
fed to the pure decision kernels (TabGroupResolver, PhantomWindowDetector, WsEventRouting). The messy
facts that break tab detection — duplicate ~ titles, identical tab geometry, Space-less background tabs,
the removed-from-Space event storm — are captured ONCE as CapturedWindow / raw-event fixtures, so heuristics
can keep changing while the ground truth stays fixed, and we never re-record from a live machine again.
CapturedWindow holds only RAW API output (AXTitle / AXSubrole / AXTabGroup titles / WindowServer bounds /
CGSCopySpacesForWindows / minimized / fullscreen). Nothing derived (isTabbed, grouping) is stored — each
test projects a capture onto the record its kernel needs (TabWindow / WindowState) and supplies the
algorithm state for the step under test. So a kernel refactor moves the projections, not the recordings.
Record with a temporary Logger.debug at the AX/CGS read sites (e.g. Applications.addDiscoveredWindow
extractTabTitles, TabGroup.updateState, WindowServerEvents.handle), reproduce on a real machine, then
transcribe the raw values into a new static let capture with a provenance comment (app, macOS version,
date, gesture). Never hand-tune the numbers to make a test pass — if behavior changed, change the expectation.
terminalMerge4Tabs — Terminal "Merge All Windows" over 4 windows. All ~, 757×583 @ (683,101);
active (29328) holds Space 3 + AXTabGroup ["~"×4], three background tabs Space-less, no AXTabGroup.terminalActive9Titles / terminal9TabsTracked — mid-creation of a 9-tab group: active reports 9 ~,
only 5 background siblings tracked yet (3 tabs not yet discovered).finderActive4Tabs — Finder 4-tab window, AXTabGroup ["QRHYWK4QHQ","lwouis","lwouis","lwouis"]; only
the active tab is a real window (Finder inactive tabs aren't separate windows).terminalSeparate4Windows — DEFAULT tabbing: 4 genuinely separate Terminal windows, same size/position,
all hold a Space, none exposes an AXTabGroup. The "must never group" ground truth.removedFromSpaceStorm — the raw SkyLight (id, wid) burst when Terminal windows left a Space at once
(807 resized / 816 orderedOut / 1326 removedFromSpace).terminalFullscreenActive / terminalFullscreenBackgroundTabs — a 3-tab group fullscreened: active on
fullscreen Space 2 at 1440×864, background tabs frozen at 757×543 (Space-less), AXTabGroup unreadable (nil).dragOut* — "Move Tab to New Window": the leaving tab shrinks 757×543 → 757×527 (tab bar gone) and goes
standalone; the 3 survivors stay 757×543. Pre-drag group [30238, 30236, 30231, 30230].finderGitActive / finderLwouisInactiveTab / finderMoviesStandalone — the maintainer's recorded
Finder case (see experimentations/TabbedWindowDetection.swift): tabs "lwouis"(inactive)/"git"(active) +
a same-app standalone "Movies". Distinct titles, so a clean unambiguous match.tabbedWindowMovedBetweenSpaces — a tabbed window changing Space: 1326 (leave old) + 1325 (join new),
each carrying (spaceId, wid). The events that fire reconcile so the group follows the move.missionControlAxCycle — MC begin/end from the Dock AX stream (AXExposeShowAllWindows / AXExposeExit).
Reference only: MC has no pure-kernel consumer and moves no window between Spaces (it orders thumbnails in/out);
the ids it fires (818, 1327, 1328) are intentionally not routed. AXExposeExit is the clean end-of-transition hook.twoGroupsSameApp)Recorded LIVE: with TABDBG logging armed, the user hand-dragged tabs between two real TextEdit groups (and
closed one window mid-way). Both AXTabGroups were captured from the log: A = ["Untitled", "Untitled 2",
"Untitled 3"], B = ["Untitled 7", "Untitled 9"], plus 3 standalone windows. testTwoCoexistingGroups_* pin
the durable invariant a between-groups move must preserve: each group's matchSiblings resolves ONLY its own
tabs, never the other group's or the standalones. (Automating the atomic single-tab drag is impractical —
TextEdit Cmd-T = Show Fonts, a torn-off tab detaches into a new window unless dropped exactly on a tab bar,
and AltTab's off-screen windows block computer-use drop targets — so it was done by hand and read from the log.)
textEditGroup6 is a separate real single-group capture (distinct titles, the clean-match contrast to ~).
tabbedWindowMovedBetweenSpaces; the live end-to-end drag is not.geometryGroups groups the 3 Space-less tabs under the active.~ titles all resolve to the tracked windows, nothing untracked.~, 5 tracked ⇒ 5 matched, 3 untracked (→ discovery). "sometimes 9".isTabbed, then exempt..updateSpaceMembership (the churn trigger).tabbedSiblingWids link is what holds the group.isTabbed.