Skip to content

fix(focus): prime VS Code's Electron AX tree so suggestions work#671

Merged
FuJacob merged 2 commits into
mainfrom
fix/vscode-ax-priming-allowlist
Jun 11, 2026
Merged

fix(focus): prime VS Code's Electron AX tree so suggestions work#671
FuJacob merged 2 commits into
mainfrom
fix/vscode-ax-priming-allowlist

Conversation

@FuJacob

@FuJacob FuJacob commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

VS Code produced no suggestions anywhere (editor, chat, integrated terminal), even with the integrated-terminal setting on, while OCR kept working. Root cause: the Electron AX-priming allowlist (BrowserAppDetector.electronEditorBundleIdentifiers) only contained ClickUp, so Cotabby never set AXManualAccessibility on VS Code and its lazily-built web accessibility tree stayed dormant — no focused text element ever resolved.

Two changes:

  1. Add the VS Code family (Code, Insiders, VSCodium) to the priming allowlist, and make isElectronEditor case-insensitive (VS Code's real bundle id is the mixed-case com.microsoft.VSCode, which the prior exact Set.contains would have missed).
  2. Re-assert the prime for Electron editors on every activation edge. Observed live: on a long-running VS Code the first AXManualAccessibility write returns success but the tree stays dormant for minutes; a re-assert on app switch wakes it promptly. Chromium browsers keep the existing once-per-PID behavior.

Validation

Verified live on a macOS 26 machine with the dev build (Cotabby Dev, -cotabby-debug), driving real VS Code:

  • Prime fires: CHROME-PRIME enabled web accessibility for Code (never present in any pre-fix log).
  • Focus resolves: Resolve timing: app=Code … up to capability=Supported; terminal caret derived primary, chat caret exact primary.
  • Setting gates correctly, both directions, typing in the integrated terminal (xterm-helper-textarea focused, confirmed via direct AX query):
    • cotabbySuggestInIntegratedTerminals=1 → no terminal suppression; prediction pipeline proceeds.
    • =0Predictions disabled: Cotabby is not available in the integrated terminal.
  • Hardened build: prime + capability=Supported within ~200 ms of launch against an already-frontmost VS Code.
swiftlint lint --quiet   # exit 0
xcodebuild test … BrowserAppDetectorTests + TerminalAppDetectorTests
# ** TEST SUCCEEDED **  25 tests, 0 failures

Linked issues

Refs the "no suggestions in VS Code" report.

Risk / rollout notes

  • Scope honesty: this PR makes VS Code resolvable and fully fixes the integrated terminal path. The editor and Copilot chat use VS Code's native-edit-context, whose AXValue stays empty (and the editor's focus proxy has a zero-width frame), so those surfaces resolve but cannot produce content-aware suggestions yet — that needs a native-edit-context text source (follow-up; related to the TextKit caret work).
  • New behavior: one extra AXManualAccessibility write per activation of a named Electron editor; Chromium browsers unchanged.
  • Integrated-terminal ghost text still respects suggestInIntegratedTerminals (off by default).
  • Cursor/Windsurf remain uncovered (opaque ToDesktop / unverified bundle ids); follow-up candidates.

Greptile Summary

This PR fixes VS Code (and VSCodium / VS Code Insiders) receiving no suggestions by adding them to the Electron AX-priming allowlist and making the isElectronEditor check case-insensitive — VS Code's real bundle id is the mixed-case com.microsoft.VSCode, which the prior case-sensitive Set.contains silently missed.

  • BrowserAppDetector.swift: Adds com.microsoft.vscode, com.microsoft.vscodeinsiders, and com.vscodium to electronEditorBundleIdentifiers (all lowercased) and lowercases the input in isElectronEditor before the Set lookup.
  • ChromiumAccessibilityEnabler.swift: Introduces lastFrontmostPID to track activation edges; Electron editors are re-primed on every app-switch back, working around VS Code's observed behaviour of ignoring the first AXManualAccessibility write.
  • BrowserAppDetectorTests.swift: New assertions cover VS Code's mixed-case bundle id, Insiders, VSCodium, and the Discord negative case, with a needsWebAccessibilityPriming smoke test for the mixed-case id.

Confidence Score: 5/5

Safe to merge — the change wakes VS Code's AX tree the same way Chrome and ClickUp have been primed all along, using no new mechanism.

The core fix (lowercasing before the Set lookup and adding the VS Code bundle ids) is straightforward and well-tested. The activation-edge re-priming in ChromiumAccessibilityEnabler is narrowly scoped to isElectronEditor apps and incurs at most one extra AX write per app switch. Chromium browsers retain the existing once-per-PID path untouched. The lastFrontmostPID update is placed before the needsWebAccessibilityPriming guard, so it correctly tracks activation edges even for apps that are not primed. No data is persisted, no new IPC is introduced, and the change is fully reversible.

No files require special attention.

Important Files Changed

Filename Overview
Cotabby/Support/BrowserAppDetector.swift Adds VS Code, VS Code Insiders, and VSCodium (all lowercased) to the Electron editor allowlist and makes isElectronEditor case-insensitive by lowercasing the input before the Set lookup.
Cotabby/Services/Focus/ChromiumAccessibilityEnabler.swift Introduces lastFrontmostPID to detect app-activation edges; Electron editors are re-primed on each such edge, working around VS Code's observed behaviour of ignoring the first AXManualAccessibility write while long-running.
CotabbyTests/BrowserAppDetectorTests.swift Extends the existing test to assert VS Code (mixed-case bundle id), Insiders, and VSCodium are treated as Electron editors, Discord stays excluded, and needsWebAccessibilityPriming returns true for the mixed-case VS Code id.

Reviews (2): Last reviewed commit: "fix(focus): re-assert Electron editor pr..." | Re-trigger Greptile

FuJacob added 2 commits June 10, 2026 23:04
VS Code produced no suggestions anywhere (editor, Copilot chat, OR the
integrated terminal) because the Electron AX-priming allowlist only held
ClickUp. Chromium/Electron build their web accessibility tree lazily, so
without AXManualAccessibility priming VS Code's tree stays dormant and no
focused text element ever resolves. Debug logs confirm it: Chrome, cmux,
Finder, etc. all resolve focus, but 'Code' never appears once.

Add the VS Code family (Code, Insiders, VSCodium) to the priming allowlist
and make isElectronEditor case-insensitive: VS Code's real bundle id is the
mixed-case com.microsoft.VSCode, which the prior exact Set.contains would
have missed even after adding it. Cursor/Windsurf stay uncovered (opaque
ToDesktop bundle ids that change per build); noted inline.
Observed live on VS Code: the first AXManualAccessibility write returns
success on a long-running process, yet the web-AX tree stays dormant for
minutes; a later re-assert wakes it promptly. Re-prime named Electron
editors on every activation edge (one cheap AX write per app switch)
instead of once per PID. Chromium browsers keep once-per-PID, which
already works for them.
@FuJacob FuJacob merged commit 9f74241 into main Jun 11, 2026
4 checks passed
@FuJacob FuJacob deleted the fix/vscode-ax-priming-allowlist branch June 11, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant