Commit Graph

35 Commits

Author SHA1 Message Date
Michał Pierzchała fa1b0b7c8a docs: configure agent skill conventions (#871) 2026-06-25 11:02:37 +02:00
Michał Pierzchała d8e6bb7aa7 fix: add web viewport control and screenshot aliases (#865)
* fix: add web full-page screenshots

* fix: add web viewport command and screenshot aliases

* fix: address viewport CI regressions
2026-06-24 19:35:03 +02:00
Michał Pierzchała d47cd30117 feat: add agent-device proxy command (#844) 2026-06-23 17:20:08 +02:00
Michał Pierzchała d7beb52768 feat: expose web network dump through agent-browser (#838)
* feat: expose web network dump through agent-browser

* fix: reduce web network mapper complexity

* fix: gate web network headers by include mode

* test: assert compact web network summary

* refactor: simplify web network dump mapping

* refactor: trim web network coverage
2026-06-22 14:40:25 +02:00
Michał Pierzchała c6fd3dc972 test: add live web platform smoke (#832)
* test: add live web platform smoke

* test: harden web smoke cleanup
2026-06-21 13:05:51 +02:00
Michał Pierzchała d05cfc727b feat: manage web backend setup (#833) 2026-06-20 11:44:00 +02:00
Michał Pierzchała 5c83fe4e50 fix: improve daemon diagnostics and remove compact snapshots (#786)
* fix: improve daemon startup diagnostics

* perf: relax query-sweep recovery budget

* fix: make compact snapshot flag a no-op

* fix: remove compact snapshot mode

* test: align tvOS remote provider expectation

* test: drop compact snapshot progress target
2026-06-12 17:32:56 +02:00
Michał Pierzchała 4142daa0c3 docs: update internal agent guidance (#789) 2026-06-12 14:58:18 +02:00
Michał Pierzchała fa1c1d55da refactor: localize command surface modules (#772)
* refactor: localize command surface modules

* refactor: localize command runtime modules

* refactor: tighten localized command exports

* refactor: address command localization review

* refactor: deepen batch command policy

* refactor: split provider progress model

* refactor: collapse command client facets

* refactor: run progress metrics as TypeScript

* refactor: remove obsolete command shims

* fix: update localized snapshot output import

* fix: preserve debug command localization
2026-06-12 14:02:04 +02:00
Michał Pierzchała fa8cce37d1 refactor(ios): snapshot capture plans with a structured quality verdict (#783)
* refactor(ios): snapshot capture plans with a structured quality verdict

Implements ADR 0004's explicit-strategies decision as architecture
(candidates 1+2 of the snapshot pipeline review):

- Snapshot backend seam: three adapters (recursive tree, query sweep,
  private AX) behind one captureWithBackend dispatch. Each strategy
  declares its chain as data (regular: tree→queries→private-ax,
  compact: queries→private-ax, raw: tree→private-ax) and one plan
  runner walks it under a 20s umbrella budget so chained recovery can
  never stack past the 30s main-thread watchdog. Terminal policy is
  per-plan: raw rethrows AX failures (diagnostics preserve errors),
  interactive fails closed with runnerFatal invalidation.
- Single quality classifier: one sparsePayloadReason predicate (with
  reason codes), one collapsed-leaf detector, replacing the three
  divergent sparse detectors (Swift structural, daemon count==1, CLI
  count<=3) that each patched a different failure shape.
- Structured snapshot quality verdict on the wire (state, backend,
  reason, reasonCode, effectiveDepth, collapsedLeafIndexes): the daemon
  and CLI render warnings from it instead of re-deriving degradation
  from node shapes; budget starvation is no longer blamed on the app's
  accessibility. Legacy runner messages and daemon-side detectors stay
  behind a verdict-absent gate for mixed-version compat.
- The verdict surfaces in --json (snapshotQuality) for agents; the
  generic sparse CLI hint is suppressed when a verdict explains it.

Threading the verdict exposed two more hand-copy field drops
(captureInteractionOutcomeAwareSnapshot, serializeSnapshotResult,
client response mapping) - now carried alongside warnings everywhere.

Verified live: Settings healthy (tree, no warnings), Settings compact
under load (recovered/private-ax/budget), production login (sparse
best-effort with honest warning), collapse fixture (healthy +
collapsedLeafIndexes -> @ref warning), Bluesky Home (recovered/
private-ax, 24 nodes in 2s). Full unit suite 2327 passed, fallow clean,
runner builds.

* fix(ios): correct recovered-snapshot viewport and private-AX scope semantics

Review follow-ups on the capture-plan refactor:

- The query-sweep synthetic root doubles as the daemon's viewport
  (find.ts prefers on-screen matches inside nodes[0].rect), but it was
  built from candidate bounds, so off-screen controls below the screen
  could inflate it and win duplicate-label resolution. The root now
  uses the real finite viewport, falling back to candidate bounds only
  when viewport capture failed.

- The private-AX backend applied --scope as a per-node text filter,
  hiding the matched container's children — diverging from regular
  snapshot scope semantics and contradicting the depth-cap hint that
  recommends scoped re-runs. Scope now selects the matched subtree:
  descendants inherit the match and only the normal option filters
  apply to them (in-bundle test covers a non-matching descendant).

Verified live on Bluesky Home: scope homeScreen returns the 52-node
subtree including non-matching descendants; compact root rect equals
the screen (0,0,402,874).

* fix(ios): fail closed on interactive AX failure, stamp fatal verdict, validate parser

Three review findings on the capture-plan terminal path:

- P1: the fail-closed guard required `best == nil`, but the query-sweep
  tier always returns a synthetic-root sparse payload that sets `best` —
  so an interactive recursive-tree AX serialization failure that no
  backend recovered returned a sparse snapshot instead of invalidating
  the cached target. Reaching the terminal already means no backend
  produced a usable tree, so the sparse `best` must not suppress the
  fail-closed path. Extracted the decision into a pure, unit-tested
  `resolveSnapshotPlanTerminal` (closes the terminal-ordering testability
  gap the architecture review flagged).
- P2: `snapshotAccessibilityUnavailable` returned a payload with no
  `snapshotQuality`, leaving one planned sparse result on the
  legacy-message path. It now carries a sparse/ax-rejected verdict like
  every other planned snapshot, so downstream sparse handling keys off
  the verdict.
- P2: `readSnapshotQualityVerdict` cast any string state/backend into the
  union, so a malformed object suppressed the legacy node-shape
  detectors. State and backend are now validated against their unions
  (unknown → verdict-absent → legacy detectors run); an unknown
  reasonCode is dropped rather than rejecting the whole verdict, so a
  forward-version runner still yields a usable verdict.

Unit-covered: Swift resolveSnapshotPlanTerminal matrix + fatal-verdict
assertion; TS parser accept/reject/forward-compat. Full suite 249 files
/ 2449 tests, fallow, lint, runner build green.
2026-06-12 12:25:40 +02:00
Michał Pierzchała 3a02e514e1 refactor(ios): consolidate series batching onto the sequence runner command (#768)
* refactor(ios): consolidate series batching onto the sequence runner command

Closes #767

Routes every Apple multi-press variant (plain, double-tap, hold, jitter)
and swipe series through budget-chunked sequence requests, retiring the
daemon-side tapSeries and dragSeries senders:

- Add a doubleTap step kind to the sequence allowlist on both ends,
  mirroring the retired tapSeries doubleTapAt branch.
- The single doubleTap interactor sends a one-step sequence and parses
  the result, surfacing step failures as errors.
- Swipe series unroll ping-pong daemon-side into per-step endpoints;
  the runner's coordinate-drag path ignores durationMs exactly as the
  daemon-sent (non-synthesized) dragSeries did.
- Extract runIosSequenceChunks so press and swipe share the chunking,
  aggregation, and global step-index rebasing.
- Keep tapSeries/dragSeries runner handlers for wire compatibility with
  older daemons, annotated like interactionFrame; remove both from the
  preflight-skip allowlist (daemon never sends them) and update ADR
  0005 / protocol-optimizations docs.

This also closes the latent watchdog exposure where press --count N
--interval-ms M routed to tapSeries and executed all pauses inside one
30s-watchdog main-thread block with no chunking.

Behavior note: plain tap series now use the synthesized HID tap path on
iOS non-tv (with runner-side tapAt fallback), matching the individual
tap command instead of the retired tapSeries' XCUICoordinate taps.

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

* refactor(ios): drop dead series wire surface from the daemon

- Remove chunkRunnerSequenceSteps: superseded by the budget-aware
  chunker; no production callers remained.
- Remove tapSeries/dragSeries from the RunnerCommand union along with
  their orphaned fields (count, intervalMs, doubleTap, pauseMs,
  pattern) and protocol fixtures: this type is the send surface of the
  current daemon, which no longer sends either command. The Swift
  runner keeps serving both for wire compatibility with older daemons.
- Retarget the ready-mutation preflight test from tapSeries to
  sequence.

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

* refactor(ios): remove retired series and frame wire commands entirely

Drops the runner-side wire compatibility for tapSeries, dragSeries, and
interactionFrame now that no daemon path sends them (series fuse into
sequence since this branch; interactionFrame was fused into scroll in
#760):

- Swift: delete the three handler cases, performDragSeries, runSeries
  (no remaining callers), the CommandType enum cases, journal-retention
  and traits entries, and the Command fields (count, intervalMs,
  doubleTap, pauseMs, pattern) that existed only for them. The
  never-sent synthesized dragSeries branch goes with it.
- TS: drop interactionFrame from the RunnerCommand union and
  isReadOnlyRunnerCommand, and its protocol fixture.
- Update stale perf scenario labels referencing the retired commands.

Verified dead before removal: no dynamic command construction anywhere
(runner-command-recovery only echoes in-flight command ids), no
raw-string references in Swift, no docs references. Helpers shared with
live paths (synthesizedDragAt, doubleTapAt, keyboardAvoidingDragPoints,
sleepFor) all retain callers.

Compat: an old daemon paired with a runner built from these sources
gets a CommandType decode rejection; the source-fingerprint check
rebuilds a matching runner on the next session.

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-11 14:08:30 +02:00
Michał Pierzchała e6e2baf30f perf(ios): add lifecycle-safe runner sequence command for hot press series (#764)
* perf(ios): add lifecycle-safe runner sequence command for hot press series

Adds a narrow 'sequence' runner command that batches an explicit
allowlist of coordinate steps (tap, longPress, drag) into one
lifecycle-tracked request with stop-on-first-failure and small bounded
per-step results. iOS press series with hold/jitter now issue one
sequence request per ~20-step chunk (also budgeted to stay under the
runner's 30s main-thread watchdog) instead of one request per press.
Sequence responses are journaled and retained, so lost-response recovery
returns observed results without replaying the gesture sequence.

Closes #669

* fix: perform every press in direct press series

runDirectPressSeries guarded the awaited interaction itself with ??=,
so presses 2..N were silently skipped once the first result was kept
(affects Android series and doubleTap series; introduced in #512).
The kept-first-result shape is preserved.

* chore: unexport internal sequence chunk budget constant

* perf(ios): make sequence eligible for readiness preflight skip

Rebased onto main with #763 (healthy-mutation preflight skip) and #760
(fused scroll). Per the merge-order note, add 'sequence' to
PREFLIGHT_SKIP_ELIGIBLE_RUNNER_COMMANDS so a successful sequence earns
the next hot-command skip instead of always taking the
conservative_command path. Extend the per-family skip tests and the
allowlist enumeration in ADR 0005 and the protocol-optimizations doc.

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-11 12:50:30 +02:00
Michał Pierzchała 3780ca6ed5 perf(ios): fuse scroll frame resolution and drag into one runner command (#760)
* perf(ios): fuse scroll frame resolution and drag into one runner command

Non-tvOS scroll now sends a single mutating 'scroll' runner command. The
Swift runner resolves the interaction frame and executes the same
non-synthesized drag path, eliminating the separate read-only
interactionFrame request per scroll. The command is lifecycle-journaled
with retained response JSON so lost-response recovery returns the result
without replaying the gesture.

Closes #668

* perf(ios): make fused scroll eligible for readiness preflight skip

#763 landed the healthy-mutation preflight skip with a note that the
fused scroll command should join the allowlist once it exists. Add
'scroll' to PREFLIGHT_SKIP_ELIGIBLE_RUNNER_COMMANDS, drop the
now-resolved code note, extend the per-family skip tests, and update
the allowlist enumeration in ADR 0005 and the protocol-optimizations
doc.

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

* test: complete scroll plan parity vector mirror

Address review on the cross-language parity vectors:
- mirror the Swift pixels-plan vector (down, 120px @ 300x600) in the
  vitest suite so every vector exists in both languages
- add amount > 1 clamp and tiny-frame (2x2) vectors to both suites;
  the tiny frame engages every max(1, ...) floor and the .5 rounding
  cases where JS half-up and Swift half-away-from-zero must agree

https://claude.ai/code/session_01VokBZWESTDgcnbYwS4DkJo

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-11 12:03:53 +02:00
Michał Pierzchała 462db525cc perf(ios): skip runner uptime preflight after recent healthy mutations (#763)
Reintroduces the #662 adaptive readiness-preflight skip with guardrails
for the #702 failure modes. Recency is recorded only from healthy
(non-runnerFatal) responses to an explicit mutating-interaction allowlist
(tap, tapSeries, longPress, drag, dragSeries, swipe), scoped to the same
appBundleId, capped at a 5s freshness window, and lives on the session
object so it dies with every invalidation. Startup, no-recent-success,
stale, app-switch, and non-allowlisted commands still preflight. A
transport failure after a skip clears recency, carries the skip context
through status recovery, and never routes into restart-and-replay.

Closes #667
2026-06-11 11:46:19 +02:00
Thiago Brezinski b2e4ace12c fix: focus booted iOS simulators with Device Hub (#750)
* fix: focus booted iOS simulators with Xcode Device Hub

* fix: expose Device Hub opt-out

* test: cover Device Hub screenshot retry focus

---------

Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
2026-06-10 20:07:08 +02:00
Michał Pierzchała a0522c7bcc docs: document issue label workflow (#742) 2026-06-10 13:00:34 +02:00
Michał Pierzchała 35f54a863c fix: resolve Maestro taps from regular snapshots (#709)
* fix: resolve Maestro taps from regular snapshots

* fix: tighten Maestro snapshot compatibility

* test: align Maestro snapshot freshness fixtures
2026-06-08 18:12:09 +02:00
Michał Pierzchała 76cee982ba fix: stabilize iOS runner navigation taps (#702)
* 0.16.14

* fix: stabilize iOS runner navigation taps

* fix: recover iOS runner after AX failures

* docs: clarify AX-unavailable snapshot recovery

* test: cover synthesized ios provider taps

* test: cover iOS runner AX failure paths

* fix: clarify sparse iOS AX recovery hint
2026-06-07 11:17:27 +02:00
Michał Pierzchała aa5b07faa5 fix: keep iOS runner hot across app closes (#700)
* fix: keep iOS runner hot across app closes

* fix: keep iOS snapshots fast after relaunch

* fix: bound compact iOS snapshots on broken AX trees

* docs: clarify iOS snapshot backend strategy

* test: update Settings replay selectors

* fix: stabilize Settings replay selectors

* fix: fall back for selector interactions

* chore: simplify flat interactive snapshot query
2026-06-06 21:26:12 +02:00
Michał Pierzchała f2424f9d3a refactor: centralize daemon command registry (#693) 2026-06-05 18:34:01 +02:00
Michał Pierzchała 57cd3f3a07 perf: recover iOS runner responses by status (#661)
* perf: recover ios runner responses by status

* docs: plan ios runner protocol optimizations

* fix: clarify ios runner recovery errors

* fix: retry read-only in-flight runner commands

* refactor: split ios runner status recovery handling
2026-06-01 21:26:15 -05:00
Michał Pierzchała ae73b77b2b refactor: narrow Maestro flow runtime bridge (#626)
* refactor: narrow Maestro flow runtime bridge

* fix: address maestro replay control review

* test: guard maestro replay control boundary

* chore: trim maestro flow control cleanup
2026-05-30 16:04:38 +02:00
Michał Pierzchała 14bbcf4f69 docs: map Maestro compatibility debt (#621) 2026-05-30 13:33:56 +02:00
Michał Pierzchała d087a62d1d fix: improve Maestro Android reliability and snapshot speed (#612)
* fix: improve maestro tab target swipes

* fix: stop replay suites on pending timeout cleanup

* fix: tighten maestro compat support plumbing

* fix: resolve ios simulator url open targets

* fix: speed up Android Maestro snapshots

* fix: resolve android snapshot ci regressions

* perf: reduce android snapshot helper overhead

* docs: record persistent helper session architecture

* chore: address snapshot session review

* perf: add persistent Android snapshot helper session

* fix: stabilize Android replay interactions

* fix: stabilize Maestro visibility resolution

* refactor: simplify Android keyboard parsing
2026-05-29 22:09:18 +02:00
Michał Pierzchała 59d28e8446 refactor: add provider-first device lab tests (#542)
* refactor: add provider-first device lab tests

* refactor: tighten device lab provider seams

* test: cover provider lab contracts

* docs: record device lab harness direction

* ci: run device lab integration tests

* test: move device lab under integration

* test: extract device lab helpers

* refactor: centralize apps filter defaults

* test: drop lab-covered unit tests

* test: fold platform happy paths into device lab

* test: reuse device lab helpers

* test: move device lab to in-process harness

* test: replace session handler cases with device lab

* test: harden device lab scenario contracts

* docs: define unit test retention policy

* test: expand provider device lab coverage

* test: harden provider device lab coverage

* test: cover manifest install and runner session contracts

* chore: remove unused provider cleanup code

* test: split android find device lab scenario

* test: track provider lab architecture progress

* test: clarify provider lab roadmap progress

* test: advance provider lab session coverage

* test: move menubar click routing to device lab

* test: move menubar snapshots to device lab

* refactor: centralize screenshot flag plumbing

* refactor: colocate screenshot flag metadata

* test: cover all public commands in device lab

* test: move macos wait success to device lab

* test: drop redundant perf and diff units

* test: move push payload paths to device lab

* test: move network parsing to device lab

* test: move log cleanup to device lab

* test: move log restart and boot to device lab

* test: move ios physical boot to device lab

* test: cover perf startup in device lab

* test: extract android and ios device lab worlds

* test: trim device lab world surface

* test: split snapshot capture unit coverage

* test: deepen device lab coverage and trim handler units

* test: clean up device lab migration scaffolding

* test: report device lab public command coverage

* refactor: make Apple provider seams semantic

* refactor: tighten device inventory and Linux provider seams

* refactor: tighten request provider scoping

* refactor: add semantic macos host provider

* test: broaden device lab find coverage

* test: cover workflow flags in device lab

* refactor: promote linux input provider seam

* test: clarify device lab flag coverage

* test: classify snapshot force-full progress

* test: enforce device lab progress in ci

* test: stabilize device lab ci

* test: move packaged metro smoke to integration

* test: drop stale provider seam coverage

* test: harden provider scope regression coverage

* refactor: remove stale platform barrels

* refactor: keep linux clipboard and screenshots semantic

* refactor: move macos host tools behind provider

* fix: honor remote artifact output paths

* test: deepen runtime coverage for daemon and runner paths

* test: share loopback test helpers

* refactor: make daemon runtime importable

* fix: honor replay target metadata

* chore: tighten final device lab quality gates

* test: share device lab setup helpers

* test: remove generic apple lab fallback

* test: deduplicate device lab helpers

* chore: tighten fallow duplication signal

* refactor: share apple diagnostic helpers

* fix: detect active android ime during fill verification

* test: consolidate provider-backed integration suite

* ci: fix fallow and iOS smoke setup

* chore: consolidate cleanup after ci fixes

* test: split vitest unit and integration projects

* docs: mention MCP discovery metadata

* docs: add agent skills context pointers

* fix: close provider recording coverage gaps

* fix: restore mcp compatibility smoke

* test: cover provider edge regressions

* test: consolidate loopback helpers

* docs: remove stale provider routing reference

* fix: harden final provider review issues

* chore: defer mcp cleanup from provider refactor
2026-05-18 14:50:52 +02:00
Michał Pierzchała e84612a393 feat: docs (#7)
* feat: docs v1

* update wording

* update action
2026-02-05 15:25:52 +01:00
Michał Pierzchała d8b1800dc0 fix long-running timeouts for session app 2026-02-05 07:59:31 +01:00
Michał Pierzchała 1d6994440c perf: improve xctest backend speed dramatically and make default 2026-02-04 22:35:18 +01:00
Michał Pierzchała 460886f714 document missing device iOS support; fix missing swift 2026-02-03 20:03:15 +01:00
Michał Pierzchała a66cedd82b feat: trace 2026-02-03 09:44:16 +01:00
Michał Pierzchała ca88d60bbf feat: add hybrid backend for speed and correctness 2026-02-03 08:55:37 +01:00
Michał Pierzchała 0f90c61e7c remove rect; adjust error messages 2026-02-02 14:06:11 +01:00
Michał Pierzchała e5c77bcf5a cleanup 2026-01-31 19:57:49 +01:00
Michał Pierzchała fb53d72b63 feat: AX snapshot goes brrrr 2026-01-31 12:52:04 +01:00
Michał Pierzchała 4da4745a6c initial commit 2026-01-30 19:41:00 +01:00