Latest Version: v0.1.1029
Ready for
better switching?
WOS for macOS
Universal Last-Recently-Seen switching for apps, windows, and tabs. Simple DMG installation. Full privacy guaranteed.
Download WOS.dmg
Supports macOS 15.0+ · Universal Binary (M1/M2/Intel)
What's New in v0.1.1029
Your most-used browser tab no longer vanishes from Cmd+Tab. Two long-standing bugs conspired to keep dropping one specific tab from the switcher — typically the web app you live in all day. First, a text-encoding oversight made every background scan silently lose the first tab of the first window, so WOS kept concluding it was closed and removed it from your recents. Second, for web apps that change their page title and URL as you navigate (dashboards, SaaS tools), WOS could mistake a successful switch for a failed one and delete the entry you had just switched to. Both are fixed: scans now see every tab, and WOS verifies a switch by the tab's actual identity — its position (Safari) or its internal ID (Chrome) — instead of comparing yesterday's page title.
New: silence noisy tabs without leaving your keyboard (⌘⌃M). Tap the chord and WOS shows every tab and app currently playing audio — across all your running browsers — so you can mute one, jump to it, or mute everything. Hold the chord to instantly silence it all (panic mode). Toggleable in Settings.
From v0.1.1016: The "Cmd+Tab is blocked — Secure Input is active" notice now names the real culprit and clears itself. When macOS blocks Cmd+Tab because a password field or a system prompt holds "Secure Input", WOS now identifies the exact process holding it — including system processes like the login window, which it previously couldn't see and would mis-blame on whatever app was in front. If a stale system lock is the cause, it tells you to simply lock and unlock your screen to clear it, and the on-screen notice no longer lingers after the block lifts.
From v0.1.1007: The "Search menu bar items" (⌘⇧B) badges look right now. The little label on the right of a row — "Battery", "Dark Mode", "Bluetooth" — used to be a heavy, typewriter-style block. It's now a subtle, neatly-padded pill sized to its text, with proper margins and spacing in both light and dark mode.
From v0.1.1007: A cleaner ⌘⇧B layout. The redundant "Visible" header and the divider line under the search field are gone, so the search field flows straight into your results. (Hidden menu-bar items are still grouped under their own "Hidden" heading.)
From v0.1.1006: "Search menu bar items" (⌘⇧B) now matches Quick Search — and opens on the first press. The panel got the same Spotlight-style search field (no more clipped placeholder), a chromeless window (the stray close/minimize/zoom buttons are gone —
esc closes it), and the same rotating "did you know?" tips while it scans. It also previously did nothing unless you pressed Cmd+Tab first; that cold-press bug is fixed.
From v0.1.1006: Memory Bank — a friendly save prompt if you open search by mistake. If you have text selected and press ⇧⌘M (search) when you meant ⌥⌘M (save), a banner now offers to save that selection as a new entry —
↩ to save, esc to discard. Nothing is written until you confirm, and your clipboard is never touched.
From v0.1.1005: Memory Bank — a searchable Markdown wiki for everything you copy. Select text anywhere on macOS and press ⌥⌘M to save it to a personal knowledge base; press ⇧⌘M to open a Spotlight-style search HUD where
↩ pastes the chosen snippet straight back into the app you came from. Storage is plain Markdown you can edit by hand. No new sandbox permissions were added.
From v0.1.1005: Cmd+Tab no longer loses a tab that shares a title with another. Committing to one of two same-titled tabs — two Gmail accounts both showing "Inbox", several "Untitled" docs, duplicate page titles across windows — used to silently drop the other from your recents until it was seen again. Tabs are now de-duplicated by URL, with the title used only when no URL is available.
From v0.1.1005: Duplicate iTerm / Terminal rows are gone. The same terminal session could appear twice in the switcher because two internal recording paths disagreed on how to identify it. They now agree, so one session shows as exactly one row.
From v0.1.1004: iTerm tabs are searchable again — including right after a restart. Two bugs hid them: WOS's enumeration script asked iTerm for each tab's
index, a property iTerm doesn't support, so every tab silently dropped and the search panel showed zero iTerm sessions. And even with that fixed, iTerm was only learned when you focused a session — so a fresh start showed nothing. WOS now reads tab titles from the active session and runs a cold-start re-scan (plus a lazy re-scan when you open Quick Search) so your terminal tabs are there immediately.
From v0.1.1004: A wedged iTerm no longer freezes tab search. If iTerm's automation stops responding (a stuck session), WOS used to block for ~2 minutes waiting on it. There's now a hard 3-second timeout that gives up cleanly and shows "iTerm isn't responding to automation — quit & relaunch iTerm to restore tab search."
From v0.1.1004: Clipboard HUD no longer spills off-screen. A long URL could stretch the clipboard panel far past the right edge of the display. Long entries now truncate neatly inside the fixed-width, centered panel.
From v0.1.997: Jump-to-File (Cmd+Shift+G) now also opens web URLs. Select a URL anywhere — schemed (
https://github.com/...) or a bare domain (foo.workers.dev, apple.com/mac) — hit the hotkey, and WOS hands it to your default browser. Previously the resolver would fall through to "treat raw clipboard as a path" and surface a confusing "Jump failed: not found" toast when the clipboard happened to hold non-path text. The hotkey's new precedence: UI path → file path → web URL → raw-string fallthrough. file:// URLs still flow through the file-path branch unchanged.
From v0.1.964: Quick Search "App Launcher" can now cold-launch installed apps. Pressing Enter on a non-running app (e.g. Front, Google Chrome Canary) used to fail with a generic "miscellaneous error" — the kernel sandbox was missing one rule (
(allow lsopen)) that LaunchServices needs to open another app. Rule added; network blackout, Gatekeeper, notarization, and sandbox non-inheritance to launched apps are all unchanged. See the security page for the threat-model delta.
From v0.1.964: Recent Files idle CPU dropped from 50–65% to ~0%. The Spotlight engine was re-scanning the entire 500-item result set on every
DidUpdate notification — several times per second on a busy disk. Now throttled (2s) and switched to delta processing (only items the notification flags as added/changed, typically 1–10). Plus a new "Scan Documents, Downloads, Desktop Only" toggle in Settings → Recent Files that narrows both the Spotlight scope and the FSEvents root, skipping per-second churn from ~/Library, browser caches, and IDE build artifacts. On by default for fresh installs.
From v0.1.964: Crash fixed on the Jump-to-File hotkey when two running apps normalize to the same name.
Dictionary(uniqueKeysWithValues:) traps on duplicate keys; switched to the collision-tolerant variant. Reproduced in a real crash report.
From v0.1.964: Launch failures are no longer silent. If WOS can't launch an app from Quick Search for any reason (sandbox, Gatekeeper, missing bundle), a status HUD now beeps and shows the underlying error message — instead of just doing nothing on Enter.
From v0.1.955: Easter egg
somebody → "Somebody's gonna get hurt real bad. I'm not saying who. Somebody." — a Russell Peters reference in the Cmd+Tab+S search panel.
From v0.1.954: Distribution is now signed with a real Apple Developer ID and notarized. First-launch UX is the standard one-click "Open" dialog with no Privacy & Security → Open Anyway detour.
From v0.1.953: Easter egg
vedio → "Did you mean: Video? ;)".
From v0.1.952: Easter-egg lightbox no longer haunts a fresh search panel. The lightbox is a child window of the search panel — AppKit doesn't sever the parent-child link when the parent is ordered out, so the banner used to ride back onto the screen alongside the empty results. Fix: the lightbox now unconditionally removes itself from the parent's child-window list when hidden, regardless of current visibility.
From v0.1.950: Easter eggs in the Cmd+Tab+S search panel. Type a recognized phrase and a HUD-style lightbox pops above the panel — pinned on top via a child-window relationship so it's always in front. Icons are monochrome to keep it professional.
Text reveals (from v0.1.950):
show wos version, open the pod bay doors, 42, hello there, how do i exit vim, i am groot, the cake is a lie, i'm a teapot, rm -rf /, sudo make me a sandwich, chmod 777, git blame.
Self-referential (from v0.1.950):
who am i returns your full name plus the live count of open tabs. wos secrets reports how many easter eggs you've discovered (persisted across launches). show wos credits.
One-shot animations (from v0.1.950):
do a barrel roll spins the panel 360°. matrix washes it green for 2.5 s. thanos fades half the results. konami pulses a rainbow border. Each only fires when the trigger phrase actually changes.
From v0.1.937 / v0.1.938: Safari tab drag no longer corrupts Cmd+Tab history for other tabs in the same window, and a comprehensive source-code documentation pass landed for the browser-tab subsystem (no behaviour changes).
Full Release History (20 Latest)
View full CHANGELOG.md
The "Cmd+Tab is blocked" overlay now comes back the moment you press a shortcut into it. WOS's event tap is bypassed while Secure Input is held, so it cannot see Cmd+Tab — but the session-level event counters keep running (they must: idle detection has to work while a password is typed). While a hold persists, WOS samples `CGEventSource.counterForEventType`/`flagsState` at 5 Hz and, when a key goes down with Command/Control/Option held, force-shows the overlay out of schedule — the exact instant the user presses Cmd+Tab and gets nothing. Plain typing never triggers it (the commonest legitimate cause of Secure Input *is* the user typing a password), and Shift alone doesn't count. Throttled to one interruption per 15 s. Closes the gap where a dismissed warning stayed silent for 15 minutes while Cmd+Tab was dead — observed 2026-08-05: dismissed 11:15:07, next scheduled reminder 11:30:07, and in between the user concluded WOS had crashed. Policy is pure (`SecureInputAttentionPolicy`) and unit-tested. Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`SecureInputOverlayController.swift`](Sources/WOS/SecureInputOverlayController.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift).
Wake and unlock re-surface a held Secure-Input warning. The classic report is "the notebook slept overnight, I unlocked it, started working, and Cmd+Tab was dead". WOS now observes `NSWorkspace.didWakeNotification` and loginwindow's `com.apple.screenIsUnlocked`, and force-shows the overlay if the hold is still active — the user meets the state fresh at unlock, whatever the re-show schedule had planned before the machine slept.
After WOS restarts a stuck holder, it re-checks within seconds instead of waiting a minute. The mid-episode re-identification ran only on the 1/min heartbeat, so when the flag survived the holder's exit (2026-08-05: Chrome quit, `kCGSSessionSecureInputPID` kept naming the dead pid 16734, Secure Input stayed asserted) the overlay went on offering "Restart Google Chrome…" for a process that no longer existed — for 54 seconds, after which the heartbeat corrected it to the lock remedy that cleared the hold in 4 s. A restart WOS performed now schedules re-checks at 3/8/15 s, so the remedy switches as soon as the old process is actually gone. Files: [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift).
`scripts/build_release.sh` no longer SIGKILLs unrelated processes that merely mention "WOS". Its survivor sweep was `pgrep -f "WOS" | xargs kill -9` — a match against the whole command line, so it killed an editor with a WOS file open, a `log stream` filtered on our subsystem, or a shell whose arguments contained the word. It killed the shell running the 0.1.1028 release build itself (the output filter's pattern contained "WOS"), aborting the build mid-flight and — because the shell died with it — skipping the very `EXIT` trap meant to restore the app. The sweep now matches the app binary path (`/WOS.app/Contents/MacOS/WOS`), which still catches the `--watchdog` sibling and nothing else. File: [`build_release.sh`](scripts/build_release.sh).
`scripts/build_release.sh` no longer leaves the machine with no WOS running. The script kills every running instance before building — including the crash-relaunch watchdog, which its `kill -9` sweep also takes out — and, unlike `dev_loop.sh`, never restarted anything, because it exists to produce a DMG rather than to install one. So every release build silently took the user's WOS down until they noticed Cmd+Tab doing nothing (2026-08-04: ~21 hours). It now records the bundle path of the running instance (skipping the `--watchdog` sibling, relaunching which would not give the app back) and restores it from an `EXIT` trap, so the app returns even when the build fails or is interrupted, and warns instead of failing silently if the relaunch doesn't work. Opt out with `RELAUNCH_WOS_AFTER_BUILD=false` for headless build machines. File: [`build_release.sh`](scripts/build_release.sh).
The Secure-Input holder is now re-identified mid-episode when it stops making sense. Identification ran once, on the OFF→ON edge, so a long episode kept naming whoever was blamed at the start — verified wrong twice on 2026-08-03: after Brave was quit, `kCGSSessionSecureInputPID` kept naming the dead pid 3808 while Secure Input stayed asserted (the assertion outlived its owner — a session-level leak), and the overlay went on offering "Show Brave Browser" for an app that no longer existed; only a whole new episode or a WOS relaunch corrected the label. The observer now re-checks at heartbeat cadence (one IORegistry read + a `kill(pid, 0)` liveness probe per minute) and re-identifies when the recorded holder has exited or the holder pid changed, preserving `activatedAt` so episode duration keeps measuring from the original assertion. The corrected holder is published immediately, so the overlay's copy and button follow it — a dead app holder becomes a system holder and the remedy switches from "Restart \…" to the lock → logout ladder. Guarded against re-probing forever (a dead holder re-identifies to the same dead pid) and silent when nothing actually changed. Decision is pure (`SecureInputCulpritRefresh`) and unit-tested. Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift); tests in [`SecureInputTabJumpTests.swift`](Tests/SwitchCoreTests/SecureInputTabJumpTests.swift).
The Secure-Input overlay can now restart a stuck app holder — and stops claiming there is a prompt to dismiss when there isn't. A browser can *leak* its `EnableSecureEventInput` assertion: on 2026-08-03 Brave held Secure Input for 20+ minutes with a single window, no password field anywhere, surviving repeated front/background cycles — Cmd+Tab dead system-wide, and the overlay's only offer was "Show Brave Browser", clicked 15 times in 13 seconds because nothing else was there. App holders now get the escalation ladder system holders already had: "Show \" / "Show the Tab" → "Restart \…" , tripped either 25 s after a failed front attempt or 2 minutes into the episode (`SecureInputRemedy.shouldOfferRestart`, unit-tested), re-evaluated on the grace boundary rather than only on the 1/min heartbeat. The restart confirms first (unsubmitted form input is at stake), quits gracefully, waits up to 12 s for the process to exit — never force-kills, and says so when a "Leave site?" dialog blocks the quit — then relaunches, passing `--restore-last-session` to Chromium browsers so every tab comes back regardless of the user's "On startup" preference. Copy fixed in both places it was wrong: the overlay no longer says "dismiss the password prompt or finish entering your password" for a leaked hold, and the diagnostics file no longer prescribes "lock/unlock the screen" for an *app* holder — lock/unlock cannot touch an app's own assertion, only ending the process does (`SecureInputRemedy.stillHeldAdvice`, shared by both surfaces so they can't drift). Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`SecureInputOverlayController.swift`](Sources/WOS/SecureInputOverlayController.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift); tests in [`SecureInputTabJumpTests.swift`](Tests/SwitchCoreTests/SecureInputTabJumpTests.swift).
The Secure-Input overlay now jumps to the browser *tab* holding the keyboard, not just the browser. "Show Google Chrome" fronted the app and left the user hunting: the password field is one tab among hundreds, routinely in a background window of a *different profile* (12 Chrome windows is a normal session here), and `NSRunningApplication.activate` raises whichever window AppKit considers key. WOS now captures the holder's front tab at the OFF→ON edge — a focused password field lives in the front window's active tab, so that read *is* the culprit — and the button becomes "Show the Tab", selecting the exact tab (window raise → tab select, same order as Tab Therapy) so the user can close it. The overlay names the tab in its subtitle and the hint becomes "close it (Cmd+W)". The capture is budgeted (0.35 s, `fetchFrontTabWithinBudget`) because it runs on the observer's main-thread poll — a contended AppleScript engine yields no tab and the button silently degrades to the old "Show \". Only real browsers are probed (`BrowserKind.isWebBrowser` — a terminal holding Secure Input via Secure Keyboard Entry has no tab to close), and Incognito tab titles are redacted from the overlay and from `~/Library/Logs/WOS/WOS.log` while the jump still works. Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`SecureInputOverlayController.swift`](Sources/WOS/SecureInputOverlayController.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift); tests in [`SecureInputTabJumpTests.swift`](Tests/SwitchCoreTests/SecureInputTabJumpTests.swift).
The Secure-Input overlay now offers a one-click remedy. New contextual action button next to an explicit Dismiss: for stuck system holders (loginwindow, SecurityAgent, screensaver/Touch-ID brokers — including `com.apple.LocalAuthentication.UIAgent`, which the old system-holder matcher missed) it shows "Lock Screen to Fix" and locks the screen via `SACLockScreenImmediate` (login.framework, resolved dynamically, `#if !WOS_MAS`; degrades to a logged no-op naming the Control-Command-Q chord); for regular app holders it shows "Show \" and fronts the holder via `NSRunningApplication.activate` (unaffected by Secure Input) so the user can finish or dismiss the secure prompt. `SecureInputCulprit` now carries the holder `pid` for exact activation; remedy selection is pure (`SecureInputRemedy` in SwitchCore) and unit-tested. Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`SecureInputOverlayController.swift`](Sources/WOS/SecureInputOverlayController.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift).
The floating status toast can now be clicked away. The toast that surfaces persistent diagnostics next to the Cmd+Tab HUD / Quick Search panel ("⚠️ Multiple Google Chrome instances running…", missing Automation permission, …) accepted clicks but did nothing with them — its click handler was armed only for opt-in toasts (audio panic), so the warning could neither be moved nor dismissed and could linger on screen indefinitely. Now a click anywhere on the toast body hides it, and the exact dismissed message is suppressed for 30 minutes (`StatusToastDismissPolicy` in SwitchCore) so the persistent condition re-emitting the same note on the next HUD open doesn't undo the dismissal seconds later. Error toasts hide on click too but are never suppressed. The Details/Ignore buttons and the audio-toast click action are unchanged. Files: [`StatusToastDismissPolicy.swift`](Sources/SwitchCore/StatusToastDismissPolicy.swift), [`StatusHUDController.swift`](Sources/WOS/StatusHUDController.swift); tests in [`StatusToastDismissPolicyTests.swift`](Tests/SwitchCoreTests/StatusToastDismissPolicyTests.swift).
A dismissed Secure-Input warning now comes back while the hold persists, and Secure-Input episodes are recorded in a persistent logfile. The "Cmd+Tab is blocked" overlay could be waved away with one click for the *entire* episode — for a stuck system hold (loginwindow leaked Secure Input for two days, 2026-07-19) that meant a single reflexive click bought days of unexplained dead Cmd+Tab, and since WOS logged only to unified logging (unretrievable historically on many machines), there was nothing on disk to diagnose with afterwards. Now: a dismissed overlay re-shows 2 minutes after the first dismissal and every 15 minutes thereafter for as long as Secure Input stays held (`SecureInputReshowPolicy`, driven by a 1/min observer heartbeat), and a new append-only diagnostics file at `~/Library/Logs/WOS/WOS.log` (2 MB rotation, low-frequency events only) records app launches plus every Secure-Input episode: activation with holder/confidence/evidence, a "still held" line every 10 minutes, overlay shown/dismissed/re-shown, and release with duration. Files: [`DiagnosticsFileLog.swift`](Sources/SwitchCore/DiagnosticsFileLog.swift), [`SecureInputObserver.swift`](Sources/WOS/SecureInputObserver.swift), [`SecureInputOverlayController.swift`](Sources/WOS/SecureInputOverlayController.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift); tests in [`DiagnosticsFileLogTests.swift`](Tests/SwitchCoreTests/DiagnosticsFileLogTests.swift).
Link-click browser activations no longer promote the browser's previous tab above the app you came from. `freshenBrowserRecencyOnActivation` optimistically bumps the browser's last-known front tab at activation, betting the user is returning to it. When Chrome is activated *by a link click that opened a brand-new tab* (e.g. from the Gmail PWA), that bet is wrong — yet the wrongly-bumped old tab kept its fresh stamp and sat at Cmd+Tab position 2, displacing the app the user switched from ("Villa Brissago above Gmail"). The bump is now recorded as a `PendingArrivalBump` and settled by its paired deliberate capture: front tab matches the bumped entry (or its window) → bump stands; different front tab within 5 s → `LRSHistory.revertRecencyBump` restores the pre-bump timestamp (guarded so a legitimate write that landed in between is never demoted). Dropped/late captures leave the bump in place — preserving arrival order during rapid switching is what the bump exists for. Files: [`FrontTabFeed.swift`](Sources/SwitchCore/FrontTabFeed.swift), [`LRSHistory.swift`](Sources/SwitchCore/LRSHistory.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift).
Email-digest link clicks no longer leave a phantom duplicate tab row in Cmd+Tab. Clicking a tracking-wrapped link (e.g. a Quora digest opened from the Gmail PWA) makes Chrome open a *lander tab* — `google.com/url` → tracker → landing page — that `window.open`s the real destination tab and closes itself within ~0.5 s. Chrome mints a fresh tab GUID for each, so WOS's deliberate front-tab captures raced the hand-off and recorded both: the dead lander then sat at Cmd+Tab position 2 with the same title as the real tab (one press landed on a dead tab instead of the app you came from) until the next enumeration + prune (~30 s) removed it. The reconciler couldn't heal it — the real tab's entry consumes the live GUID via its Tier-1 exact match, and the lander's URL differs from the live tab's, so `tabMatchKeys` (URL-only when a URL is present) never linked them. New `TransientTabDetector` merges the pair at capture time instead: when a deliberate capture lands, a *provisional* (capture-inserted, never enumeration-confirmed) same-window predecessor tracked within the last 6 s whose normalized title or URL host matches is retired into the incoming tab via `renameStableID`, so the phantom never surfaces. Enumeration snapshots confirm provisional GUIDs as real (never merged) and expire registrations after 60 s. Diagnosed via Chrome History forensics (`visits.opener_visit` + 0.5 s `visit_duration` on the lander visit). Files: [`FrontTabFeed.swift`](Sources/SwitchCore/FrontTabFeed.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift); tests in [`FrontTabFeedTests.swift`](Tests/SwitchCoreTests/FrontTabFeedTests.swift).
Browser Extension (Turbo) automation engine is now real — a WOS Chrome extension replaces the never-shipped "patched browsers" backend. AppleScript stays the default; power users opt in via Settings → Performance. Three new pieces: an MV3 extension ([`Sources/WOS/Resources/ChromeExtension/`](Sources/WOS/Resources/ChromeExtension/README.md) — `chrome.tabs`/`chrome.windows` only, no `chrome.debugger`, so no "started debugging this browser" banner) speaking the existing `WOS.ListTabs`/`WOS.ActivateTab` JSON-RPC vocabulary; [`WOSNativeHost`](Sources/WOSNativeHost/main.swift), a native-messaging relay the browser launches, which serves the per-browser `NativeIPC.sock` that [`NativeIPCBridge`](Sources/SwitchCore/NativeIPCBridge.swift) already polls; and a shared [`WOSBridgeKit`](Sources/WOSBridgeKit/WOSBridge.swift) target owning the contract (framing codec, socket paths, pinned extension ID). New Settings card "Browser Extension Bridge" (Performance section) does one-click setup: writes native-messaging host manifests for every installed Chromium browser (Chrome, Chrome Beta/Canary, Brave, Arc) and reveals the unpacked extension at `~/Library/Application Support/WOS/ChromeExtension` for chrome://extensions → Load unpacked. Falls back to AppleScript automatically whenever the bridge is down. Direct-distribution only (`#if !WOS_MAS`). Files: [`ChromeExtensionInstaller.swift`](Sources/WOS/ChromeExtensionInstaller.swift), [`SettingsPanelController.swift`](Sources/WOS/SettingsPanelController.swift), [`build_release.sh`](scripts/build_release.sh), [`dev_loop.sh`](scripts/dev_loop.sh); tests in [`WOSBridgeKitTests.swift`](Tests/SwitchCoreTests/WOSBridgeKitTests.swift).
Automation Engine option renamed: "Native IPC (Turbo Mode - Patched Browsers Only)" → "Browser Extension (Turbo)" (same stored raw value — existing settings keep working).
When the Turbo engine is selected but the bridge socket is absent (extension off, browser closed), tab scans and activations now skip the bridge instantly instead of stalling on the 800 ms / 450 ms timeouts before falling back to AppleScript.
Successful bridge activations now also bring the browser app frontmost (the extension can only focus the window *within* the browser; AppleScript's `activate` used to do the app-level raise).
Chrome Canary/Beta get distinct bridge socket paths (previously all three Chrome variants collided on `Google/Chrome/NativeIPC.sock`).
Subprocess AppleScript output was never decoded — the first tab of every enumeration was silently dropped. Both `osascript` subprocess runners launch with `-s s` (source-form output), which wraps string results in quotes and backslash-escapes `"`/`\`. Nobody decoded it (since 2026-03): the leading quote glued onto the first data row, its index failed `Int()` parsing, and tab 1 of window 1 vanished from every scan, for every browser — the history pruner then kept evicting that tab's Cmd+Tab entry as "closed". Masked for months by the pre-0.1.1014 sampler firehose; the (correct) anti-firehose change exposed it. Output is now decoded centrally in both runners (`AppleScriptSubprocess.decodeSourceForm`), so subprocess and in-process paths return identical text — this also stops literal `\"` escapes leaking into stored tab titles and match keys. `parseTabRows` now warning-logs any malformed row it drops, so a parse regression can never be silent again. Files: [`AppleScriptSubprocess.swift`](Sources/SwitchCore/AppleScriptSubprocess.swift), [`BrowserScriptBridge.swift`](Sources/SwitchCore/BrowserScriptBridge.swift); see LESSONSLEARNED → "osascript `-s s` Quote-Wrapped Every String Result".
Post-commit verification pruned the tab the user had just switched to. Verification compared the *stored* title/URL against the live front tab — for an SPA that rewrites both between visits (per-route titles, badge counters, overnight session-expiry → login redirect), every *successful* Cmd+Tab activation evaluated as `.differs`. The recovery chain's content search ran against the dead metadata, the `activateWindow` fallback was frequently aborted by an `activationToken` bump (the same SPA's title churn fires the manual-switch classifier every few seconds), and the `.differs + failed fallback` path removed the just-activated entry from history. Static-title tabs never triggered it — which is why exactly one heavily-used web app kept dying. Two fixes: (1) `BrowserTabMatchEvaluator` gained an identity tier ahead of metadata — index-based browsers (Safari/Firefox/terminals) match on window + tab index (precisely what the activation targeted), Chromium on the full composite tab-GUID identifier; (2) the eviction arm now refuses to prune a stableID still present in the live open-tab cache (a token-aborted fallback is "couldn't act", not "target gone"). Files: [`BrowserTabMatch.swift`](Sources/SwitchCore/BrowserTabMatch.swift), [`AppDelegate.swift`](Sources/WOS/AppDelegate.swift); see LESSONSLEARNED → "Post-Commit Verification Compared Dead Metadata".