macOS: keep foreground tracking coherent when browser context fails - #141
macOS: keep foreground tracking coherent when browser context fails#141hawai-i wants to merge 1 commit into
Conversation
Greptile SummaryThe PR restructures the native macOS watcher around PID-based foreground reconciliation and preserves app/title heartbeats when optional browser enrichment fails.
Confidence Score: 3/5The PR should not merge until the Chrome fallback preserves incognito privacy when browser scripting is unavailable. The new fallback fixes dropped foreground evidence but also sends AX-derived Chrome identity and titles when the failed browser lookup prevents the only incognito check; the Swift test target additionally does not exercise the supported deployment floor. Files Needing Attention: aw_watcher_window/macos.swift, Makefile
|
| Filename | Overview |
|---|---|
| aw_watcher_window/macos.swift | Consolidates foreground reconciliation and improves recovery, but the browser-failure fallback bypasses Chrome incognito blanking. |
| aw_watcher_window/macos_state.swift | Adds small, deterministic helpers for observer rebuild decisions and stale AX callback rejection. |
| tests/macos_state_tests.swift | Covers PID changes, observer repair, and callback ownership for the extracted reconciliation helpers. |
| Makefile | Wires the new Swift source and tests into builds, though the test compiler invocation does not preserve the production macOS 12 target. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Startup, activation, or poll] --> B[Select NSRunningApplication]
B --> C{Tracked PID changed or observer missing?}
C -->|Yes| D[Rebuild AX observer]
C -->|No| E[Reuse observer]
D --> F[Refresh focused AX window]
E --> F
F --> G[Read app and window title]
G --> H{Supported browser?}
H -->|Chrome or Safari| I{Browser context available?}
I -->|Yes| J[Add URL and tab title]
I -->|No| K[Keep AX app and title]
H -->|Firefox| L[Read URL from AX tree]
H -->|Other| M[Keep app and title]
J --> N[Apply privacy filters]
K --> N
L --> N
M --> N
N --> O[Send heartbeat]
Reviews (1): Last reviewed commit: "fix(macos): preserve foreground events w..." | Re-trigger Greptile
| } else { | ||
| log("Failed to read Chrome context; emitting foreground heartbeat without URL") | ||
| } |
There was a problem hiding this comment.
Fallback bypasses incognito blanking
If Chrome automation access is unavailable while Accessibility access remains granted, this fallback sends the AX-derived application and window title even for an incognito window, causing private browsing information to be stored in the currentwindow bucket. Incognito blanking occurs only inside the successful ScriptingBridge branch, with no equivalent guard before sendHeartbeat. How this was verified: The failed optional ScriptingBridge chain was traced to heartbeat delivery while the only incognito check remains inside its successful branch.
Knowledge Base Used:
| fi | ||
|
|
||
| test-swift: | ||
| swiftc aw_watcher_window/macos_state.swift tests/macos_state_tests.swift -o /tmp/aw-watcher-window-macos-state-tests |
There was a problem hiding this comment.
The new state-test command does not use the production helper's macOS 12 target, so it can pass with APIs available only on the runner's newer deployment target and provide false compatibility coverage.
| swiftc aw_watcher_window/macos_state.swift tests/macos_state_tests.swift -o /tmp/aw-watcher-window-macos-state-tests | |
| swiftc -target "$(shell uname -m)-apple-macosx$(MACOSX_DEPLOYMENT_TARGET)" aw_watcher_window/macos_state.swift tests/macos_state_tests.swift -o /tmp/aw-watcher-window-macos-state-tests |
Knowledge Base Used:
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Browser URL/title enrichment is optional context, but the macOS Swift watcher currently returns without emitting a foreground heartbeat when some Chrome/Safari ScriptingBridge lookups fail. Heartbeat merging then extends the previous application's event across the real browser interval.
This change:
NSRunningApplicationfrom the workspace notification;Validation
A controlled
Codex → Chrome → Finder → Chrome → Codexsequence was scored against WindowServer's top visible layer-0 owner. Browser context failure was forced at the existing pre-heartbeat failure point in both the before and fixed test builds.A normal companion build also retained same-title Chrome
page-a → page-bURL changes.Automated Swift state tests cover:
make build-swift,make test-swift, a real PyInstaller 6.11 package build,mypy, andgit diff --checkpassed. The packaged arm64 helper preserves the macOS 12.0 minimum. The borrowed local Python environment reported 61 passing tests and two macOS config-path failures that reproduce unchanged on the base commit.Related work
ActivityWatch/activitywatch#1411 grants the responsible outer app Apple Events permission, which lets browser context acquisition succeed. This PR is logically independent: foreground truth must still be emitted when optional context is unavailable.
This also corrects the mismatched title-notification cleanup and observer teardown discussed in #139, but this PR does not claim a separate multi-day leak validation.