390 Commits

Author SHA1 Message Date
Michał Pierzchała e9c473034b 0.11.15 v0.11.15 2026-04-11 16:24:31 +02:00
Michał Pierzchała ffd472a5bf feat: expose typed client command methods (#380) 2026-04-11 16:24:16 +02:00
Michał Pierzchała 60bed774c6 chore: clean up unused exports (#383) 2026-04-11 15:43:39 +02:00
Michał Pierzchała 98dc1c7def refactor: extract shared test utilities and remove redundant assertions (#382)
* Remove test assertions redundant with TypeScript static analysis

Drop assertions that merely verify unset optional properties are
undefined (a JavaScript language guarantee) and a second test block
whose only runtime value was re-checking literals just assigned to
typed variables. TypeScript's compiler already validates that these
object literals conform to the declared union types.

* fix: remove unused descriptor variable to fix noUnusedLocals

* refactor: extract shared test utilities from duplicated patterns

Introduce src/__tests__/test-utils/ with reusable device fixtures,
session factories, store factory, snapshot builders, and mocked
binary helpers. Migrate 27 test files to use these shared utilities,
eliminating duplicated DeviceInfo constants, makeSession/makeStore
helpers, snapshot node builders, and withMockedAdb/withMockedXcrun
across core, daemon, and handler tests.

Add AGENTS.md guidance to check test-utils before writing new tests.

* fix: restore public Metro type contract coverage with satisfies fixtures
2026-04-11 14:21:15 +02:00
Michał Pierzchała c91d547fb1 0.11.14 v0.11.14 2026-04-11 13:46:46 +02:00
Michał Pierzchała 4a1104e1f7 0.11.13 2026-04-11 13:42:48 +02:00
Michał Pierzchała a48eb96336 docs: clarify agent runtime and preflight guidance (#381) 2026-04-11 13:02:55 +02:00
Michał Pierzchała 20021c3d1c refactor: reduce duplication and simplify codebase (#374)
* refactor: reduce duplication and simplify codebase

Eliminate copy-pasted functions, inline error boilerplate, and repeated
patterns across daemon handlers and platform modules.

Key changes:
- Deduplicate isEnvTruthy, displayNodeLabel, roundPercent into single sources
- Extract throwDaemonError helper for client/CLI daemon response errors
- Add sessionNotFoundResponse/unsupportedOperationResponse helpers and
  adopt errorResponse() across ~30 handler files (-565 lines)
- Unify BATCH_PARENT_FLAG_KEYS/REPLAY_PARENT_FLAG_KEYS into shared
  mergeParentFlags helper in handler-utils
- Extract createLinuxToolResolver for screenshot/clipboard tool detection
- Remove stale type-sync comments from contracts.ts and metro.ts

* refactor: deeper structural simplification pass

Bigger wins from restructuring, not just mechanical dedup:

- cli.ts: move logTailStopper to try/finally (eliminates 28 duplicate
  calls), extract writeCommandCliOutput/writeLogsCliOutput/writeNetworkCliOutput
  from 350-line if/else chain, fix remaining throwDaemonError site
- session-store.ts: replace 67-line sanitizeFlags destructure/reconstruct
  with 10-line pick-from-array loop
- record-trace: extract finalizeRecordingOverlay helper, replacing 4
  copies of the telemetry+overlay block across ios/android/recording files
- Deduplicate normalizeText (finders.ts + selectors-match.ts)
- Fix isEnvTruthy to preserve whitespace-tolerant parsing (.trim())

* fix: ensure logTailStopper runs before process.exit

process.exit() does not unwind the stack, so finally blocks are
skipped. Restore explicit logTailStopper() calls before each
process.exit() to prevent leaking the background daemon log tail
process. The finally block remains as a safety net for normal
return paths.

Also refactor writeCommandCliOutput to return an exit code instead
of calling process.exit() directly, keeping the exit decision in
the caller where cleanup is visible.

* refactor: simplify daemon failure responses

* refactor: remove redundant daemon response cast
2026-04-11 12:53:53 +02:00
Michał Pierzchała be001e1906 feat: add upload cache preflight (#379) 2026-04-11 12:53:30 +02:00
Michał Pierzchała 52d9707647 feat: expose apps list in node client (#378) 2026-04-11 12:33:58 +02:00
Michał Pierzchała 937ce8f6b2 test: stabilize android emulator boot tests (#377) 2026-04-11 10:36:38 +02:00
Michał Pierzchała 897c25def8 fix: clean up metro companion workers (#376)
* fix: clean up metro companion workers

* fix: clarify metro companion lease shutdown

* test: fix installed-package metro typecheck
2026-04-11 09:38:03 +02:00
Michał Pierzchała 3c62a2b839 fix: carry remote-config run id for install-from-source (#375)
* fix: carry remote-config run id for install-from-source

* test: reuse CLI capture helper in remote-config regression
2026-04-10 20:27:34 +02:00
Michał Pierzchała d4ee32f998 0.11.12 v0.11.12 2026-04-10 14:06:39 +02:00
Michał Pierzchała be09c1d58a feat: expose bridge-facing contract and metro APIs (#373)
* feat: expose bridge-facing contract and metro APIs

* chore: address review feedback on public contract exports

* refactor: reuse public daemon contracts internally

* refactor: reuse public metro types internally

* fix: widen bridge-facing public contracts
2026-04-10 14:06:27 +02:00
Michał Pierzchała c02cbd015f 0.11.11 v0.11.11 2026-04-10 13:03:33 +02:00
Michał Pierzchała 66d65c887c refactor: expose metro and remote config node apis (#372)
* refactor: expose metro and remote config node apis

* refactor: tighten public node api surface

* refactor: tighten metro public type boundaries

* refactor: normalize remote config public profile

* refactor: make remote config parser library-owned

* refactor: share remote config parsing primitives

* refactor: avoid regex in base url normalization
2026-04-10 13:03:13 +02:00
Michał Pierzchała a4d686e686 fix: package detached worker entrypoints (#371)
* fix: package detached worker entrypoints

* refactor: rename metro companion worker entry

* chore: trim packaged smoke logging
2026-04-10 11:45:20 +02:00
Michał Pierzchała defbe44852 0.11.10 v0.11.10 2026-04-10 09:45:04 +02:00
Michał Pierzchała f3181a51b6 fix: auto-manage metro companion for remote runs (#370)
* fix: auto-manage metro companion for remote runs

* fix: fail fast on non-retryable metro bridge errors

* fix: scope metro companion ownership by profile

* fix: align remote close metro companion cleanup

* fix: guard metro companion shutdown reconnect

* test: ignore expected bridge reset in metro reconnect test

* chore: format, cleanup
2026-04-10 09:42:38 +02:00
Michał Pierzchała 9cbba956b0 fix: require auth for non-loopback remote daemons (#369)
* fix: require auth for non-loopback remote daemons

* fix: allow mapped loopback remote daemons

* refactor: use net blocklist for loopback checks
2026-04-08 13:45:52 +02:00
Michał Pierzchała 877aaef920 0.11.9 v0.11.9 2026-04-08 11:00:58 +02:00
Michał Pierzchała c6666803c1 fix: address vite and lodash dependabot alerts (#368)
* fix: address vite and lodash dependabot alerts

* fix: update rspress theme dependencies
2026-04-08 09:09:38 +02:00
Michał Pierzchała 60e23b0b32 ci: reduce e2e retries in workflows (#367) 2026-04-07 20:50:18 +02:00
Michał Pierzchała 98069db6d5 fix: harden command execution and replay script escaping (#364)
* fix: harden command execution and replay script escaping

* fix: tighten whichCmd executable checks

* fix: allow explicit relative executables
2026-04-07 20:19:26 +02:00
Michał Pierzchała 3eccb5b5c4 fix: recover android network dump after stale logcat pid (#363) 2026-04-07 18:48:07 +02:00
Michał Pierzchała b204c65b2e fix: fingerprint daemon runtime graph (#361) 2026-04-07 18:29:21 +02:00
Michał Pierzchała 80e1bb84b6 refactor: replace xctestrun XML regex parsing with shared helper (#362)
* refactor: use shared xml parser for xctestrun fallback

* refactor: share plist xml traversal helpers
2026-04-07 18:29:07 +02:00
Michał Pierzchała 83db76f14a feat: add iOS device perf sampling (#358)
* feat: add iOS device perf sampling

* fix: restart stale daemon after source changes

* chore: ignore tests in daemon signature

* fix: dedupe iOS perf samples by pid

* chore: move daemon invalidation out of perf PR

* refactor: use fast xml parser for iOS perf exports

* refactor: simplify iOS perf XML coverage

* test: align iOS perf parser follow-ups

* fix: preserve duplicate iOS perf export columns

* refactor: reuse XML parser for plist fallback

* refactor: share iOS XML parsing helpers
2026-04-07 16:46:15 +02:00
Michał Pierzchała 72cc398585 0.11.8 v0.11.8 2026-04-04 17:31:45 +02:00
Michał Pierzchała 48aa32921d fix: respect scoped simulator sets in ios runner (#354)
* fix: respect scoped simulator sets in ios runner

* fix: harden xctest device set redirect

* fix: preserve xctest backup on redirect collisions

* fix: release simulator-set redirect on abort path and simplify redirect internals

Address P1 review feedback: abortAllIosRunnerSessions now releases
simulator-set redirect handles after killing processes, preventing
stale locks from blocking subsequent scoped simulator commands.

Simplify redirect internals:
- Store redirect handle directly on session instead of wrapping in closure
- Simplify sameResolvedPath to direct comparison instead of set intersection
- Collapse double liveness check in clearStaleXcodebuildSimulatorSetLock

https://claude.ai/code/session_01VsAUdPKbQoGbwvftBZtXfB

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-04 15:45:59 +02:00
Michał Pierzchała caf0e834b8 feat: add Linux desktop automation support via AT-SPI2 (#356)
* feat: add Linux desktop automation support via AT-SPI2 (Phase 1+2)

Add Linux as a first-class platform using AT-SPI2 accessibility framework
via node-gtk for accessibility tree snapshots. This mirrors the macOS
desktop automation approach using accessibility snapshots.

New files:
- src/platforms/linux/atspi-bridge.ts: Core AT-SPI2 bridge using node-gtk
  with lazy loading, recursive tree traversal (max 1500 nodes, depth 12)
- src/platforms/linux/role-map.ts: AT-SPI2 role normalization (~100 roles
  mapped to existing snapshot type conventions)
- src/platforms/linux/snapshot.ts: Snapshot entry point with surface,
  scope, depth, and interactive-only filtering support
- src/platforms/linux/devices.ts: Local device discovery for Linux
- src/platforms/linux/node-gtk.d.ts: Type declarations for node-gtk

Integration:
- Extended Platform type with 'linux', backend union with 'linux-atspi'
- Wired snapshot into dispatch.ts and snapshot-capture.ts
- Added Linux device discovery to dispatch-resolve.ts
- Added stub interactor (input actions deferred to Phase 3)
- Added 'linux' to CLI --platform flag
- node-gtk added as optional dependency (only installs on Linux)

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* refactor: code review cleanup for Linux platform support

- Extract SnapshotBackend type alias to replace repeated string union
  across 5 files (snapshot.ts, snapshot-capture.ts, session-replay-heal.ts,
  interaction.test.ts)
- Remove duplicate scope/interactive/depth filtering from
  linux/snapshot.ts — let the existing buildSnapshotState pipeline handle
  it, same as Android
- Extract isDesktopBackend() helper in snapshot-capture.ts to consolidate
  the "skip mobile semantics" pattern for macos-helper and linux-atspi
- Collapse 17 repetitive throw statements in Linux interactor stubs
  into a linuxStub() factory function

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* feat: Linux input synthesis, screenshots, and app lifecycle (Phase 3+4)

Add xdotool/ydotool input actions (tap, swipe, scroll, type, fill,
right/middle click, long press, double click), screenshot capture via
grim/scrot, and app lifecycle management (open, close, back, home).
Wire Linux interactors with real implementations and fix device
discovery order so Linux doesn't displace Android in auto-selection.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* refactor: consolidate Linux env detection, simplify input actions

- Extract linux-env.ts with cached display server + input tool detection
  so every action avoids repeated `which` lookups
- Add moveTo/clickButton/sendKey helpers to eliminate repeated
  mousemove boilerplate across 5 mouse actions
- Make scrollLinux respect amount/pixels options instead of hardcoded
  scroll count
- Have backLinux/homeLinux reuse sendKey instead of duplicating tool
  detection

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* feat: add Linux CI smoke test with Xvfb and AT-SPI2

Add GitHub Actions workflow that boots a virtual X11 display (Xvfb),
installs AT-SPI2 accessibility tooling and xdotool, opens
gnome-calculator, takes screenshots, and captures an accessibility
snapshot. Screenshots are uploaded as artifacts for visual verification.

Also adds 'linux' to replay script metadata platforms and a
test:replay:linux script to package.json.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: remove pre-session screenshot from Linux replay test

The replay runner requires an active session before any commands can
run. Move the screenshot after the open command that creates the
session.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: Linux CI — add missing node-gtk build deps and AT-SPI2 env

- Add gobject-introspection, libcairo2-dev, build-essential for
  node-gtk native compilation
- Split AT-SPI2 registry start into its own step so it picks up
  DBUS_SESSION_BUS_ADDRESS from GITHUB_ENV
- Set GTK_A11Y=atspi, GTK_MODULES=gail:atk-bridge, NO_AT_BRIDGE=0
  to ensure GTK apps expose their accessibility tree on headless CI
- Set GSETTINGS_BACKEND=memory to avoid dconf failures
- Add node-gtk verification step to catch build failures early

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: explicitly rebuild node-gtk native module in Linux CI

pnpm install silently skips failed optional dependency builds and
the pnpm cache may not include the native binary. Force a rebuild
after install to ensure the node-gtk .node binding is compiled
against the system GI/cairo headers.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: use node-pre-gyp directly to build node-gtk from source

pnpm rebuild doesn't trigger node-pre-gyp properly for optional deps.
Run node-pre-gyp install --fallback-to-build --update-binary directly
inside the node-gtk package directory to force compilation when no
prebuilt binary exists for the current Node ABI (v127 / Node 22).

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* refactor: replace node-gtk with Python subprocess for AT-SPI2

node-gtk is a native C++ addon that requires compilation against
specific Node ABI versions and GObject Introspection headers. This
proved unreliable on CI (no prebuilt binaries for Node 22 ABI v127,
silent optional dep build failures, pnpm cache staleness).

Replace it with a Python helper script (atspi-dump.py) that uses
PyGObject — the reference GObject Introspection consumer. python3-gi
is trivially installable on any Linux distro with no compilation step.
The Node bridge spawns `python3 atspi-dump.py` and parses JSON output.

- Remove node-gtk from optionalDependencies
- Remove node-gtk.d.ts type stub
- Add atspi-dump.py (~200 lines) doing the same tree traversal
- Rewrite atspi-bridge.ts to use subprocess instead of in-process GI
- Simplify CI workflow: no more native build deps or rebuild steps

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* chore: drop pre-installed packages from Linux CI apt-get

python3-gi, gir1.2-atspi-2.0, at-spi2-core, and dbus-x11 are already
present on Ubuntu GitHub Actions runners.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* feat: surface support for Linux, unit tests, stronger CI assertions

- Allow --surface desktop and --surface frontmost-app on Linux
  (previously only macOS could use --surface)
- Add unit tests for atspi-bridge (9 tests: JSON parsing, role
  normalization, null coercion, error handling, arg forwarding)
- Add unit tests for role-map (3 tests: common roles, case
  normalization, PascalCase fallback)
- Improve .py script path resolution (walk upward instead of
  hardcoded relative paths)
- CI replay test now asserts snapshot contains calculator UI
  nodes via is-exists

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* docs: add cross-platform snapshot traversal contract

Document the shared schema, traversal rules, surface semantics, and
normalized role types that all snapshot backends (Swift, Python,
Android) must conform to. This serves as the single source of truth
when adding or modifying platform backends.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: update lockfile after removing node-gtk optional dependency

pnpm-lock.yaml still referenced node-gtk after it was removed from
package.json, causing pnpm install --frozen-lockfile to fail in CI.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: address review findings in Linux platform code

- atspi-dump.py: use ctx dict for traversal limits instead of globals,
  fix rect filter (width/height <= 0 should use `or`), add surface validation
- input-actions.ts: make sendKey scancodes required to prevent silent
  no-op on ydotool, fix ydotool longPress/swipe to use click --down/--up
- app-lifecycle.ts: use pkill -x (exact match) instead of pkill -f
- linux-env.ts: emit diagnostic warning when falling back to xdotool on Wayland

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix(ci): explicitly install all Linux a11y dependencies

Ubuntu runners may not have at-spi2-core, python3-gi, gir1.2-atspi-2.0,
or dbus-x11 pre-installed. Install them explicitly instead of assuming
they exist. Also make the verify step's tree dump non-fatal since no
apps are running at that point.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: quote multi-word role value in Linux smoke test selector

The selector parser tokenizes on whitespace, so `role=push button`
was split into two tokens causing a parse failure. Use single quotes
inside the selector: `role='push button'`.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: use valid selector keys in Linux smoke test

appName is not a valid selector key. The supported keys are: id, role,
text, label, value, visible, hidden, editable, selected, enabled,
hittable. Simplified to use label and role only.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* chore: cleanup pass — menubar warning, fix contract doc example

- snapshot.ts: emit diagnostic warning when menubar surface is
  requested on Linux (falls back to desktop silently otherwise)
- SNAPSHOT_CONTRACT.md: fix unmapped role example to use a role
  that isn't actually mapped (was "color chooser" which maps to Dialog)

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* chore: add Python bytecache to gitignore

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* feat: harden Linux platform — capability matrix, CI, error handling

P0: Add explicit Linux capability matrix with 3-way platform routing
(Apple/Linux/Android) in isCommandSupportedOnDevice. Linux now correctly
blocks unsupported commands (clipboard, rotate, scrollIntoView, etc.)
at capability level rather than throwing at runtime. Includes tests.

P0: Expand Linux CI to run typecheck + unit tests before smoke tests.
Add AT-SPI2 registry health probe with fail-fast on missing registry.

P1: Harden atspi-dump.py — arg parsing now produces JSON errors on bad
int values, and a top-level catch wraps unexpected exceptions in JSON.

P1: Add 10s per-action timeout to xdotool/ydotool input commands to
prevent indefinite hangs.

P1: Tighten smoke test selectors to calculator-specific signals
(digit labels) instead of generic role='push button'.

P2: Document Linux surface mapping, supported commands, and known
limitations in SNAPSHOT_CONTRACT.md.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: apply depth/interactive filtering to Linux snapshots

Linux snapshots were bypassing snapshotInteractiveOnly and snapshotDepth
filtering that macOS-helper gets via shapeDesktopSurfaceSnapshot. Route
Linux through the same function so snapshot -i and --depth flags work.

Renamed shapeMacOsSurfaceSnapshot → shapeDesktopSurfaceSnapshot since
it's now shared between macOS and Linux desktop backends.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* fix: address review findings — error reporting, Wayland, timeout

- app-lifecycle.ts: emit diagnostic on fire-and-forget app launch
  failure instead of silently swallowing errors
- linux-env.ts: make xdotool on Wayland a hard error instead of
  a broken fallback (xdotool doesn't work on Wayland)
- atspi-bridge.ts: increase Python subprocess timeout from 15s to
  30s for safety on slow/loaded systems with large a11y trees

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* feat: appName/windowTitle selectors, clipboard, input-action tests

Selectors:
- Add appname and windowtitle as selector keys for desktop platforms.
  Both macOS and Linux snapshots already populate these fields — now
  they're usable in selector expressions (e.g., "label=OK appname=Calc").
  Keys are case-insensitive.

Clipboard:
- Implement readLinuxClipboard/writeLinuxClipboard using xclip/xsel
  (X11) or wl-copy/wl-paste (Wayland) with descriptive TOOL_MISSING
  errors. Enable clipboard in Linux capability matrix. 7 unit tests.

Input action tests:
- Add 18 unit tests covering xdotool and ydotool code paths: press,
  right/middle click, double click, sendKey, type, scroll, swipe,
  focus, fill. Tests mock runCmd and verify correct tool + args.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

* chore: cache tool detection for screenshot/clipboard, extract get_app_info helper

Avoid repeated `which` calls on every screenshot/clipboard operation by
caching the resolved tool on first use, matching the input-action pattern.
Extract duplicated app_name/pid retrieval in atspi-dump.py into get_app_info.

https://claude.ai/code/session_01H9hrmueNF5pcBM8JeX81mT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-04 13:14:04 +02:00
Michał Pierzchała 606042f24e 0.11.7 v0.11.7 2026-04-02 12:37:11 +02:00
Michał Pierzchała d437efe079 feat: generalize perf sampling for Apple app sessions (#351)
* feat: generalize perf sampling for Apple app sessions

* fix: report physical ios perf as unsupported

* refactor: simplify Apple perf sampling flow

* docs: refresh debugging skill guidance
2026-04-02 12:36:27 +02:00
Michał Pierzchała f2b0262abc 0.11.6 v0.11.6 2026-04-02 12:09:56 +02:00
Michał Pierzchała cd44582d40 fix: tighten dogfood snapshot and session UX (#350)
* fix: tighten dogfood snapshot and session UX

* fix: improve iOS simulator network dump recovery

* fix: honor simulator device set in iOS log recovery
2026-04-02 10:02:34 +02:00
Michał Pierzchała b4cfe3b638 fix: harden Android network dump recovery (#348)
* fix: harden android network dump recovery

* refactor: centralize app log network recovery

* fix: only mark android app logs active after attach
2026-04-02 07:59:54 +02:00
Michał Pierzchała 413f67cdba feat: add Android perf cpu and memory sampling (#349)
* feat: add Android perf cpu and memory sampling

* fix: degrade Android perf metrics individually
2026-04-02 07:55:19 +02:00
Michał Pierzchała 0bdfde1d95 0.11.5 v0.11.5 2026-04-01 21:34:28 +02:00
Michał Pierzchała ab30308989 refactor: simplify Android snapshot hinting pipeline (#347)
* refactor: simplify android snapshot hinting

* refactor: clarify android snapshot source mapping
2026-04-01 21:34:05 +02:00
Michał Pierzchała 5e788f6534 Refactor command handlers into specialized functions (#346)
* fix: document magic thresholds, fix BFS perf, and add edge-case tests

Address code review findings from #345:

- Document all undocumented heuristic constants across 11 files with
  rationale comments (freshness windows, retry delays, stale detection
  thresholds, safe-band zones, viewport-sized checks, scroll indicator
  boundaries, network log scan radii, nav subtree detection thresholds)
- Fix O(n²) BFS in ui-hierarchy.ts findScopeNode — replace shift() with
  index-based queue traversal
- Remove unused variable in ios/devices.ts listAppleDevices
- Document bundletool cache thread-safety assumption in app-lifecycle.ts
- Add 7 edge-case tests to mobile-snapshot-semantics.test.ts: zero-width
  viewport, zero-height viewport, negative coordinates, exact boundary
  visibility (both visible and outside cases)
- Add 2 boundary-condition tests to output.test.ts for nav subtree
  detection thresholds (below node floor, below duplicate floor)

All 1112 tests pass.

https://claude.ai/code/session_014aYgMag5ziyhXZoXcP9a7i

* refactor: decompose large handler functions for readability

Extract handler functions from three monolithic files:
- dispatch.ts: 13 command handlers from 786-line switch statement
- request-router.ts: split executeSessionRequest into focused helpers
- session-observability.ts: split into per-command handler functions

https://claude.ai/code/session_014aYgMag5ziyhXZoXcP9a7i

* test: add malformed snapshot data coverage for buildSnapshotState/buildSnapshotVisibility

Closes the remaining acceptance gap in #345: tests for undefined nodes,
sparse node fields, filtered-vs-unfiltered comparisonSafe semantics,
raw/macos-helper backend bypass, and scroll-hint visibility detection.

https://claude.ai/code/session_014aYgMag5ziyhXZoXcP9a7i

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-01 21:32:55 +02:00
Michał Pierzchała 6ec465a3d7 fix: preserve android snapshot visibility hints (#343) 2026-04-01 21:01:13 +02:00
Michał Pierzchała 7df452b3b5 feat: add rotate command for iOS and Android (#344)
* feat: add device rotation command

* fix: simplify rotate command handling
2026-04-01 20:34:56 +02:00
Michał Pierzchała 8df45b69a8 fix: make snapshot refs visible-first (#337)
* fix: make snapshot refs visible-first

* fix: handle zero-height visible rects

* refactor: simplify scrollintoview success handling

* feat: hint hidden scroll content in snapshots

* refactor: simplify snapshot output helpers

* feat: add hidden scroll-area hints to snapshots

* refactor: keep scroll containers in interactive snapshots

* perf: reuse Android snapshot tree for scroll hints

* refactor: trim hidden scroll hint scope

* refactor: unify mobile visible-first snapshot semantics

* fix: suppress noisy system scroll-container labels

* refactor: unify scroll indicator heuristics

* refactor: trim android hinting overhead

* fix: avoid viewport-sized ancestor promotion for ref taps

* refactor: dedupe viewport helpers and clarify hint naming
2026-04-01 19:00:02 +02:00
Michał Pierzchała 904be86019 fix: serialize first-session open requests per device (#341) 2026-04-01 18:53:27 +02:00
Michał Pierzchała 63423dacaa fix: harden iOS simulator automation stability (#340)
* fix: harden iOS simulator automation stability

* refactor: simplify automation hardening follow-ups
2026-04-01 17:57:52 +02:00
Michał Pierzchała 3d736ebba1 docs: use GIF for README video (#339)
* update readme

* chore: update demo link

* chore: use gif
2026-04-01 16:40:08 +02:00
Michał Pierzchała fe27c50408 chore: update demo link 2026-04-01 16:16:44 +02:00
Michał Pierzchała cf34583f47 fix: make Android snapshot freshness recovery internal (#335)
* feat: add --wait-stable for Android AX tree and --first/--last for find

Address the #1 token efficiency issue on Android: stale accessibility
trees after navigation. `snapshot --wait-stable <ms>` polls until two
consecutive uiautomator dumps match (tree stabilized) or the timeout
expires, eliminating retry loops caused by AX lag after screen transitions.

Also adds `find --first` / `find --last` flags to disambiguate when
multiple elements match, avoiding the fallback to raw snapshot +
coordinate taps that burned 4-6 extra tool calls.

https://claude.ai/code/session_01FzX5t9qATyT9iWnYjssShC

* cleanup: simplify find disambiguation and tighten flag descriptions

- Use consistent array reassignment for --first/--last instead of
  .length mutation
- Inline FIND_DISAMBIGUATE_FLAGS (only 2 entries, no reuse)
- Shorten --wait-stable usage description

https://claude.ai/code/session_01FzX5t9qATyT9iWnYjssShC

* docs: add flag plumbing checklist and --wait-stable/--first/--last guidance

Add a 7-step checklist to AGENTS.md for adding new CLI flags — this was
the main non-obvious cost in the implementation (7 files for one flag).

Update exploration skill to recommend --wait-stable for Android AX
staleness recovery and --first/--last for ambiguous find matches.

https://claude.ai/code/session_01FzX5t9qATyT9iWnYjssShC

* docs: improve skill clarity for weaker models

- Split "Most common mistake" into three labeled subsections (stale
  refs, Android AX lag, React Native overlays) so each is scannable
  independently
- Convert Android AX recovery from prose into a numbered list
- Add --wait-stable to debugging.md for consistency with exploration.md
- Replace vague "meaningful UI changes" with concrete triggers
- Tighten QA recovery sentence that was getting unwieldy

https://claude.ai/code/session_01FzX5t9qATyT9iWnYjssShC

* fix: make Android snapshot freshness recovery internal

* fix: tighten Android freshness baselines

* docs: clarify Android freshness tradeoffs

* docs: clarify empty interactive freshness warning

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-01 14:22:39 +02:00
Michał Pierzchała 31b80ff436 docs: add demo video to the repo (#338)
* docs: add demo video to the repo

* update readme
2026-04-01 12:34:24 +02:00