diff --git a/.claude/skills/prowl-ui/SKILL.md b/.claude/skills/prowl-ui/SKILL.md index 66c753bc..15e4417c 100644 --- a/.claude/skills/prowl-ui/SKILL.md +++ b/.claude/skills/prowl-ui/SKILL.md @@ -31,7 +31,7 @@ Run the bundled script before opening an AX session: .claude/skills/prowl-ui/scripts/preflight.sh ``` -It checks `command -v agent-ctrl`, requires version 0.1.3 or newer, inspects `info --json`, and runs +It checks `command -v agent-ctrl`, requires version 0.1.4 or newer, inspects `info --json`, and runs `doctor --json --quick`. Its contract is: - Exit `0` with `{"status":"READY",...}` when the macOS AX surface and Accessibility permission are ready. @@ -90,7 +90,10 @@ An action response such as `ok method=ax-press`, `ax-value`, or `cg-event` is de changed state. Never report `PASS` from the action response alone. If delivery is uncertain, observe before considering a retry. -Use refs only from the latest snapshot. `find` searches the cached snapshot; it does not walk the UI itself. For negative +Use refs only from the latest snapshot. `find` searches the cached snapshot; it does not walk the UI itself. Structural +containers — the window root, toolbars, dialog and sheet roots, and popover containers — carry scope-only refs (`@sN` in +CLI output, `scope_N` in JSON). Use them with `find --in`, `get`, and `is` to bound a search to one surface; actions on a +scope ref are rejected by design, so act on an `@eN` element ref resolved inside the scope. For negative scroll deltas, terminate option parsing explicitly, for example: ```bash @@ -171,7 +174,10 @@ of treating a focus failure as proof that the window is inaccessible. `Add...` opens a named container with identifier `add-to-prowl-popover` inside the in-window `Add to Prowl` dialog. `Browse…` opens an `NSOpenPanel` sheet that remains embedded in the main window's AX tree; it may not appear as another -entry in `window-list`. Inspect the pinned tree for `dialog`, `Cancel`, and `Open` before searching for a sibling window. +entry in `window-list`. Resolve the active surface with `find --role dialog` — dialog and sheet roots carry scope-only +refs — then scope common-control lookups such as `Cancel` or `Open` with `find --in @sN` instead of searching the whole +window tree. Cancelling a nested `NSOpenPanel` can also dismiss the popover that opened it, so re-run `find --role dialog` +to confirm which surfaces remain before further cleanup. Prefer `fill` on a fresh editable ref for safe text-entry checks. Keyboard `press` can fail with `AXRaise` on sheets or Settings. Native search fields can temporarily replace the snapshot root with a suggestions menu and may never become diff --git a/.claude/skills/prowl-ui/scripts/preflight.sh b/.claude/skills/prowl-ui/scripts/preflight.sh index f9fa100a..a9d621bc 100755 --- a/.claude/skills/prowl-ui/scripts/preflight.sh +++ b/.claude/skills/prowl-ui/scripts/preflight.sh @@ -3,7 +3,7 @@ set -u set -o pipefail -minimum_version="0.1.3" +minimum_version="0.1.4" skip() { local reason="$1" diff --git a/.claude/skills/prowl-ui/scripts/preflight_test.sh b/.claude/skills/prowl-ui/scripts/preflight_test.sh index ccb711f5..a8de7dc0 100755 --- a/.claude/skills/prowl-ui/scripts/preflight_test.sh +++ b/.claude/skills/prowl-ui/scripts/preflight_test.sh @@ -16,7 +16,7 @@ cat >"$mock" <<'EOF' #!/bin/bash case "${1:-}" in --version) - printf 'agent-ctrl %s\n' "${MOCK_VERSION:-0.1.3}" + printf 'agent-ctrl %s\n' "${MOCK_VERSION:-0.1.4}" ;; info) printf '%s\n' "${MOCK_INFO_JSON:-}" @@ -39,7 +39,7 @@ run_preflight() { set +e output="$( AGENT_CTRL_BIN="${AGENT_CTRL_BIN_OVERRIDE:-$mock}" \ - MOCK_VERSION="${MOCK_VERSION_OVERRIDE:-0.1.3}" \ + MOCK_VERSION="${MOCK_VERSION_OVERRIDE:-0.1.4}" \ MOCK_INFO_JSON="${MOCK_INFO_OVERRIDE:-}" \ MOCK_DOCTOR_JSON="${MOCK_DOCTOR_OVERRIDE:-}" \ /bin/bash "$preflight" 2>&1 @@ -72,13 +72,13 @@ assert_status 2 "missing binary" assert_json '.status == "SKIPPED" and .reason == "agent_ctrl_not_installed"' "missing binary" AGENT_CTRL_BIN_OVERRIDE="$mock" -MOCK_VERSION_OVERRIDE="0.1.2" +MOCK_VERSION_OVERRIDE="0.1.3" run_preflight assert_status 2 "old version" -assert_json '.status == "SKIPPED" and .reason == "unsupported_version" and .minimum_version == "0.1.3"' \ +assert_json '.status == "SKIPPED" and .reason == "unsupported_version" and .minimum_version == "0.1.4"' \ "old version" -MOCK_VERSION_OVERRIDE="0.1.3" +MOCK_VERSION_OVERRIDE="0.1.4" MOCK_INFO_OVERRIDE='{"os":"macos","recommended_surface":"ax","surfaces":[{"kind":"ax","status":"ready"}],"macos_accessibility":"denied"}' MOCK_DOCTOR_OVERRIDE='{"success":false,"checks":[{"id":"env.surface.ax","status":"pass"},{"id":"perm.accessibility","status":"fail"}]}' run_preflight @@ -89,12 +89,12 @@ MOCK_INFO_OVERRIDE='{"os":"macos","recommended_surface":"ax","surfaces":[{"kind" MOCK_DOCTOR_OVERRIDE='{"success":true,"checks":[{"id":"env.surface.ax","status":"pass"},{"id":"perm.accessibility","status":"pass"}]}' run_preflight assert_status 0 "ready" -assert_json '.status == "READY" and .version == "0.1.3" and .surface == "ax"' "ready" +assert_json '.status == "READY" and .version == "0.1.4" and .surface == "ax"' "ready" -MOCK_VERSION_OVERRIDE="0.1.3+local" +MOCK_VERSION_OVERRIDE="0.1.4+local" run_preflight assert_status 0 "build metadata version" -assert_json '.status == "READY" and .version == "0.1.3+local"' "build metadata version" +assert_json '.status == "READY" and .version == "0.1.4+local"' "build metadata version" MOCK_DOCTOR_OVERRIDE='not-json' run_preflight