Repository navigation
0.0.87
Added
- feat(mcp): return installApp as an MCP task (Tasks extension) (#13089)
- feat(mcp): return executePlan as an MCP task (Tasks extension) (#13088)
- feat(gestures): report velocityPxPerSecond on swipeOn (symmetry with swipeAt) (#12968) (bot-filed, routine:tracker-hygiene)
- prototype request: canonicalize bound numbers on Android like the host and iOS (#12843) (android)
- prototype(android): automatic adb reverse for localhost ports in via: "device" requests (#12530) (android, daemon)
- prototype(android): request action runtime with a Retrofit device client (#12528) (android, dependencies)
- daemon: host-proxied HTTP executor for prototype request actions (via: "host") (#12527) (daemon)
- prototype(ios): persisted prototype storage in the prototype agent and viewer app (#12526) (ios)
- prototype(android): persisted prototype storage in CtrlProxy (#12525) (android)
- prototype spec: request action, statusKey lifecycle and limits behind prototype_network_v1 (any host, no allowlist) (#12523)
- prototype spec: storage block and re-show precedence behind prototype_storage_v1 (#12522) (needs-decision)
- prototype(ios): runtime for setData, appendData and removeData (#12521) (ios)
- prototype(android): runtime for setData, appendData and removeData (#12520) (android)
- prototype spec: setData, appendData and removeData actions behind prototype_data_actions_v1 (#12519)
- prototype tool: save, listSaved and deleteSaved actions for home-screen prototypes on Android (#12267) (android)
- prototype(android): pinned-shortcut publisher — requestPinShortcut with the prototype's label and adaptive icon, update and disable (#12265) (android, needs-device-verify)
- prototype(android): SavedPrototypeActivity — render a saved prototype in an activity with a standalone lifecycle and offline event replay (#12264) (android, needs-device-verify)
- prototype tool: save, listSaved and deleteSaved actions for home-screen prototypes on iOS simulators (#12257) (ios, needs-device-verify)
- prototype(ios): host installer — copy the viewer template, rewrite bundle id/name/icon, re-sign, install, write data (#12256) (ios, needs-device-verify)
- release: ship the prototype viewer template with a pinned checksum; resolve, download and cache it (#12255) (ios, release engineering, needs-device-verify)
- feat(prototype): rich text — styled and tappable
spansin atextnode (#12072) (android, ios, needs-device-verify) - feat(prototype): pager options — vertical axis, peek, page spacing, fixed page size; Material carousel (#12071) (android, ios, needs-device-verify)
- feat(prototype): wrapping and grid layout —
flowandgridcontainer nodes (#12070) (android, ios, needs-device-verify) - feat(prototype):
searchBarnode bound to a query key, with an expanded results view (#12069) (android, ios, needs-device-verify) - feat(prototype): screen navigation —
stacknode with push/pop actions, transitions and back (#12068) (android, ios, needs-device-verify) - feat(prototype): menus —
menunode (overflow, context) andselectexposed dropdown (#12067) (android, ios, needs-device-verify) - feat(prototype):
textFieldoptions — label, outlined variant, icons, supporting text, keyboard type, secure, multiline (#12066) (android, ios, needs-device-verify) - feat(prototype): gestures beyond tap —
onLongPress,onDoubleTap, row swipe actions, pull-to-refresh (#12065) (android, ios, needs-device-verify) - feat(prototype):
emit.context— payload values bound to state, repeat item and data at tap time (#11678) (android, ios, needs-device-verify) - feat(prototype): declarative input
checks, field error display, andenabledWhenfor controls (#11676) (android, ios, needs-device-verify) - feat(prototype): bring back a coordinated
patchaction — revisioned data/state ops andreplaceNode, no full rebuild (#11675) (android, ios, needs-device-verify) - migrate(mcp): adopt SDK v2 server/client + stateless core (gates Tasks) (#4678) (needs-human, needs-decision)
Changed
- chore(lint): track named oxlint-enable closures of a bare oxlint-disable in the suppression scan (#12973) (devxp)
- chore(lint): let a file-wide oxlint-disable be narrowed to a block without --allow-grow (#12972) (devxp)
- test(session-broker): share one retry deadline across open and admit in the admission contender (#12971) (flaky test, testing)
- refactor(daemon): design a host port to move startReleaseTeardown orchestration out of SessionManager (#12862) (daemon)
- refactor(daemon): split getSessionInternal into pure find and explicit expireIfDue (#11798 S8) (#12581) (daemon)
- playground: audit Android 17 behaviour changes for targetSdk 37 (background audio, large-screen resizability, reflection) (#12275) (android, testing)
- ctrlproxy: replace non-SDK reflection (UserHandle.myUserId, DeviceStateManager) with public APIs before targeting API 37 (#12271) (android, needs-device-verify)
- refactor(junit-runner): table-drive daemon flag forwarding; replace static test seams with injected collaborators (#11882) (android, testing)
- chore(scripts): guard against unreferenced scripts and collapse the boundary-check wrappers (#11874) (devxp, dead-code)
- test(lint): replace regex/indexOf source-text assertions with AST guards or behaviour tests (#11867) (testing)
- test(daemon): extract builders for devicePool.test.ts and sessionManager.test.ts and split the monoliths (#11866) (testing)
- test(fakes): make FakeAdbClient a full AdbExecutor and merge the two simctl fakes (#11864) (testing)
- refactor(db): validate behaviour-driving JSON columns on read (#11859) (database)
- refactor(features): merge split feature directories and remove vestigial single-implementation interfaces (#11856)
- refactor(android-emulator): split AndroidEmulatorClient along its existing interfaces (#11851) (android)
- refactor(observe): hoist the remaining copied client methods into DeviceServiceClient (#11845)
- refactor(observe/android): route the remaining hand-rolled CtrlProxy requests through sendCommand (#11844) (android)
- chore(action): name the remaining inline retry counts and settle sleeps (#11843)
- refactor(observe): break ObserveScreen.executeSingleDisplay into capture, enrich and reconcile stages (#11841)
- refactor(sendKeys): split DefaultSendKeysCommandExecutor into per-mode typers and an ImeSpan service (#11840)
- chore(lint): typed raw-node accessor so no-raw-selector-field-read needs no suppressions (#11839)
- refactor(adb): give AdbExecutor.executeCommand and the hierarchy readers an options object (#11836) (android)
- refactor(observe): move waitFor/settle evaluation out of observeTools.ts (#11828)
- refactor(system-tray): move system-tray domain logic out of src/server (#11826)
- refactor(tools): typed defineTool so handler args are inferred from the zod schema (#11824)
- refactor(server): split toolRegistry.ts into registry plus named pipeline-stage modules (pure move) (#11822)
- refactor(daemon): classify proxy errors by code, not message text (#11821) (daemon)
- refactor(daemon): put ide/*-named daemon lifecycle methods and HTTP heartbeat on the shared handlers (#11819) (daemon)
- refactor(daemon): route control-socket input/* and ide/* through a method registry with zod params (#11813) (daemon)
- refactor(daemon): give DaemonManager a dependency object and separate the restart variants (#11809) (daemon)
- refactor(devicePool): narrow collaborator ports so they cannot mutate pool entries or take the assignment mutex (#11804) (daemon)
- refactor(daemon): extract plan-label registry and liveness lease/policy out of SessionManager (#11797) (daemon)
- refactor(daemon): replace SessionManager's positional constructor defaults with an options object (#11796) (daemon)
- refactor(daemon): move restore-on-release into SessionDeviceStateRestore (#11795) (daemon)
- refactor(daemon): one restore-queue implementation for clock, rotation and screen-reader (#11794) (daemon)
- refactor(daemon): extract device cleanup quarantine out of SessionManager (#11793) (daemon)
- refactor(daemon): delete write-only SessionManager.sessionDeviceMap (#11792) (dead-code, daemon)
- build(detekt): enable coroutines, exceptions, empty-blocks and complexity rule sets with a baseline ratchet (#11791) (android, devxp)
- refactor(arch): extend the import-direction ratchet to models, db, devices, ctrlProxy and features -> server (#11789)
- chore(lint): promote fully burned-down ratchet rules from warn to error (#11788) (devxp)
- test(lint): ratchet
as unknown asin test/ (about 2,430 today, ungated) (#11786) (testing) - chore(lint): gate inline oxlint-disable directives with a per-file, per-rule count ratchet (#11785) (devxp)
- chore(lint): per-file line-count ratchet so decomposed files cannot regrow (#11784) (devxp)
Fixed
- tapAt (ios): coordinate tap right after pinchOn is rejected with Stale frame context (#13437)
- ctrlproxy(android): GestureStreamCoordinator drops dragPath waypoints past the 64-entry queue cap (#13280)
- doctor: Device Ownership Agreement check never sees exec owners and treats a reused PID as a live lock holder (#13279)
- sendKeys eventAll 4096-char pre-API-31 chunk exceeds the 15s ADB timeout; 6000-char run fails on API 30 (#13172)
- sendKeys (Android IME): a 3 s 'ime list' timeout during restoration quarantines the device and automatic recovery cannot clear it (#13158) (android)
- fix(record): recordDeviceGestures drops pen digitizers and pressure (#13101) (android)
- perf(daemon): stateless MCP endpoint adds ~15-20 ms to every daemon-bound call (p50 3 ms -> 21 ms) (#13068)
- bug(daemon): cancelling a long tool call over the control socket no longer stops it on the device (loopback notifications/cancelled lacks the session-key header) (#13067)
- Stateless daemon (slice L files): unaddressed review findings from #13047, #13049, #13053 (#13062)
- iOS prototype patch_prototype: /data conflicts unguarded and nonStateBytes baseline not refreshed (review of #13028) (#13061) (needs-device-verify)
- broker budget: unbound ambroker iOS sims that are Booting/Shutting Down are treated as powered off (review of #13030) (#13060)
- pinch: unbounded rotationDegrees defeats the 10-degree arc approximation and overflows NSInteger on iOS (review of #13037) (#13059)
- desktop McpHttpClient generates a new session key per client but AutoMobileContent builds a client per action (review of #13046) (#13058)
- prototype: pin the revision a show reports (Android 1, iOS 0 after first show) (#13040) (needs-device-verify)
- swipeOn durationMs is not honored on TalkBack semantic scroll or clamped iOS XCUICoordinate routes (#12987) (needs-device-verify)
- Session broker: stdin EOF can win the shutdown race and mask execution-owner loss (failed/session_owner_exited recorded as released) (#12986)
- Session broker proxy acquisition: unheld-session release can stall past the acquisition deadline (#12985)
- Session requirements: Android tie-break prefers google_apis flavor over host-runnable ABI (#12984)
- prototype deleteSaved removeIcon: clear-shortcuts ignores the active work/secondary profile (--user) (#12983)
- fix(record): recordDeviceGestures normalizes touches with the start-of-recording geometry after a rotation (#12880) (android)
- fix(record): recorded swipeAt keeps raw pixel endpoints without geometry provenance (#12878)
- Owner death after proxy release records
released, not terminalsession_owner_exited(#12791) - proxy-session close hangs 240 s after a failed attempt and races after --resume (#12790)
- Live cross-client probe returns device_outside_bound_session, harness/brief expect device_outside_broker_grant (#12789)
- Broker cannot resolve an installed Android 17 / API 37 image (catalog_metadata_invalid) (#12788)
- Follow-ups from post-merge review of #12651–#12693: weakened test assertion, harness helpers, stale log text (#12721)
- setAppPermissions (iOS): establish and verify full Photos access through the direct simulator grant API (#12317) (ios)
- getAppPermissions (iOS): Photos reports granted while native read/write authorization is not determined (#12316) (ios)
- bug(ctrlproxy prototype): an idle fullscreen prototype renders ~87 frames per second; every window event relayouts the window (#12137) (android, performance, needs-device-verify)
- sendKeys (Android): default IME typing reports an error in a focused MultiAutoCompleteTextView; a11y retry succeeds (#10385) (android, needs-device-verify)
Security
- prototype(ios viewer): attach a host to a viewer launched from the home screen (#12258) (enhancement, ios, needs-device-verify)
Other
- Session broker: retain grant proof until client acknowledgement (crash before first proof capture) (#13474)
- Review findings: iOS CtrlProxy SDK hierarchy envelope and swipe route reporting (#13319)
- Review findings: release artifact-capability gate and api-dump checks (#13318)
- prototype-agent: commitDataWrite leaves the spec size baseline (nonStateBytes) stale (#13298)
- bug(daemon): two keyless requests sharing a JSON-RPC id make a header-less notifications/cancelled cancel the newer one (#13294)
- DaemonClient unit tests read the host's real daemon PID file, so results depend on host state (#13293)
- ios/sdk-wire API gate: assert @_exported import and pin all shared DTO encodings; scalar pin test takes ~10s (#13178)
- iOS SdkEndpointResolver.health(at:) hardcodes "health" instead of SdkRoute.health.path (#13177)
- flake: ScreenshotPathProtection contract 'run one at a time, in order' polls a fixed 1000 ticks for real async I/O (#13167)
- TaskSessionBindings: timed-out binding can publish after close, poll failure does not refresh expiry, bound task leaks its expiry timer (review findings on #13155) (#13166)
- swipeOn/iOS swipe duration reporting: clamp and velocity ignore the dispatch route; TalkBack display swipe omits durationExplicit (review findings on #13072, #13137) (#13145) (needs-device-verify)
- TaskSessionBindings: forgets binding on non-terminal errors, never expires abandoned tasks, close does not drain bindings (review findings on #13140) (#13144)
- recordDeviceGestures: end a contact when its slot's tracking ID is replaced directly (#13129)
- IOSCtrlProxyManager.flattening test spawns real xcrun simctl get_app_container on macOS (#13112)
- mcp: default-off tools (pinchOn, prototype) are callable but unlisted, and setToolEnabled does not say where to find their names (#13092)
- feat(gestures): stylus tool type on tapAt and straight swipeAt (Android, fixed pressure) (#13081)
- prototype request via device: cleartext http://10.0.2.2 times out after 10s on API 37 (https works) (#13018) (needs-device-verify)
- broker: stale amslot/ambroker devices and --protect devices count as orphaned and exhaust binding budget (#13017)
- pinchOn rotation with equal start/end distances still zooms transiently (straight-line finger paths) (#12997) (needs-device-verify)
- multiTouch: not registered as a coordinate action (no caller-stale display fence) and rejects explicit swipe distances under 20 px (#12995) (needs-device-verify)
- dragPath: lost start acknowledgement leaves the streamed gesture active; default-display route drops the display fence (#12994)
- swipeOn: display + fromEdge validates the unresolved content direction (wrong-way error before dispatch) (#12992)
- prototype(android): request action has no transport in SavedPrototypeActivity (ends as a network error) (#12970) (android, bot-filed, routine:tracker-hygiene)
- chore(lint): oxlintDisableScan exits without a message on a source file with a parse error (#12969) (bot-filed, routine:tracker-hygiene)
- bug(devicePool): pool-ownership property sweeps fail on main in deferred-rebind-cleanup and other profiles (#12832) (daemon)
- record(android): a touch at the digitizer maximum is recorded at exactly the display size, which replay rejects as out of bounds (#12785)
- feat(gestures): swipeAt display support (swipe on a selected panel or display) (#12784)
- ci: Kotlin Code Coverage failed once on a partially restored Gradle dependency cache (ArtifactNotFoundException) (#12706)
- feat(gestures): swipeOn durationMs override for precise fling/velocity control (#12538)
- feat(gestures): edge-anchored swipes (start a swipe at a screen or panel edge) (#12537)
- pinchOn: verify and document rotation without zooming (distanceStart == distanceEnd + rotationDegrees) (#12536)
- feat(gestures): multi-finger tap, long press and swipe/scroll (2–5 fingers) (#12535)
- feat(gestures): drag along a polyline path with segment timing and an initial hold (#12534)
- feat(gestures): swipeAt — coordinate-to-coordinate swipe tool (#12533)
- docs + manual-test: prototype data, storage and network acceptance scenario (#12531) (documentation, testing)
- Manual verification: Python MCP stdio close with two independent clients on two Android emulators (#11951) (android, testing, needs-device-verify, daemon)
- research(daemon): decide whether the in-process loopback HTTP hop for socket-forwarded calls should remain (#11820) (research, daemon, needs-decision)
- startTestRecording MCP tool lacks the unheld-start refusal; cancelled ide/* mutations stamp idle before the cancel check (#11716)
- tapOn: result message drops the selected label, and the diff pairs unrelated switches across screens by resource-id (#11638) (bot-filed, routine:dogfood)
- Action responses on 0.0.84 still ship layoutWarnings diffs, skeleton plus added/removed, and bounds-only container changes on every tap (#11637) (bot-filed, routine:dogfood)
- CI: nightly macOS jobs (XCTestRunner Simulator Tests, Thread Sanitizer, BATS) give no GitHub-visible signal since they moved to CircleCI (#11615) (ci)
- flake-sentinel:
mainred across the On-Merge wave —Node Unit Tests (windows-latest)deterministic on new managed-slots test files (recurrence of closed #10926) + companion On-Merge gates (ktfmt / Validate Shell / BATS / Kotlin Code Coverage) (#11293) (ci, bot-filed, needs-human, routine:flake-sentinel)
CtrlProxy APK
SHA256 Checksum: 65e6c420b48b9af28377df9b68073b6151567a90059cefb33e677a5310cb6544
Download the APK from the release assets below.
CtrlProxy iOS IPA
SHA256 Checksum: 0d5bc367976e67475400fd85a84b85c2e51bd4efa31060bfb43fbba47c4fab7c
Download the IPA from the release assets below.
video-server jar
SHA256 Checksum: 943adc314a3a573108619cba3326b2a07ae42c9d631b15bb284e480115e639ab
Download automobile-video.jar from the release assets below.
macOS screen-capture-helper
SHA256 Checksum: 02034a9b3973240097b853c4281b0debbd979195ab256c825f2d1a207a86e64b
Download screen-capture-helper-macos-universal.zip from the release assets below.
iOS simulator prototype agent
SHA256 Checksum: 9f329aea7173a371c180364849d5823fd12f96c0b5716953b68e255de1fb5b41
Download AutoMobilePrototypeAgent.dylib (universal arm64 + x86_64, ad-hoc signed) from the release assets below.
iOS simulator prototype viewer
SHA256 Checksum: 60ac1b236434ac112aa293efcce258123db2a6f341bc6f809438f0b375b97fd9
Download AutoMobilePrototypeViewer.zip (universal arm64 + x86_64, ad-hoc signed) from the release assets below.
macOS network-filter
SHA256 Checksum: b177bccc11732773f7df2bfc0c398924739a92eca2fef2a5e822a3098561511f
Download automobile-network-filter-macos-universal.zip from the release assets below.
Desktop App
Native installers are attached below: macOS .dmg (signed & notarized), Windows .msi, and Linux .deb.