fix: CI builds helpers from source; survive AX cycles; portable ax tests - #17
Merged
Merged
Conversation
…urces The accessibility tree is a graph. Safari lists the application element as its own child and answers kAXWindows with it, so the walk descended into the application over and over and returned menu bars at the depth limit instead of the window — the cause of an occasional two-node result. Visited elements are now tracked by CFHash/CFEqual. Windows come from the union of kAXWindows and the application element's children, filtered to real windows and never the app element, since apps differ in which they populate. The union is a superset of the children-only path that was working before. The tests stopped assuming a fixed app has a window. They now probe until the accessibility API actually answers and skip when nothing does: CGWindowList still lists windows on a locked Mac while AX exposes none, and a CI runner has neither — which is why a hard-coded Finder target passed locally and failed on CI, where it had only ever passed by exercising the fallback these tests exist to forbid. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mainis currently red — the Release run after #16 failed — and this is the fix.CI was testing the previous release, not the branch
postinstalldownloads prebuilt helpers for the package's current version. Once that version is published, CI on a branch that changes Swift finds those assets and runs the whole suite against the previous release. Native changes were never tested.It surfaced when two tests covering behaviour added in #16 failed on CI while passing locally: the runner was executing a binary that predated them. CI now sets
MACOS_VISION_SKIP_DOWNLOAD=1and asserts each helper exists and is newer than its source.The AX tree is a graph, and the walk assumed it was a tree
Safari lists the application element as its own child, and answers
kAXWindowswith it:Without cycle protection the walk descends into the application repeatedly and returns menu bars at the depth limit instead of the window — the cause of an occasional two-node result seen while wiring this into the MCP server. Visited elements are now tracked by
CFHash/CFEqual, and windows are taken from the union ofkAXWindowsand children, filtered to real windows and never the app element.The tests asserted a precondition instead of checking it
They targeted Finder.
CGWindowListstill lists windows on a locked Mac while AX exposes none, and a CI runner has neither — so the fixed target passed locally and failed on CI, where it had only ever passed by exercising the very fallback #16 removed. They now probe until they find an app AX actually answers for, and skip when none does.Verification, and what is not verified
105/105 with the screen locked, which is the headless case: the
axTreetests skip cleanly and everything else passes. CI on this PR exercises that path for real, compiling from source.Not verified by me: the windowed path with this new union enumeration — the machine locked itself and stays locked behind a password. The union is a superset of the children-only enumeration that was returning 224 nodes correctly before, so the risk is low, but it deserves one run on an unlocked Mac before release.
🤖 Generated with Claude Code