Skip to content

Changelog

[v0.0.44] - 2026-07-11

Other

  • junit-runner >= 0.0.36 forces kotlin-stdlib 2.4.0 on consumers, locking out projects on older Kotlin (#3558)
  • Daemon remains healthy after observation-stream socket disappears (#3556)
  • DevicePool should validate iOS simulator liveness before assigning idle pooled UDIDs (#3553)
  • Evict Android Emulator From Pool When Process Exits or ADB Disappears (#3552)
  • CI: resolve Homebrew tap-trust warning in iOS IPA build (#3548) (ci)
  • CI: bump gradle-task-run actions off deprecated Node.js 20 (#3547) (ci)

[v0.0.43] - 2026-07-10

Other

  • Invalid observe outputSchema breaks strict MCP tools/list clients (#3542)
  • observe returns malformed/truncated JSON on occlusion-heavy screens (regression in current main) (#3539)

[v0.0.42] - 2026-07-10

Added

  • docs/observe: contentDescription waitFor predicate silently ignores textMatch (#3514) (documentation)
  • perf: getToolDefinitions() re-runs Zod->JSON-Schema conversion for every tool on every tools/list (#3426) (performance)
  • perf: ObserveElementsBuilder makes 4 full tree traversals per observe, 2 identical (#3419) (performance)
  • perf: filterOffscreenNodes does 2x full-tree JSON.stringify for a debug-only log (#3418) (performance)
  • Audit + concurrency stress-test in-process RMW get-or-create paths (#3405) (database)
  • Design and implement daemon input/key endpoint (#3370) (android, ios)
  • Add typed client helpers for daemon input API (#3345) (android)
  • Document daemon input API consumer examples (#3344)
  • Implement daemon text and key input endpoints (#3343) (android, ios)
  • Implement daemon input/pressButton endpoint (#3342) (android, ios)
  • Implement daemon input/swipe endpoint (#3341) (android, ios)
  • Implement daemon input/tap endpoint (#3340) (android, ios)
  • Define daemon Unix socket input API contract (#3339)
  • actions-diff-observe: choose diff strictness by action class (#3319) (ios, performance)
  • actions-diff-observe iOS: improve stable node identity beyond positional paths (#3318) (ios, performance)
  • iOS observe output: collapse XCTest/UIKit structural noise before action diffs (#3317) (ios, performance)
  • actions-diff-observe: report why a diff was skipped or emitted (#3316) (devxp, performance)
  • actions-diff-observe iOS: gate same-screen diffs on screenIdentity (#3315) (ios, performance)
  • actions-diff-observe iOS: derive fallback screenIdentity from accessibility hierarchy (#3314) (ios, performance, a11y)
  • Capture-layer stable node identity to shrink scroll diffs (opaque id-less rows) (#3228)
  • Forward + broadcast tools/list_changed & resources/list_changed across proxy and multi-session daemon (follow-up to #2963) (#3223)
  • Thread StructuredToolResponse through the tool registry (remove the asToolEnvelope unchecked cast) (#3222)
  • Dead observe screenshot cache chain: setLastScreenshot never fires, lastScreenshot never read (#3221)
  • Extend SessionCacheData escape-hatch guard to forbid setter-bypass slot writes in production code (follow-up to #2973) (#3219)
  • Follow-up #2962: consider structured log fields for the structuredContent-omission trace (#3216)
  • Follow-up #2962: directly test INFO-level suppression of the structuredContent-omission debug trace (#3215)
  • Complete or remove the incomplete declare-module “zod” stub forcing schema code into the typecheck baseline (#3207)
  • elementBoundsSchema advertises integer bounds but iOS coordinates are fractional points (#3206)
  • iOS storage telemetry value fidelity: lossy “(value)” stringification for Data/Date/array/dictionary (#3194) (ios)
  • iOS UserDefaults change telemetry has no production trigger (startListening never called) + standard-suite NSGlobalDomain noise (#3193) (ios)
  • feat(video): name recording files/folders by caller-supplied outputName (not just recordingId UUID) (#3145) (video)
  • Surface Compose toggle state (checked/selected/stateDescription) in the extracted view hierarchy (#3139)
  • feat(ios): return a physical-aware failure for getAppPermissions on physical iOS devices (#3135) (ios)
  • feat(ios): support the all privacy keyword for physical-device permission reset (#3133) (ios)
  • Explore structural-id content identity for in-place edits + optional pre-move key in diff (follow-up to #3053 part 1) (#3088)
  • Mark navigation/setup internal tool calls no-diff (DefaultUIStateSetup, NavigateTo) — baseline pollution under –actions-diff-observe (#3087)
  • actions-diff-observe: add a byte-size regression guard for element-field diffs (follow-up to #3059) (#3064)
  • feat(ios): unify device app-listing (ListInstalledApps devicectl parity) for terminate/uninstall wasInstalled (#3057) (ios)
  • feat(ios): explicit iOS<=16 ‘requires iOS 17+’ error for physical terminateApp/launchApp (#3056) (ios)
  • fix(ios): tolerate already-exited PID on devicectl device terminate (avoid false success:false) (#3054) (ios)
  • actions-diff-observe: positional node key cascades on scroll/insert; explore stable node identity + internal-consumer diff exposure (#3053)
  • actions-diff-observe: diff omits top-level focusedElement / accessibilityFocusedElement / awaitedElement changes (#3052)
  • actions-diff-observe: sign off the diff format on real-device output (#3026 acceptance) (#3051)
  • Dormant output-reduction flags: –actions-diff-observe and –actions-no-observe are plumbed but have no consumer (#3026)
  • observe tool has no outputSchema — advertise ObserveResult (incl. compact bounds tuple) on the wire (#3025)
  • Follow-up to #2997: generate golden tables from JSON + parser string-literal robustness (#3021)
  • Harden pinch-geometry parity: single-source golden vectors instead of hand-duplicated tables (follow-up to #2979) (#2997) (ios)
  • observeResultCompact follow-ups: actionsDiffObserve composition test + wire-schema tuple doc (#2990) (performance)
  • Add executable guard for iOS pinch geometry (parity with Android computePinchPoints) (#2979) (ios)
  • observeResultCompact: resolve mixed bounds representation (node tuples vs. object elements/root/window bounds) (#2978) (performance)
  • Promote well-known customData keys (keep-awake, device-label) to typed SessionCacheData slots (follow-up to #2917) (#2973)
  • Type or remove the dormant lastActionTime session-cache write (follow-up to #2917) (#2972)
  • Emit tools/list_changed when output-reduction flags toggle at runtime (follow-up to #2759) (#2963)
  • Output reduction: debug-log intentional structuredContent omission (follow-up to #2759) (#2962)
  • Wire observeResultCompact flag into sanitizeObserveResult (flag plumbed but dormant) (#2951) (performance)
  • Durable typed-envelope: re-type the ToolHandler boundary so envelope payload dead-reads are a compile error (#2932)
  • SessionCacheData typed lastHierarchy/lastScreenshot slots are dormant decoys; real data lives in customData with a different type (#2917)
  • pinchOn rotationDegrees: document or fix start-horizontal/end-rotated axis convention (Android + iOS) (#2911) (ios)
  • iOS pinchOn: add public pinch(withScale:velocity:) fallback when private XCTest event-synth symbols are unavailable (#2910) (ios)
  • Typed accessor / typed envelope to eliminate the envelope-vs-structuredContent dead-read bug class (#2907)
  • Wire toolResultsNoStructuredContent flag into finalizeToolResponse (flag plumbed but dormant) (#2899) (performance)
  • Latent bug: swipeOn scroll-position update reads response?.found off the MCP envelope (always undefined) (#2897)
  • feat(ios): terminateApp physical-device support (currently a silent success no-op) (#2882) (ios)
  • Output reduction: extend observe perf-strip to top-level perfTiming/gfxMetrics (#2878) (performance)
  • Automatically recover from an incomplete bunx extraction (consume the EX_TEMPFAIL / exit-code 75 signal) (#2865) (devxp)
  • iOS DND: replace version gate with behavior-based (write→independent readback) detection (#2861) (ios)
  • Output reduction 7: strip embedded observation (–actions-no-observe) (#2762) (performance)
  • Output reduction 6: observe diff for non-observe tools (–actions-diff-observe) (#2761) (performance)
  • Output reduction 5: compact/TOON observe encoding (–observe-result-compact) (#2760) (performance)
  • Output reduction 4: gate structuredContent duplication (drop for no-schema tools) (#2759) (performance)
  • Output reduction 3: finalizeToolResponse hook + lastHierarchy cache repair (#2758) (performance)
  • Output reduction 2: sanitizeObserveResult (perf-strip + node-trim + elements-drop) (#2757) (performance)
  • Output reduction 1: config plumbing for output-reduction flags (CLI + env) (#2756) (performance)
  • feat(ios): setAppPermissions — reset privacy permissions on physical iOS devices via the CtrlProxy XCUITest runner (#2491) (ios, research)
  • feat(ios): openLink — open URLs/deep links on physical iOS devices via devicectl (#2490) (ios)
  • feat(ios): listApps — enumerate installed apps on physical devices via devicectl (#2489) (ios)
  • feat(ios): terminateApp — physical-device termination via devicectl (#2488) (ios)
  • feat(ios): launchApp — physical-device launch/terminate via devicectl (#2487) (ios)
  • feat(ios): pinchOn — coordinate-based pinch/zoom via XCUITest CtrlProxy runner (#2482) (ios)

Changed

  • chore(observe): remove dead camelCase element-attribute fallbacks in waitFor matcher (#3513) (dead-code)
  • Consolidate near-duplicate ThresholdManager and MemoryThresholdManager into a generic threshold manager (#3448) (performance)
  • Consolidate identical deviceSnapshot/videoRecording config socket servers into a generic ConfigSocketServer (#3447)
  • Consolidate 3 byte-identical config repositories into a generic KeyedJsonConfigRepository (#3446) (database)
  • Dead Code Detection: Threshold Exceeded (#3257) (automated, dead-code)
  • refactor(ios): extract IOSCtrlProxyManager port health and host-control collaborators (#3218) (ios)
  • Follow-up to #2885: SessionManager barrier comment, in-process reopen reset, and trackExisting direction re-eval (#3154) (database)
  • test(db): databaseLazyPath + dbWriteBarrierResetOnClose flake (timeout) on windows-latest CI (file-backed sqlite) (#3030) (database)
  • chore(db): fileLock hardening follow-ups from PR #2995 (release incarnation-awareness + positional-format contract) (#3006) (database)
  • Remove pre-existing dead Image facade methods (transform/disableCache) (#2970) (javascript, dead-code)
  • chore(db): in-process same-path reopen can steal an in-flight migration’s own-PID lock (reclaimOwnPid) (#2947) (database)
  • chore(db): consolidate migration-state module globals into a single MigrationState + reset() (#2944) (database)
  • test(db): reset-test files bleed process.env across the suite → intermittent databaseReset.test.ts flake (#2942)
  • db: guard migration-lifecycle against a startMigrations run that settles after closeDatabase() reset (#2940) (database)
  • Trim unused ImageUtils/Image surface left over from the sharp→jimp migration (#2938) (javascript, dead-code)
  • refactor(db): consolidate closeDatabase() reset checklist behind a single resetDbLifecycleState() (#2935) (database)
  • docs(db): two inaccurate comments left by #2905 (test ‘fully true’ over-claim + null-swap safety rationale omits use-time throw) (#2934) (documentation, database)
  • chore(db): dbWriteBarrier reset is identity-swap — construction-captured consumers keep the drained barrier across a same-process reopen (#2912) (database)
  • refactor(db): encapsulate migration-lifecycle module globals into a single resettable state object (#2900) (database)
  • chore(db): no generation fence — an in-flight migration completing after closeDatabase() can stomp the next generation’s migrationsError (#2898) (database)
  • chore(db): dbWriteBarrier drain latch does not cold-start on a same-process DB reopen (#2896) (database)
  • chore(db): logged swallow for retention-cleanup catch blocks in event repositories (CLAUDE.md convention) (#2894)
  • chore(db): consume err.cause.code for a BUSY/constraint-aware SQLite retry (follow-up to #2793) (#2874) (database)
  • refactor(ios): finish control-proxy typed-model cleanups (dead CommandError cases, enum-derived responseType, WebSocketServer test) (#2859) (ios, dead-code)
  • test(ios): add control-proxy wire-parity drift tripwire + fix request_voiceover_action mismatch (#2857) (ios, testing)
  • refactor(ios): migrate control-proxy off the flat WebSocketRequest bag to a typed command model (#2846) (ios, dead-code)
  • refactor(scripts): extract scripts/lib/file-selection.sh to de-duplicate validate/apply git file-selection (#2823) (devxp)
  • refactor(scripts): extract scripts/lib/tool-install.sh to de-duplicate installer boilerplate (#2822) (devxp)
  • refactor(desktop-core): decompose 4898-line AutoMobileContent.kt into per-concern sibling files (#2820) (android)
  • chore(desktop-core): delete dead unified/ socket-client package (~1498 LOC, zero references) (#2819) (android, dead-code)
  • refactor(control-proxy): extract dispatchGestureWithResult helper; de-duplicate 5 gesture callback/perf blocks in CtrlProxy.kt (#2817) (android)
  • perf(db): batch getFailureGroups/getSampleOccurrences N+1 queries into grouped IN(…) lookups (#2810) (performance)
  • refactor(server): decompose registerDeviceAware handler pipeline + replace boolean-trap signature with options bag (#2804)
  • chore(db): closeDatabase() leaves migration flags set, so a same-process reopen would skip migration gating (#2796) (database)
  • chore(db): harden bunSqliteDialect — nested-txn deadlock guard, preserve SqliteError cause/stack, word-boundary RETURNING detection (#2793) (database)
  • refactor(plan): extract executeStep to de-duplicate PlanExecutor step pipeline; replace createCombinedSignal with AbortSignal.any (#2783)
  • refactor(ios): extract ProcessSupervisor to de-duplicate xctest/iproxy supervisor stacks in IOSCtrlProxyManager (#2770) (ios)
  • chore(android-cmdline-tools): remove dead installAndroidTools, dedupe AvdManager interface, fix [object Object] AVD error (#2769) (android, dead-code)
  • refactor(video): extract shared ChildProcessTracker; de-duplicate exit-tracking across ffmpeg/platform backends (#2767) (video)
  • ci: enable tsc type-checking in CI (unblock tsc, triage 548 hidden type errors, then gate) (#2766) (ci)
  • refactor(observe/android): consolidate scattered telemetry/crash ingestion in AndroidCtrlProxyClient behind SdkEventIngestor (#2764) (android)
  • refactor(observe/ios): extract wire-decode module + IosSdkEventIngestor from 2147-line IOSCtrlProxyClient (#2763) (ios)
  • refactor(observe): standardize AdbClientFactory injection, remove factory-vs-executor sniff across 11 observe classes (#2754) (android)
  • refactor(models): introduce BaseActionResult to collapse ~65 duplicated action Result types (#2753)
  • refactor(android): finish WebSocketServer typed-handler migration in control-proxy (retire LegacyWebSocketRequest) (#2752) (android, dead-code)

Fixed

  • observe: occludedByViewId never populates — occluder’s stable view-id is dropped in the Android runner occlusion pass (#3536) (android)
  • AppLifecycleMonitor.isPackageRunning swallows ADB errors → emits phantom “terminate” lifecycle events (#3515)
  • fix(observe): fail fast on iOS activityName-only waitFor instead of silent timeout (#3512) (ios)
  • Silent error-swallowing catch blocks violate the CLAUDE.md convention; add a lint backstop (#3508) (maintenance)
  • NavigateTo: missing await on shouldUseBackButton leaves smart back-button nav dead in production (#3445)
  • PK-keyed inserts crash on duplicate/concurrent create (deviceSnapshot, videoRecording) (#3404) (database)
  • testExecutionRepository.recordExecution: wrap multi-insert in a transaction (atomicity) (#3403) (database)
  • Daemon health check never probes the DB (post-startup liveness gap) (#3402) (database)
  • startDevice (Android cold-boot) returns wrong deviceId + false isReady when another emulator is already running (#3393) (android)
  • postNotification (Android) targets stale getCachedActiveWindow() and ignores explicit appId → delivers to wrong package (#3392) (android)
  • Daemon shutdown mid-startup-migration doesn’t await in-flight migrations before closeDatabase() (#3044)
  • JimpCliBackend wiring + drop @jimp/wasm-webp + Windows smoke (closes #2974) (#3012) (performance, javascript)
  • Windows CI: databaseLazyPath + dbWriteBarrierResetOnClose file-DB tests still flake (EBUSY/livelock) despite #2916/#2923 (#2992)
  • jimp image tests fail locally (bun/macos-arm64) while passing in CI (#2971) (javascript)
  • test(nav): isolate NavigationGraphManager.test.ts singleton-backed blocks to fix cold-first-run flakiness (#2969)
  • fix(db): transactionalize promoteSuggestion + recordHierarchyNavigation graph writes (siblings of #2791) (#2968) (database)
  • Flaky CI: windows-latest file-backed SQLite close/reopen tests (EBUSY/livelock) intermittently fail (#2916) (database)
  • Flaky CI: DefaultProcessExecutor “exec captures stdout” times out (30s) on macos-latest; spawns real subprocess (#2914)
  • iOS runner: widen gesture request coordinate fields to Double (Int decode + roundCoordinates:false is a latent robustness gap) (#2909) (ios)
  • fix(db): migration columns store literal “datetime(‘now’)” instead of a timestamp (48 columns, 24 migrations) (#2895) (database)
  • fix(db): route NavigationGraphManager shutdown write through the DB-write barrier without perturbing nav/hierarchy ordering (follow-up to #2792) (#2885) (maintenance, database)
  • fix(db): wrap FailureAnalyticsRepository.recordFailure in a single transaction (close count-ahead-of-occurrence window) (#2877) (database)
  • fix(cli): direct-mode DB guard transiently over-refuses during daemon startup (publish dbPath before DB open) (#2871) (database)
  • fix(daemon): daemon process detection is POSIX-only (ps), breaking singleton enforcement + forcing direct-mode guard fail-open on Windows (#2870)
  • fix: 6 remaining TS2304 out-of-scope identifiers (2 latent runtime ReferenceErrors in Capture/RestoreSnapshot) (#2866)
  • fix(cli): refuse –no-proxy/–direct when a live daemon already owns auto-mobile.db (#2795) (database)
  • fix(db): guard runMigrations with a cross-process lock so two DB openers can’t trip a spurious startup failure (#2794) (database)
  • fix(db): drain in-flight DB writes before closeDatabase() so shutdown cannot strand on Kysely ConnectionMutex (#2792) (maintenance, database)
  • fix(db): make NavigationGraphManager.recordNavigationEvent graph write transactional (#2791) (database)
  • fix(db): non-transactional get-or-create / read-modify-write races across coverage, navigation, prediction, and appearance repositories (#2790) (database)
  • fix(db): add UNIQUE index on failure_groups.signature and make recordFailure an atomic upsert (#2789) (database)
  • fix(db): reset failed migrationsPromise and surface a cached startup error synchronously so a floating rejection can’t kill the daemon (#2786) (database)
  • fix(db): destructive migration auto-recovery (default-on) can DROP every table on a populated database (#2785) (database)
  • fix(daemon): make startup DB/migration failure fatal so the daemon doesn’t run query-dead while reporting healthy (#2784) (database)
  • fix(talkback): FocusNavigationExecutor.navigateToElement throws ReferenceError on zero-swipe path (accessibilityService out of scope) (#2765) (android, a11y)
  • fix(ios): setDeviceState binary Do Not Disturb does not verify on iOS 18.6 simulator (notifyutil read-back unchanged) (#2545) (ios)

Other

  • chore: retire historical catch logging lint allowlist (#3532)
  • tapOn: no way to target the Nth of several matching elements (repeated controls with no unique text) (#3524)
  • tapOn –sibling can’t reach a row’s action control when the row’s label is nested (#3522)
  • Expose occluding node view-id in observe hierarchy (#3519)
  • macOS development installer CI misses runtime dependencies (#3500)
  • Use app-scoped Android locale changes when targeting an app (#3492)
  • Avoid import-time failure for malformed asset mirror config (#3491)
  • Remove host-control Docker remote device support (#3485)
  • feat(output-artifacts): extend artifact mode to non-observation heavy outputs (#3481)
  • feat(output-artifacts): add startup config and per-call directory validation (#3482)
  • feat(output-artifacts): artifact all agent-facing observation payloads (#3480)
  • feat(output-artifacts): define artifact writer and response metadata contract (#3483)
  • Reduce keyed JSON config wrappers to one repository (#3463)
  • perf: fold observe element collection into a single traversal (#3456)
  • Tools Use File Output Mode (#3455)
  • perf: SharpBackend materializes a full Buffer between every pipeline operation (#3431) (performance)
  • perf: TestCoverageAnalyzer recomputes entry points + multi-source BFS per gap (~O(gaps*V*E)) (#3424) (performance)
  • perf: findPath BFS uses array-scan adjacency, Array.shift() queue, and path-array copies (#3423) (performance)
  • perf: Explore main loop calls full exportGraph() every iteration just to count nodes (#3422) (performance)
  • perf: findPath enriches ALL edges with 4 DB queries each before running BFS (#3421) (performance, database)
  • perf: cleanupIosXCTestHierarchy re-walks each subtree at every ancestor level (O(n*depth)) (#3420) (ios, performance)
  • Extend daemon recovery for DB health probe failures (#3416)
  • Fix unguarded DB RMW follow-ups from concurrency audit (#3415)
  • Periodic PRAGMA optimize / ANALYZE for query-planner stats (#3407) (performance, database)
  • Set cheap unset SQLite pragmas (cache_size, mmap_size, temp_store) (#3406) (performance, database)
  • Track Android cold-boot emulator deviceId without relying on AVD name resolution (#3399)
  • Expose optional screenshot stream performance metadata (#3389)
  • Add screenshot format and fallback metadata to observation stream (#3385)
  • Support subscriber-controlled iOS hierarchy polling cadence (#3381)
  • Support subscriber-controlled Android hierarchy throttling (#3380)
  • Add hierarchyIntervalMs to observation stream subscriptions (#3379)
  • startDevice reports a device as booted before the OS has finished booting (#3334)
  • Add configurable live observation cadence for stream subscribers (#3333)
  • Flaky: stripToolResultWireBoundary.test.ts DEBUG-gate trace fails under full-suite ordering (#2962 test) (#3256) (flaky test, testing)
  • Investigate dead replayTools / ReplayToolsService surface (#3209)
  • Add focused ToolRegistry pipeline collaborator coverage (#3208)
  • fix(db): resolve #3176 migration typecheck errors and ratchet baseline down (#3204)
  • refactor(doctor): fold ios.ts local createExecResult clone into canonical createExecResult (#3200)
  • typecheck gate hardening: signature-swap blind spot, base-drift UX, exact TS pin, test/** scope (#3196)
  • typecheck burndown: resolve TS2300 CtrlProxyHierarchy + TS2305 missing-export clusters (ratchet #3172 AC#3) (#3195)
  • control-proxy: tighten LaunchCancellationScanner to flag conditional rethrows in broad catches (#3192) (android)
  • control-proxy: generalize CancellationException-swallow scan beyond the curated suspend-fn list (#3191) (android)
  • Follow up: clear hierarchy request owners after uncorrelated observe completions (#3190)
  • ci(image): investigate intermittent Ubuntu Bun image runtime smoke null-reference failure (#3189)
  • Follow up physical iOS all reset for every XCUIProtectedResource (#3188)
  • test-infra: decide keep-vs-retire the unit-test DB guard’s opt-in fallback (flag + preload + #3117 tripwire) after arm-by-default (#3140 follow-up) (#3185)
  • perf(db): cap structured-JSON large-text columns at the telemetry backfill boundary (os/layout/failure) (#3182) (performance, database)
  • Track control-proxy lintDebug failures (#3181)
  • perf(telemetry): capture & emit prior UserDefaults value from iOS CtrlProxy runner (follow-up to #3000) (#3174) (performance)
  • Normalize storage_events.value_type vocabulary across iOS/Android (#3173) (database)
  • Add a scoped tsc –noEmit typecheck gate for src/ (fail on new errors) (#3172)
  • iOS SDK storage_changed never captures real key/value/type (KVO emits nil/”unknown”) (#3171) (database)
  • test(db): use bounded temp DB cleanup in synchronous pragma readback test (#3160) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3158) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3157) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3156) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3155) (database)
  • follow-up(ios): finish DeviceAppManager variable cleanup in IOSCtrlProxyManager (#3150) (ios)
  • Reduce MCP output token cost for agentic runs (inert –actions-no-observe, element subtree bloat, pretty-printed JSON) (#3141)
  • test-infra: make the unit-test DB guard arm-by-default (opt-out) instead of preload-opt-in (#3083 follow-up) (#3140)
  • perf(db): shared batched telemetry ingestion path (buffer + multi-row INSERT + shared EventRetentionPolicy) (#3138) (performance, database)
  • chore(db): converge telemetry-event retention onto the canonical offset(N-1)+id-tiebreak idiom (#3137) (database)
  • chore(db): extract a shared cleanupIfNeeded retention helper for the six event repos (#3136) (database)
  • test(ios): unit-test the physical-reset permission→XCUIProtectedResource mapping table (#3134) (ios, testing)
  • Android CtrlProxy: add behavioral test for EXTRACT_HIERARCHY error-frame emission (#3089 follow-up) (#3131) (android)
  • Android CtrlProxy: commandReceiver outer catch swallows CancellationException (#3130) (android)
  • Guard-test the ‘side-effects outside fn’ convention for runBothReposInTransaction (follow-up to #3075) (#3129)
  • Make ServiceScopeGuard correlation structural for raw serviceScope.launch (follow-up to #3104) (#3128) (android)
  • Add fallback-to-back-button test for DefaultUIStateSetup.dismissTopModal bottom-sheet branch (#3125)
  • refactor(ios): reduce launchApp / launchWithPayloadUrl drift in DeviceAppInspector (#3123) (ios)
  • refactor(ios): DeviceAppInspector name no longer reflects its scope (install/launch/terminate/open-URL) (#3122) (ios)
  • ci(ios): ‘Daemon failed to start within 10000ms’ flake in XCTestRunner — 10s readiness budget too small on cold macOS runners (#3110) (ios)
  • ci(ios): XCTestRunner videoRecording step fails deterministically — unit-test DB guard (#3082) trips the integration test (#3109) (ios)
  • Optional: ToolRegistry.callInternal(name, args) seam to remove the residual mark-then-call footgun (#3108)
  • Revisit structural-id content-identity adoption (limitation 1) with real-device data; optional pre-move fromKey (#3107)
  • DefaultUIStateSetup.dismissTopModal calls getTool(“swipe”) — never registered, so bottom-sheet swipe-dismiss is dead code (#3106)
  • Enforce/close the raw serviceScope.launch fire-and-forget silent-hang gap (AsyncActionRunner adoption) (#3104) (android)
  • refactor: ActionableError sweep for OpenURL / DeviceAppInspector / DeviceCtlClient result-error family (#3102)
  • refactor(ios): fold DeviceCtlClient open-URL primitive into DeviceAppInspector (dedup devicectl wrapper) (#3099) (ios)
  • Flaky: IOSCtrlProxyManager “externally managed test-without-building runner” test times out at ~5s on macOS CI (#3098)
  • observe/android: consider short-circuiting verifyServiceReady retries on a deterministic runner handler failure (#3097) (android)
  • Android CtrlProxy: correlate the ADB-broadcast fallback hierarchy request (sync_ uuid) into the wait (#3089) (android)
  • Enforce broadcast-helper guard adoption (ResultBroadcaster/AsyncActionRunner) so #3045/#3023 can’t silently regress (#3085) (android)
  • test-infra: fire-and-forget TelemetryRecorder guard-throw surfaces as an unhandled rejection, not a deterministic test failure (#3084)
  • test-infra: unit-test DB guard fails open if the bun test preload is skipped (#3083)
  • Follow-ups from withFileBackedDb harness (#3046/PR #3078): enforcement + generic cleanup + optional hooks binder (#3081)
  • docs: document the AUTOMOBILE_DB_* env-var family (follow-up from #3065/#3071) (#3079)
  • fix(ios): surface devicectl stderr diagnostic (not just “Command failed”) on physical terminate failure (#3077) (ios)
  • refactor(ios): extract a shared “process already gone” terminate-error matcher (simctl + devicectl) (#3076) (ios)
  • Extract shared two-repo runInTransaction helper for NavigationGraphManager (follow-up to #2980) (#3075)
  • test: pin the sdkNavigationAppIds skip mechanism in the SDK-screen-name preservation test (#3068)
  • test-infra: guard against unit tests resolving the real file-backed getDatabase() (#3067)
  • Guard against production AUTOMOBILE_DB_PATH=:memory: (migrated-but-empty app connection footgun) (#3065)
  • test(observe): “getLatestHierarchy > should preserve SDK screen names when hierarchy updates follow navigation events” fails on main (#3063)
  • observe/android: let requestHierarchySync surface the runner error text instead of collapsing to null (#3062) (android)
  • Android CtrlProxy: correlate request_hierarchy_if_stale (stale_ id) error frames into the hierarchy wait (#3061) (android)
  • Tech-debt: consider a protected SharedGestureDelegate.coord() so Android-only gesture overrides reuse the shared rounding (#3049) (android)
  • Test coverage: two-finger swipe concurrency + error-frame (type:”error”) resolution path (#3048) (android)
  • Move dbWriteBarrierResetOnClose barrier test to a :memory: sentinel DB (eliminate the file-handle flake class) (#3047)
  • Silent-hang when a broadcast helper’s own broadcast() throws (pre-existing, #3023-adjacent) (#3045) (android)
  • Shared withFileBackedDb test harness to enforce the DB-lifecycle flake-avoidance pattern (#3046)
  • Enforce “new async actions get correlated-error-on-throw for free” structurally (#3023 follow-up) (#3043) (android)
  • Add production-wiring guard test for CtrlProxy async launch sites (#3023 follow-up) (#3042) (android)
  • Cleanup: minor follow-ups from ImageBackend consumer migration (#3009 / PR #3036) (#3041) (javascript)
  • test(ios): cover TerminateApp observed-interaction path + fix perf.end() tree ownership (#3037) (ios)
  • Android CtrlProxy error-envelope: hierarchy handler failures still hang the awaiter (type:”error” not routed into waitForFreshData) (#3032) (android)
  • Harden: plan retry can exceed the 10-min CI step cap if an attempt hits the outer 300s callTool timeout (#3029) (ios)
  • iOS observe cold-bring-up waitFor timeout: fix root cause behind the Reminders launch/add retries (#3028) (ios)
  • Refactor: hoist RemindersIntegrationBase retry into a shared defaultRetryCount hook (#3027) (ios)
  • Android CtrlProxy: async action failures inside launched coroutines still hang the awaiter (#3023) (android)
  • Android CtrlProxy error-envelope: iOS parity (rewriteUnknownCommandError, out-of-range legibility, targeted send) (#3022) (android)
  • Android CtrlProxy: decode failures send no wire error frame (silent drop) — mirror iOS #2986 field-attributed decode errors (#3017) (android)
  • Minimal Bun repro for sharp 0.35.x-under-Bun abort (non-blocking upstream) (#3014) (dependencies)
  • doctor image-backend check + cache-portability contract docs (#3013) (devxp, javascript)
  • cwebp/dwebp provisioning: bundle libwebp binaries + CliWebpCodec (#3011) (devxp, javascript)
  • SharpBackend + pin sharp 0.34.5/@img + dependabot ignores + build externals (macOS/Linux) (#3010) (performance, dependencies, javascript)
  • Migrate pixel consumers (PerceptualHasher/ScreenshotComparator/ContrastChecker/image-utils) to ImageBackend (#3009) (javascript)
  • Image backend seam: ImageBackend interface + declarative ImageTransformer + FakeImageBackend (#3008) (devxp, javascript)
  • ktfmt: make version-pin comparison robust to 2-part vs 3-part version strings (follow-up to #2993) (#3004)
  • ktfmt: make merge.yml full-tree ktfmt a branch-protection required check (follow-up to #2966) (#3003)
  • fix(ios): recordStorageEvent call passes undeclared ‘operation’ and omits required valueType/changeType (masked by Bun no-typecheck) (#3001) (database)
  • perf(telemetry): emit prior storage value from CtrlProxy runners to skip recordStorageEvent lookup (#3000) (performance, database)
  • Flaky: XCTestRunner Simulator ‘RemindersLaunchPlanTests’ observe waitFor timeout reds non-required CI (#2998) (ios)
  • Tech debt: extract shared bind-both-repos transaction helper in NavigationGraphManager when a 4th caller lands (Devin §4) (#2994)
  • iOS parity: guard non-finite pinch rotationDegrees in CtrlProxy CommandHandler (mirror Android #2964 / PR #2984) (#2991) (testing)
  • Android two-finger swipe result correlation is orphaned — resolves only via 5s timeout (handleTwoFingerSwipeResult has no caller) (#2988) (android)
  • iOS runner: extend decode-error legibility to typeMismatch/valueNotFound (field-attributed) — #2965 option 2 (#2986) (ios)
  • Android CtrlProxy runner swallows decode/handler failures — no error envelope sent to client (#2985) (android)
  • Make NavigationGraphManager.promoteSuggestion atomic (partial-write on mid-sequence throw) (#2981)
  • Harden recordHierarchyNavigation: guard + transactionalize the coverage-repo enlistment (follow-up to #2968) (#2980)
  • validate_ktfmt.sh: add set -euo pipefail + explicit process-substitution error handling (#2967)
  • ktfmt: enforce the pinned formatter version so version drift can’t silently land on red main (#2966)
  • iOS runner: opaque decode-boundary error for out-of-range numeric literals (1e309) — surface an actionable message (#2965) (ios)
  • Android runner: reject non-finite gesture coordinates (isFinite guard) — mirror iOS #2928, load-bearing on the kotlinx wire (#2964) (android, testing)
  • refactor(ios): merge redundant CtrlProxyVoiceOverActionResult into CtrlProxyActionResult (#2956) (ios)
  • test(ios): make control-proxy wire-parity scan structural (AST) + import-graph-derived, not regex/adjacency-based (#2955) (ios, testing)
  • test(ios): field-name wire-parity backstop for control-proxy (JSON snapshot fixtures) (#2954) (ios, testing)
  • Release: re-cut iOS CtrlProxy runner + update checksum registry to deliver the #2910 pinch fallback (#2953) (ios)
  • test(db): tripwire so a non-Windows bun:sqlite handle-leak can’t hide behind removeTempDbDir’s silent give-up (#2949) (database)
  • test(db): consolidate remaining sync best-effort temp-dir cleanup (backupDatabaseFile) into a removeTempDbDirSync helper (#2948) (database)
  • refactor(utils): consolidate DefaultProcessExecutor / DefaultHostCommandExecutor duplication + unify exec-seam type export (#2945)
  • refactor(db): extract a single EVENT_TABLES constant to de-duplicate the telemetry event-table list (follow-up to #2918) (#2943) (performance)
  • Add real-pixel regression tests for the jimp image pipeline (#2939) (testing, javascript)
  • chore(db): upgraded-DB parity for updated_at defaults (repair migration + relax type) (#2937) (database)
  • iOS runner: reject non-finite gesture coordinates (isFinite guard) at the decode/handler boundary (#2928) (ios)
  • Android runner: widen gesture request coordinate fields to Double (symmetric to iOS #2909) (#2927) (android)
  • chore(db): reconcile updated_at columns declared notNull with no default (asymmetric with created_at) (#2913) (database)
  • perf(db): add a CI drift guard for the telemetry event tables’ index inventory (follow-up to #2893) (#2908) (performance)
  • Follow up Codex skill metadata location for .agents wrapper (#2901)
  • perf(db): drop now-redundant single-column device indexes on telemetry event tables (follow-up to #2788) (#2893) (performance)
  • test(ios): hermetic LaunchApp-level coverage for clearAppData on a physical device (#2884) (ios)
  • Testing: regenerate #2755 observe baseline from a raw capture to exercise node-trim on real data (#2879) (performance, testing)
  • docs(db): document migration corrupted-recovery flow + AUTOMOBILE_MIGRATION_RECOVERY (=true vs =1) semantics (#2869) (documentation, database)
  • fix(db): duplicate date-prefixed migration filenames make Kysely ordering fragile (#2868) (database)
  • Guard MIGRATION_RUNTIME_DEPENDENCIES against drift from migration runtime imports (#2867) (devxp)
  • notifyutil: verify whether the -1 registration is actually required for notify_set_state (helper + comments may overstate it) (#2864) (ios, devxp)
  • optional plan-step primitive: parallel-track observability + log-export round-trip (#2863) (testing)
  • ci(ios): XCTestRunner Simulator Tests builds stale committed CtrlProxy.xcodeproj (no xcodegen regen) (#2858) (ios, ci)
  • Reminders add-reminder plan is pinned to CI’s iOS Reminders labels (Done/New Reminder, English) (#2855) (flaky test, ios, testing)
  • iOS CtrlProxy runner lifecycle: extract teardown/identity primitive + pre-existing kill-scoping fixes (#2847)
  • feat(observe): richer waitFor predicates + activeWindow conditions + stability gate (#2845)
  • Daemon startup DB migration hard-fails when bunx extraction is missing a transitive dep (e.g. kysely) (#2833)
  • nightly: PR title/body don’t reflect a runner-only SHA256 change (#2816)
  • Supply-chain hardening for hermetic pinning: acceptedPreinstalled mismatch + mirror URL validation (#2815)
  • iOS: bake a version constant into the XCTestRunner SPM package (#2814)
  • Enforce the version pin across a reused/shared daemon (PID-file stamp + client mismatch fail) (#2812)
  • Flaky: RemindersAddPlanTests.testAddReminderPlan (UI ‘Done’ tap race at plan step 5) (#2811) (flaky test, ios, testing)
  • Versioning: resolve (or formally accept) the -SNAPSHOT coordinate divergence for local Gradle builds (#2807)
  • Release integrity: store iOS runner SHA256 per registry entry (not a global scalar) (#2806)
  • perf(db): WAL hygiene — set journal_size_limit and checkpoint(TRUNCATE) on close (#2802) (performance, database)
  • perf(db): truncate request/response bodies in the getNetworkEvents list projection (#2801) (performance, database)
  • perf(db): batch N+1 query fan-out in getFailureGroups and getTestRuns (dashboard read paths) (#2800) (performance, database)
  • perf(db): amortize per-insert retention COUNT(*) in event repositories (#2799) (performance, database)
  • perf(db): add covering index for recordStorageEvent previous-value lookup (#2798) (performance, database)
  • perf(db): add a bounded prepared-statement cache to the Bun SQLite dialect (#2797) (performance, database)
  • perf(db): add composite (device_id, timestamp) indexes to telemetry event tables to eliminate ORDER BY filesorts (#2788) (performance, database)
  • perf(db): set PRAGMA synchronous = NORMAL under WAL to stop per-commit fsync on the telemetry write stream (#2787) (performance, database)
  • Output reduction 0: measurement harness (fixture + byte-breakdown script) (#2755) (devxp, performance, testing)
  • Provide hermetic single-version CI pinning for all clients (daemon + ctrlproxy APK/IPA + junit-runner + XCTestRunner) (#2746)
  • Shared per-uid daemon socket is unguarded for non-TS clients (JUnit/XCTest) — add server-side version/build-identity handshake (#2744)
  • Release integrity: iOS runner-binary checksum never wired (verification disabled) + no version-equality release gate (#2745)
  • Multiple checkouts share one per-uid daemon socket → wrong-build daemon serves frontend (version skew, opaque “Unknown tool” -32603) (#2732)
  • Evaluate Compose interop hidden-region text heuristic with real-world data (#2634)
  • feat(ios): invoke custom accessibility actions via tapOn (#2265)
  • No loading-awareness when refreshing element position before tap (#1949)

[v0.0.41] - 2026-07-07

Added

  • Implement daemon text and key input endpoints (#3343) (android, ios)
  • Implement daemon input/pressButton endpoint (#3342) (android, ios)
  • Implement daemon input/swipe endpoint (#3341) (android, ios)
  • Implement daemon input/tap endpoint (#3340) (android, ios)
  • Define daemon Unix socket input API contract (#3339)
  • actions-diff-observe iOS: improve stable node identity beyond positional paths (#3318) (ios, performance)
  • iOS observe output: collapse XCTest/UIKit structural noise before action diffs (#3317) (ios, performance)
  • actions-diff-observe: report why a diff was skipped or emitted (#3316) (devxp, performance)
  • actions-diff-observe iOS: gate same-screen diffs on screenIdentity (#3315) (ios, performance)
  • actions-diff-observe iOS: derive fallback screenIdentity from accessibility hierarchy (#3314) (ios, performance, a11y)
  • Capture-layer stable node identity to shrink scroll diffs (opaque id-less rows) (#3228)
  • Forward + broadcast tools/list_changed & resources/list_changed across proxy and multi-session daemon (follow-up to #2963) (#3223)
  • Thread StructuredToolResponse through the tool registry (remove the asToolEnvelope unchecked cast) (#3222)
  • Dead observe screenshot cache chain: setLastScreenshot never fires, lastScreenshot never read (#3221)
  • Extend SessionCacheData escape-hatch guard to forbid setter-bypass slot writes in production code (follow-up to #2973) (#3219)
  • Follow-up #2962: consider structured log fields for the structuredContent-omission trace (#3216)
  • Follow-up #2962: directly test INFO-level suppression of the structuredContent-omission debug trace (#3215)
  • Complete or remove the incomplete declare-module “zod” stub forcing schema code into the typecheck baseline (#3207)
  • elementBoundsSchema advertises integer bounds but iOS coordinates are fractional points (#3206)
  • iOS storage telemetry value fidelity: lossy “(value)” stringification for Data/Date/array/dictionary (#3194) (ios)
  • iOS UserDefaults change telemetry has no production trigger (startListening never called) + standard-suite NSGlobalDomain noise (#3193) (ios)
  • feat(video): name recording files/folders by caller-supplied outputName (not just recordingId UUID) (#3145) (video)
  • Surface Compose toggle state (checked/selected/stateDescription) in the extracted view hierarchy (#3139)
  • feat(ios): return a physical-aware failure for getAppPermissions on physical iOS devices (#3135) (ios)
  • feat(ios): support the all privacy keyword for physical-device permission reset (#3133) (ios)
  • Explore structural-id content identity for in-place edits + optional pre-move key in diff (follow-up to #3053 part 1) (#3088)
  • Mark navigation/setup internal tool calls no-diff (DefaultUIStateSetup, NavigateTo) — baseline pollution under –actions-diff-observe (#3087)
  • actions-diff-observe: add a byte-size regression guard for element-field diffs (follow-up to #3059) (#3064)
  • feat(ios): unify device app-listing (ListInstalledApps devicectl parity) for terminate/uninstall wasInstalled (#3057) (ios)
  • feat(ios): explicit iOS<=16 ‘requires iOS 17+’ error for physical terminateApp/launchApp (#3056) (ios)
  • fix(ios): tolerate already-exited PID on devicectl device terminate (avoid false success:false) (#3054) (ios)
  • actions-diff-observe: positional node key cascades on scroll/insert; explore stable node identity + internal-consumer diff exposure (#3053)
  • actions-diff-observe: diff omits top-level focusedElement / accessibilityFocusedElement / awaitedElement changes (#3052)
  • actions-diff-observe: sign off the diff format on real-device output (#3026 acceptance) (#3051)
  • Dormant output-reduction flags: –actions-diff-observe and –actions-no-observe are plumbed but have no consumer (#3026)
  • observe tool has no outputSchema — advertise ObserveResult (incl. compact bounds tuple) on the wire (#3025)
  • Follow-up to #2997: generate golden tables from JSON + parser string-literal robustness (#3021)
  • Harden pinch-geometry parity: single-source golden vectors instead of hand-duplicated tables (follow-up to #2979) (#2997) (ios)
  • observeResultCompact follow-ups: actionsDiffObserve composition test + wire-schema tuple doc (#2990) (performance)
  • Add executable guard for iOS pinch geometry (parity with Android computePinchPoints) (#2979) (ios)
  • observeResultCompact: resolve mixed bounds representation (node tuples vs. object elements/root/window bounds) (#2978) (performance)
  • Promote well-known customData keys (keep-awake, device-label) to typed SessionCacheData slots (follow-up to #2917) (#2973)
  • Type or remove the dormant lastActionTime session-cache write (follow-up to #2917) (#2972)
  • Emit tools/list_changed when output-reduction flags toggle at runtime (follow-up to #2759) (#2963)
  • Output reduction: debug-log intentional structuredContent omission (follow-up to #2759) (#2962)
  • Wire observeResultCompact flag into sanitizeObserveResult (flag plumbed but dormant) (#2951) (performance)
  • Durable typed-envelope: re-type the ToolHandler boundary so envelope payload dead-reads are a compile error (#2932)
  • SessionCacheData typed lastHierarchy/lastScreenshot slots are dormant decoys; real data lives in customData with a different type (#2917)
  • pinchOn rotationDegrees: document or fix start-horizontal/end-rotated axis convention (Android + iOS) (#2911) (ios)
  • iOS pinchOn: add public pinch(withScale:velocity:) fallback when private XCTest event-synth symbols are unavailable (#2910) (ios)
  • Typed accessor / typed envelope to eliminate the envelope-vs-structuredContent dead-read bug class (#2907)
  • Wire toolResultsNoStructuredContent flag into finalizeToolResponse (flag plumbed but dormant) (#2899) (performance)
  • Latent bug: swipeOn scroll-position update reads response?.found off the MCP envelope (always undefined) (#2897)
  • feat(ios): terminateApp physical-device support (currently a silent success no-op) (#2882) (ios)
  • Output reduction: extend observe perf-strip to top-level perfTiming/gfxMetrics (#2878) (performance)
  • Automatically recover from an incomplete bunx extraction (consume the EX_TEMPFAIL / exit-code 75 signal) (#2865) (devxp)
  • iOS DND: replace version gate with behavior-based (write→independent readback) detection (#2861) (ios)
  • Output reduction 7: strip embedded observation (–actions-no-observe) (#2762) (performance)
  • Output reduction 6: observe diff for non-observe tools (–actions-diff-observe) (#2761) (performance)
  • Output reduction 5: compact/TOON observe encoding (–observe-result-compact) (#2760) (performance)
  • Output reduction 4: gate structuredContent duplication (drop for no-schema tools) (#2759) (performance)
  • Output reduction 3: finalizeToolResponse hook + lastHierarchy cache repair (#2758) (performance)
  • Output reduction 2: sanitizeObserveResult (perf-strip + node-trim + elements-drop) (#2757) (performance)
  • Output reduction 1: config plumbing for output-reduction flags (CLI + env) (#2756) (performance)
  • feat(ios): setAppPermissions — reset privacy permissions on physical iOS devices via the CtrlProxy XCUITest runner (#2491) (ios, research)
  • feat(ios): openLink — open URLs/deep links on physical iOS devices via devicectl (#2490) (ios)
  • feat(ios): listApps — enumerate installed apps on physical devices via devicectl (#2489) (ios)
  • feat(ios): terminateApp — physical-device termination via devicectl (#2488) (ios)
  • feat(ios): launchApp — physical-device launch/terminate via devicectl (#2487) (ios)
  • feat(ios): pinchOn — coordinate-based pinch/zoom via XCUITest CtrlProxy runner (#2482) (ios)

Changed

  • Dead Code Detection: Threshold Exceeded (#3257) (automated, dead-code)
  • refactor(ios): extract IOSCtrlProxyManager port health and host-control collaborators (#3218) (ios)
  • Follow-up to #2885: SessionManager barrier comment, in-process reopen reset, and trackExisting direction re-eval (#3154) (database)
  • test(db): databaseLazyPath + dbWriteBarrierResetOnClose flake (timeout) on windows-latest CI (file-backed sqlite) (#3030) (database)
  • chore(db): fileLock hardening follow-ups from PR #2995 (release incarnation-awareness + positional-format contract) (#3006) (database)
  • Remove pre-existing dead Image facade methods (transform/disableCache) (#2970) (javascript, dead-code)
  • chore(db): in-process same-path reopen can steal an in-flight migration’s own-PID lock (reclaimOwnPid) (#2947) (database)
  • chore(db): consolidate migration-state module globals into a single MigrationState + reset() (#2944) (database)
  • test(db): reset-test files bleed process.env across the suite → intermittent databaseReset.test.ts flake (#2942)
  • db: guard migration-lifecycle against a startMigrations run that settles after closeDatabase() reset (#2940) (database)
  • Trim unused ImageUtils/Image surface left over from the sharp→jimp migration (#2938) (javascript, dead-code)
  • refactor(db): consolidate closeDatabase() reset checklist behind a single resetDbLifecycleState() (#2935) (database)
  • docs(db): two inaccurate comments left by #2905 (test ‘fully true’ over-claim + null-swap safety rationale omits use-time throw) (#2934) (documentation, database)
  • chore(db): dbWriteBarrier reset is identity-swap — construction-captured consumers keep the drained barrier across a same-process reopen (#2912) (database)
  • refactor(db): encapsulate migration-lifecycle module globals into a single resettable state object (#2900) (database)
  • chore(db): no generation fence — an in-flight migration completing after closeDatabase() can stomp the next generation’s migrationsError (#2898) (database)
  • chore(db): dbWriteBarrier drain latch does not cold-start on a same-process DB reopen (#2896) (database)
  • chore(db): logged swallow for retention-cleanup catch blocks in event repositories (CLAUDE.md convention) (#2894)
  • chore(db): consume err.cause.code for a BUSY/constraint-aware SQLite retry (follow-up to #2793) (#2874) (database)
  • refactor(ios): finish control-proxy typed-model cleanups (dead CommandError cases, enum-derived responseType, WebSocketServer test) (#2859) (ios, dead-code)
  • test(ios): add control-proxy wire-parity drift tripwire + fix request_voiceover_action mismatch (#2857) (ios, testing)
  • refactor(ios): migrate control-proxy off the flat WebSocketRequest bag to a typed command model (#2846) (ios, dead-code)
  • refactor(scripts): extract scripts/lib/file-selection.sh to de-duplicate validate/apply git file-selection (#2823) (devxp)
  • refactor(scripts): extract scripts/lib/tool-install.sh to de-duplicate installer boilerplate (#2822) (devxp)
  • refactor(desktop-core): decompose 4898-line AutoMobileContent.kt into per-concern sibling files (#2820) (android)
  • chore(desktop-core): delete dead unified/ socket-client package (~1498 LOC, zero references) (#2819) (android, dead-code)
  • refactor(control-proxy): extract dispatchGestureWithResult helper; de-duplicate 5 gesture callback/perf blocks in CtrlProxy.kt (#2817) (android)
  • perf(db): batch getFailureGroups/getSampleOccurrences N+1 queries into grouped IN(…) lookups (#2810) (performance)
  • refactor(server): decompose registerDeviceAware handler pipeline + replace boolean-trap signature with options bag (#2804)
  • chore(db): closeDatabase() leaves migration flags set, so a same-process reopen would skip migration gating (#2796) (database)
  • chore(db): harden bunSqliteDialect — nested-txn deadlock guard, preserve SqliteError cause/stack, word-boundary RETURNING detection (#2793) (database)
  • refactor(plan): extract executeStep to de-duplicate PlanExecutor step pipeline; replace createCombinedSignal with AbortSignal.any (#2783)
  • refactor(ios): extract ProcessSupervisor to de-duplicate xctest/iproxy supervisor stacks in IOSCtrlProxyManager (#2770) (ios)
  • chore(android-cmdline-tools): remove dead installAndroidTools, dedupe AvdManager interface, fix [object Object] AVD error (#2769) (android, dead-code)
  • refactor(video): extract shared ChildProcessTracker; de-duplicate exit-tracking across ffmpeg/platform backends (#2767) (video)
  • ci: enable tsc type-checking in CI (unblock tsc, triage 548 hidden type errors, then gate) (#2766) (ci)
  • refactor(observe/android): consolidate scattered telemetry/crash ingestion in AndroidCtrlProxyClient behind SdkEventIngestor (#2764) (android)
  • refactor(observe/ios): extract wire-decode module + IosSdkEventIngestor from 2147-line IOSCtrlProxyClient (#2763) (ios)
  • refactor(observe): standardize AdbClientFactory injection, remove factory-vs-executor sniff across 11 observe classes (#2754) (android)
  • refactor(models): introduce BaseActionResult to collapse ~65 duplicated action Result types (#2753)
  • refactor(android): finish WebSocketServer typed-handler migration in control-proxy (retire LegacyWebSocketRequest) (#2752) (android, dead-code)

Fixed

  • Daemon shutdown mid-startup-migration doesn’t await in-flight migrations before closeDatabase() (#3044)
  • JimpCliBackend wiring + drop @jimp/wasm-webp + Windows smoke (closes #2974) (#3012) (performance, javascript)
  • Windows CI: databaseLazyPath + dbWriteBarrierResetOnClose file-DB tests still flake (EBUSY/livelock) despite #2916/#2923 (#2992)
  • jimp image tests fail locally (bun/macos-arm64) while passing in CI (#2971) (javascript)
  • test(nav): isolate NavigationGraphManager.test.ts singleton-backed blocks to fix cold-first-run flakiness (#2969)
  • fix(db): transactionalize promoteSuggestion + recordHierarchyNavigation graph writes (siblings of #2791) (#2968) (database)
  • Flaky CI: windows-latest file-backed SQLite close/reopen tests (EBUSY/livelock) intermittently fail (#2916) (database)
  • Flaky CI: DefaultProcessExecutor “exec captures stdout” times out (30s) on macos-latest; spawns real subprocess (#2914)
  • iOS runner: widen gesture request coordinate fields to Double (Int decode + roundCoordinates:false is a latent robustness gap) (#2909) (ios)
  • fix(db): migration columns store literal “datetime(‘now’)” instead of a timestamp (48 columns, 24 migrations) (#2895) (database)
  • fix(db): route NavigationGraphManager shutdown write through the DB-write barrier without perturbing nav/hierarchy ordering (follow-up to #2792) (#2885) (maintenance, database)
  • fix(db): wrap FailureAnalyticsRepository.recordFailure in a single transaction (close count-ahead-of-occurrence window) (#2877) (database)
  • fix(cli): direct-mode DB guard transiently over-refuses during daemon startup (publish dbPath before DB open) (#2871) (database)
  • fix(daemon): daemon process detection is POSIX-only (ps), breaking singleton enforcement + forcing direct-mode guard fail-open on Windows (#2870)
  • fix: 6 remaining TS2304 out-of-scope identifiers (2 latent runtime ReferenceErrors in Capture/RestoreSnapshot) (#2866)
  • fix(cli): refuse –no-proxy/–direct when a live daemon already owns auto-mobile.db (#2795) (database)
  • fix(db): guard runMigrations with a cross-process lock so two DB openers can’t trip a spurious startup failure (#2794) (database)
  • fix(db): drain in-flight DB writes before closeDatabase() so shutdown cannot strand on Kysely ConnectionMutex (#2792) (maintenance, database)
  • fix(db): make NavigationGraphManager.recordNavigationEvent graph write transactional (#2791) (database)
  • fix(db): non-transactional get-or-create / read-modify-write races across coverage, navigation, prediction, and appearance repositories (#2790) (database)
  • fix(db): add UNIQUE index on failure_groups.signature and make recordFailure an atomic upsert (#2789) (database)
  • fix(db): reset failed migrationsPromise and surface a cached startup error synchronously so a floating rejection can’t kill the daemon (#2786) (database)
  • fix(db): destructive migration auto-recovery (default-on) can DROP every table on a populated database (#2785) (database)
  • fix(daemon): make startup DB/migration failure fatal so the daemon doesn’t run query-dead while reporting healthy (#2784) (database)
  • fix(talkback): FocusNavigationExecutor.navigateToElement throws ReferenceError on zero-swipe path (accessibilityService out of scope) (#2765) (android, a11y)
  • fix(ios): setDeviceState binary Do Not Disturb does not verify on iOS 18.6 simulator (notifyutil read-back unchanged) (#2545) (ios)

Other

  • Support subscriber-controlled iOS hierarchy polling cadence (#3381)
  • startDevice reports a device as booted before the OS has finished booting (#3334)
  • Add configurable live observation cadence for stream subscribers (#3333)
  • Flaky: stripToolResultWireBoundary.test.ts DEBUG-gate trace fails under full-suite ordering (#2962 test) (#3256) (flaky test, testing)
  • Investigate dead replayTools / ReplayToolsService surface (#3209)
  • Add focused ToolRegistry pipeline collaborator coverage (#3208)
  • fix(db): resolve #3176 migration typecheck errors and ratchet baseline down (#3204)
  • refactor(doctor): fold ios.ts local createExecResult clone into canonical createExecResult (#3200)
  • typecheck gate hardening: signature-swap blind spot, base-drift UX, exact TS pin, test/** scope (#3196)
  • typecheck burndown: resolve TS2300 CtrlProxyHierarchy + TS2305 missing-export clusters (ratchet #3172 AC#3) (#3195)
  • control-proxy: tighten LaunchCancellationScanner to flag conditional rethrows in broad catches (#3192) (android)
  • control-proxy: generalize CancellationException-swallow scan beyond the curated suspend-fn list (#3191) (android)
  • Follow up: clear hierarchy request owners after uncorrelated observe completions (#3190)
  • ci(image): investigate intermittent Ubuntu Bun image runtime smoke null-reference failure (#3189)
  • Follow up physical iOS all reset for every XCUIProtectedResource (#3188)
  • test-infra: decide keep-vs-retire the unit-test DB guard’s opt-in fallback (flag + preload + #3117 tripwire) after arm-by-default (#3140 follow-up) (#3185)
  • perf(db): cap structured-JSON large-text columns at the telemetry backfill boundary (os/layout/failure) (#3182) (performance, database)
  • Track control-proxy lintDebug failures (#3181)
  • perf(telemetry): capture & emit prior UserDefaults value from iOS CtrlProxy runner (follow-up to #3000) (#3174) (performance)
  • Normalize storage_events.value_type vocabulary across iOS/Android (#3173) (database)
  • Add a scoped tsc –noEmit typecheck gate for src/ (fail on new errors) (#3172)
  • iOS SDK storage_changed never captures real key/value/type (KVO emits nil/”unknown”) (#3171) (database)
  • test(db): use bounded temp DB cleanup in synchronous pragma readback test (#3160) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3158) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3157) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3156) (database)
  • chore(db): normalize MemoryBaselineManager retention comparison (datetime()) to match #2937 (#3155) (database)
  • follow-up(ios): finish DeviceAppManager variable cleanup in IOSCtrlProxyManager (#3150) (ios)
  • Reduce MCP output token cost for agentic runs (inert –actions-no-observe, element subtree bloat, pretty-printed JSON) (#3141)
  • test-infra: make the unit-test DB guard arm-by-default (opt-out) instead of preload-opt-in (#3083 follow-up) (#3140)
  • perf(db): shared batched telemetry ingestion path (buffer + multi-row INSERT + shared EventRetentionPolicy) (#3138) (performance, database)
  • chore(db): converge telemetry-event retention onto the canonical offset(N-1)+id-tiebreak idiom (#3137) (database)
  • chore(db): extract a shared cleanupIfNeeded retention helper for the six event repos (#3136) (database)
  • test(ios): unit-test the physical-reset permission→XCUIProtectedResource mapping table (#3134) (ios, testing)
  • Android CtrlProxy: add behavioral test for EXTRACT_HIERARCHY error-frame emission (#3089 follow-up) (#3131) (android)
  • Android CtrlProxy: commandReceiver outer catch swallows CancellationException (#3130) (android)
  • Guard-test the ‘side-effects outside fn’ convention for runBothReposInTransaction (follow-up to #3075) (#3129)
  • Make ServiceScopeGuard correlation structural for raw serviceScope.launch (follow-up to #3104) (#3128) (android)
  • Add fallback-to-back-button test for DefaultUIStateSetup.dismissTopModal bottom-sheet branch (#3125)
  • refactor(ios): reduce launchApp / launchWithPayloadUrl drift in DeviceAppInspector (#3123) (ios)
  • refactor(ios): DeviceAppInspector name no longer reflects its scope (install/launch/terminate/open-URL) (#3122) (ios)
  • ci(ios): ‘Daemon failed to start within 10000ms’ flake in XCTestRunner — 10s readiness budget too small on cold macOS runners (#3110) (ios)
  • ci(ios): XCTestRunner videoRecording step fails deterministically — unit-test DB guard (#3082) trips the integration test (#3109) (ios)
  • Optional: ToolRegistry.callInternal(name, args) seam to remove the residual mark-then-call footgun (#3108)
  • Revisit structural-id content-identity adoption (limitation 1) with real-device data; optional pre-move fromKey (#3107)
  • DefaultUIStateSetup.dismissTopModal calls getTool(“swipe”) — never registered, so bottom-sheet swipe-dismiss is dead code (#3106)
  • Enforce/close the raw serviceScope.launch fire-and-forget silent-hang gap (AsyncActionRunner adoption) (#3104) (android)
  • refactor: ActionableError sweep for OpenURL / DeviceAppInspector / DeviceCtlClient result-error family (#3102)
  • refactor(ios): fold DeviceCtlClient open-URL primitive into DeviceAppInspector (dedup devicectl wrapper) (#3099) (ios)
  • Flaky: IOSCtrlProxyManager “externally managed test-without-building runner” test times out at ~5s on macOS CI (#3098)
  • observe/android: consider short-circuiting verifyServiceReady retries on a deterministic runner handler failure (#3097) (android)
  • Android CtrlProxy: correlate the ADB-broadcast fallback hierarchy request (sync_ uuid) into the wait (#3089) (android)
  • Enforce broadcast-helper guard adoption (ResultBroadcaster/AsyncActionRunner) so #3045/#3023 can’t silently regress (#3085) (android)
  • test-infra: fire-and-forget TelemetryRecorder guard-throw surfaces as an unhandled rejection, not a deterministic test failure (#3084)
  • test-infra: unit-test DB guard fails open if the bun test preload is skipped (#3083)
  • Follow-ups from withFileBackedDb harness (#3046/PR #3078): enforcement + generic cleanup + optional hooks binder (#3081)
  • docs: document the AUTOMOBILE_DB_* env-var family (follow-up from #3065/#3071) (#3079)
  • fix(ios): surface devicectl stderr diagnostic (not just “Command failed”) on physical terminate failure (#3077) (ios)
  • refactor(ios): extract a shared “process already gone” terminate-error matcher (simctl + devicectl) (#3076) (ios)
  • Extract shared two-repo runInTransaction helper for NavigationGraphManager (follow-up to #2980) (#3075)
  • test: pin the sdkNavigationAppIds skip mechanism in the SDK-screen-name preservation test (#3068)
  • test-infra: guard against unit tests resolving the real file-backed getDatabase() (#3067)
  • Guard against production AUTOMOBILE_DB_PATH=:memory: (migrated-but-empty app connection footgun) (#3065)
  • test(observe): “getLatestHierarchy > should preserve SDK screen names when hierarchy updates follow navigation events” fails on main (#3063)
  • observe/android: let requestHierarchySync surface the runner error text instead of collapsing to null (#3062) (android)
  • Android CtrlProxy: correlate request_hierarchy_if_stale (stale_ id) error frames into the hierarchy wait (#3061) (android)
  • Tech-debt: consider a protected SharedGestureDelegate.coord() so Android-only gesture overrides reuse the shared rounding (#3049) (android)
  • Test coverage: two-finger swipe concurrency + error-frame (type:”error”) resolution path (#3048) (android)
  • Move dbWriteBarrierResetOnClose barrier test to a :memory: sentinel DB (eliminate the file-handle flake class) (#3047)
  • Shared withFileBackedDb test harness to enforce the DB-lifecycle flake-avoidance pattern (#3046)
  • Silent-hang when a broadcast helper’s own broadcast() throws (pre-existing, #3023-adjacent) (#3045) (android)
  • Enforce “new async actions get correlated-error-on-throw for free” structurally (#3023 follow-up) (#3043) (android)
  • Add production-wiring guard test for CtrlProxy async launch sites (#3023 follow-up) (#3042) (android)
  • Cleanup: minor follow-ups from ImageBackend consumer migration (#3009 / PR #3036) (#3041) (javascript)
  • test(ios): cover TerminateApp observed-interaction path + fix perf.end() tree ownership (#3037) (ios)
  • Android CtrlProxy error-envelope: hierarchy handler failures still hang the awaiter (type:”error” not routed into waitForFreshData) (#3032) (android)
  • Harden: plan retry can exceed the 10-min CI step cap if an attempt hits the outer 300s callTool timeout (#3029) (ios)
  • iOS observe cold-bring-up waitFor timeout: fix root cause behind the Reminders launch/add retries (#3028) (ios)
  • Refactor: hoist RemindersIntegrationBase retry into a shared defaultRetryCount hook (#3027) (ios)
  • Android CtrlProxy: async action failures inside launched coroutines still hang the awaiter (#3023) (android)
  • Android CtrlProxy error-envelope: iOS parity (rewriteUnknownCommandError, out-of-range legibility, targeted send) (#3022) (android)
  • Android CtrlProxy: decode failures send no wire error frame (silent drop) — mirror iOS #2986 field-attributed decode errors (#3017) (android)
  • Minimal Bun repro for sharp 0.35.x-under-Bun abort (non-blocking upstream) (#3014) (dependencies)
  • doctor image-backend check + cache-portability contract docs (#3013) (devxp, javascript)
  • cwebp/dwebp provisioning: bundle libwebp binaries + CliWebpCodec (#3011) (devxp, javascript)
  • SharpBackend + pin sharp 0.34.5/@img + dependabot ignores + build externals (macOS/Linux) (#3010) (performance, dependencies, javascript)
  • Migrate pixel consumers (PerceptualHasher/ScreenshotComparator/ContrastChecker/image-utils) to ImageBackend (#3009) (javascript)
  • Image backend seam: ImageBackend interface + declarative ImageTransformer + FakeImageBackend (#3008) (devxp, javascript)
  • ktfmt: make version-pin comparison robust to 2-part vs 3-part version strings (follow-up to #2993) (#3004)
  • ktfmt: make merge.yml full-tree ktfmt a branch-protection required check (follow-up to #2966) (#3003)
  • fix(ios): recordStorageEvent call passes undeclared ‘operation’ and omits required valueType/changeType (masked by Bun no-typecheck) (#3001) (database)
  • perf(telemetry): emit prior storage value from CtrlProxy runners to skip recordStorageEvent lookup (#3000) (performance, database)
  • Flaky: XCTestRunner Simulator ‘RemindersLaunchPlanTests’ observe waitFor timeout reds non-required CI (#2998) (ios)
  • Tech debt: extract shared bind-both-repos transaction helper in NavigationGraphManager when a 4th caller lands (Devin §4) (#2994)
  • iOS parity: guard non-finite pinch rotationDegrees in CtrlProxy CommandHandler (mirror Android #2964 / PR #2984) (#2991) (testing)
  • Android two-finger swipe result correlation is orphaned — resolves only via 5s timeout (handleTwoFingerSwipeResult has no caller) (#2988) (android)
  • iOS runner: extend decode-error legibility to typeMismatch/valueNotFound (field-attributed) — #2965 option 2 (#2986) (ios)
  • Android CtrlProxy runner swallows decode/handler failures — no error envelope sent to client (#2985) (android)
  • Make NavigationGraphManager.promoteSuggestion atomic (partial-write on mid-sequence throw) (#2981)
  • Harden recordHierarchyNavigation: guard + transactionalize the coverage-repo enlistment (follow-up to #2968) (#2980)
  • validate_ktfmt.sh: add set -euo pipefail + explicit process-substitution error handling (#2967)
  • ktfmt: enforce the pinned formatter version so version drift can’t silently land on red main (#2966)
  • iOS runner: opaque decode-boundary error for out-of-range numeric literals (1e309) — surface an actionable message (#2965) (ios)
  • Android runner: reject non-finite gesture coordinates (isFinite guard) — mirror iOS #2928, load-bearing on the kotlinx wire (#2964) (android, testing)
  • refactor(ios): merge redundant CtrlProxyVoiceOverActionResult into CtrlProxyActionResult (#2956) (ios)
  • test(ios): make control-proxy wire-parity scan structural (AST) + import-graph-derived, not regex/adjacency-based (#2955) (ios, testing)
  • test(ios): field-name wire-parity backstop for control-proxy (JSON snapshot fixtures) (#2954) (ios, testing)
  • test(db): tripwire so a non-Windows bun:sqlite handle-leak can’t hide behind removeTempDbDir’s silent give-up (#2949) (database)
  • test(db): consolidate remaining sync best-effort temp-dir cleanup (backupDatabaseFile) into a removeTempDbDirSync helper (#2948) (database)
  • refactor(utils): consolidate DefaultProcessExecutor / DefaultHostCommandExecutor duplication + unify exec-seam type export (#2945)
  • refactor(db): extract a single EVENT_TABLES constant to de-duplicate the telemetry event-table list (follow-up to #2918) (#2943) (performance)
  • Add real-pixel regression tests for the jimp image pipeline (#2939) (testing, javascript)
  • chore(db): upgraded-DB parity for updated_at defaults (repair migration + relax type) (#2937) (database)
  • iOS runner: reject non-finite gesture coordinates (isFinite guard) at the decode/handler boundary (#2928) (ios)
  • Android runner: widen gesture request coordinate fields to Double (symmetric to iOS #2909) (#2927) (android)
  • chore(db): reconcile updated_at columns declared notNull with no default (asymmetric with created_at) (#2913) (database)
  • perf(db): add a CI drift guard for the telemetry event tables’ index inventory (follow-up to #2893) (#2908) (performance)
  • Follow up Codex skill metadata location for .agents wrapper (#2901)
  • perf(db): drop now-redundant single-column device indexes on telemetry event tables (follow-up to #2788) (#2893) (performance)
  • test(ios): hermetic LaunchApp-level coverage for clearAppData on a physical device (#2884) (ios)
  • Testing: regenerate #2755 observe baseline from a raw capture to exercise node-trim on real data (#2879) (performance, testing)
  • docs(db): document migration corrupted-recovery flow + AUTOMOBILE_MIGRATION_RECOVERY (=true vs =1) semantics (#2869) (documentation, database)
  • fix(db): duplicate date-prefixed migration filenames make Kysely ordering fragile (#2868) (database)
  • Guard MIGRATION_RUNTIME_DEPENDENCIES against drift from migration runtime imports (#2867) (devxp)
  • notifyutil: verify whether the -1 registration is actually required for notify_set_state (helper + comments may overstate it) (#2864) (ios, devxp)
  • Reminders add-reminder plan is pinned to CI’s iOS Reminders labels (Done/New Reminder, English) (#2855) (flaky test, ios, testing)
  • Daemon startup DB migration hard-fails when bunx extraction is missing a transitive dep (e.g. kysely) (#2833)
  • nightly: PR title/body don’t reflect a runner-only SHA256 change (#2816)
  • iOS: bake a version constant into the XCTestRunner SPM package (#2814)
  • Enforce the version pin across a reused/shared daemon (PID-file stamp + client mismatch fail) (#2812)
  • Flaky: RemindersAddPlanTests.testAddReminderPlan (UI ‘Done’ tap race at plan step 5) (#2811) (flaky test, ios, testing)
  • Versioning: resolve (or formally accept) the -SNAPSHOT coordinate divergence for local Gradle builds (#2807)
  • Release integrity: store iOS runner SHA256 per registry entry (not a global scalar) (#2806)
  • perf(db): WAL hygiene — set journal_size_limit and checkpoint(TRUNCATE) on close (#2802) (performance, database)
  • perf(db): truncate request/response bodies in the getNetworkEvents list projection (#2801) (performance, database)
  • perf(db): batch N+1 query fan-out in getFailureGroups and getTestRuns (dashboard read paths) (#2800) (performance, database)
  • perf(db): amortize per-insert retention COUNT(*) in event repositories (#2799) (performance, database)
  • perf(db): add covering index for recordStorageEvent previous-value lookup (#2798) (performance, database)
  • perf(db): add a bounded prepared-statement cache to the Bun SQLite dialect (#2797) (performance, database)
  • perf(db): add composite (device_id, timestamp) indexes to telemetry event tables to eliminate ORDER BY filesorts (#2788) (performance, database)
  • perf(db): set PRAGMA synchronous = NORMAL under WAL to stop per-commit fsync on the telemetry write stream (#2787) (performance, database)
  • Output reduction 0: measurement harness (fixture + byte-breakdown script) (#2755) (devxp, performance, testing)
  • Provide hermetic single-version CI pinning for all clients (daemon + ctrlproxy APK/IPA + junit-runner + XCTestRunner) (#2746)
  • Release integrity: iOS runner-binary checksum never wired (verification disabled) + no version-equality release gate (#2745)
  • Shared per-uid daemon socket is unguarded for non-TS clients (JUnit/XCTest) — add server-side version/build-identity handshake (#2744)
  • Multiple checkouts share one per-uid daemon socket → wrong-build daemon serves frontend (version skew, opaque “Unknown tool” -32603) (#2732)
  • Evaluate Compose interop hidden-region text heuristic with real-world data (#2634)
  • feat(ios): invoke custom accessibility actions via tapOn (#2265)
  • No loading-awareness when refreshing element position before tap (#1949)

[v0.0.40] - 2026-06-30

Added

  • Cross-platform tool to read/write app preferences (adb prop / SharedPreferences / iOS UserDefaults) (#2714)
  • install.sh should detect and help install the required Android SDK platform (compileSdk) (#2680)

Fixed

  • doctor reports all-green while iOS observe is broken (no client↔runner round-trip check) (#2693)
  • iOS CtrlProxy forced-restart recovery should use PortManager to clear processes bound to the target port (#2692)
  • iOS CtrlProxy port management collides with adb; client and runner ports diverge (#2691)

Other

  • Stamp git SHA into pre-release daemon version so the version gate distinguishes dev builds (#2738)
  • Verify build-mismatch daemon restart doesn’t worsen the #2599 session-wedge for sibling MCP sessions (#2737)
  • doctor: surface daemon build identity (entryScript / buildId) to spot wrong-build skew (#2736)
  • doctor: iOS round-trip check can’t detect runner/client port mismatch (#2735)
  • fix(ios): simulator runner ignores allocated port (binds 8765) when Android is connected → client/runner port mismatch, all iOS ops fail (#2731)
  • Daemon log file is unlinked by bunx temp-dir cleanup; on-disk logs end up empty (#2724)
  • openLink times out at 30s on slow deeplinks, then logs success=true after the timeout (#2723)
  • Emulator launches windowed by default; aborts with opaque “code: null” on headless hosts (#2722)
  • Headless daemon start fails 10s budget: open -a Simulator → OSLaunchdErrorDomain Code=125 in no-GUI launchd session (#2721)
  • Remove heapdump native addon dependency for Node 26 compatibility (#2719)
  • iOS CtrlProxy reconnect cooldown is very long (~137s) and observe gives no ‘reconnecting’ signal (#2695)
  • Demote/clarify WARN: ‘Failed to read simulator app bundle for …XCTestServiceApp’ during iOS setup (#2694)
  • iOS CtrlProxy runner reports 320x480 screen (missing launch screen) instead of real device size (#2683)
  • iOS highlight (SDK path): verify/fix coordinate scaling so highlights land on the correct element (#2682)
  • iOS highlight: remove non-SDK runner-overlay fallback and report honestly that it requires the AutoMobile SDK (#2681)
  • doctor: add iOS CtrlProxy runner check so iOS gives the same certain feedback as Android (#2678)

[Unreleased]

Fixed

  • iOS highlight: remove the non-functional runner-overlay fallback and report honestly that highlighting requires the in-app AutoMobile SDK (#2681) (ios)

[v0.0.39] - 2026-06-29

Added

  • Implement iOS Simulator app-container file management (#2571)
  • Implement Android app-container file management (#2570)
  • Add internal app file management service abstraction (#2569)
  • Design platform-neutral app file MCP API (#2568)
  • feat(ios): highlight — visual element highlight overlay on iOS (#2502) (ios)
  • feat(ios): mockNetwork — register mock network response rules via URLProtocol (#2500) (ios)
  • feat(ios): sqlQuery — SQLite database inspection on iOS via the in-app SDK HTTP server (#2498) (ios)
  • feat(ios): changeLocalization — locale/timezone/calendar on physical iPhones (#2492) (ios, research)
  • feat(ios): pressButton — volume_up/volume_down/power hardware buttons (#2485) (ios)
  • feat(ios): shake — simulate device shake gesture via XCUIDevice.shake() (#2484) (ios)
  • feat(ios): executeGesture — multi-finger / VoiceOver multi-finger swipe via XCPointerEventPath (#2483) (ios, a11y)

Changed

  • Consolidate duplicated device-vs-session resolution in SocketServer.getRequestArgumentScopeKey (#2664)
  • Trim over-broad Random/Backoff utils and unify three UUID sources onto IdGenerator (#2663) (dead-code)
  • iOS network mock-rule sync is copy-pasted from Android (require() in ESM, any-typed, debug-swallowed) (#2662) (ios)
  • appFileService: replace positional-boolean params in executeAndroidAppFileCommand with options object (#2660) (android, devxp)
  • Refactor oversized orchestrators: split TapOnElement.ts (1.6k lines) and toolRegistry.ts (909 lines) (#2659)
  • Establish & document an error-handling convention (throw vs return vs log-and-continue) (#2657)
  • Refactor: de-duplicate DevicePool assignment methods (LRU drift) + remove left-in [DEVICE-POOL-DEBUG] logging (#2656)
  • Type safety: replace any in navigation hierarchy logic with existing ViewHierarchyNode type (#2655)
  • Dead Code Detection: Threshold Exceeded (#2361) (automated, dead-code)

Fixed

  • AndroidSystemConfigurationAdapter.setTimeZone reports success without read-back verification (#2661) (android)
  • fix(ios): postNotification requires appId on iOS but the schema marks it optional (#2544) (ios)
  • fix(ios): SDK in-app hierarchy (:8766) merged into observes of unrelated foreground apps — ~2.5MB hierarchies (#2540) (ios)
  • fix(intellij): #2464 device-disconnect deviceEvents wired only to uncalled LayoutInspectorDashboard (live view may still freeze) (#2531) (intellij plugin)

Other

  • doctor: make daemon health socket probes non-destructive (#2658)
  • putAppFile resolves a relative sourcePath against the daemon cwd (homedir), not the launch cwd — ENOENT/wrong-file under a detached daemon (#2644)
  • doctor: reports ‘Daemon is not running’ while it is serving, and prints device=emulator-5554 during an iOS-only run (#2643)
  • recentApps on iOS reports success but doesn’t reach the App Switcher (lands on cover-sheet/home) (#2642)
  • launchApp returns a stale embedded observation (pre-transition app) — follow with a fresh observe (#2641)
  • clipboard get on iOS can return a stale in-memory ‘shadow’ value, masking a failed/changed real read (#2640)
  • pinchOn returns ‘not supported on iOS yet’ even though the iOS runner advertises request_pinch (#2639)
  • Daemon DisconnectMonitor churns on phantom/removed devices: stale ‘Failed to stop recording’ every ~5s + repeating miss counts (+ emulator resurrection) (#2638)
  • iOS SDK: network-mock enforcement compiles into RELEASE builds (mock short-circuit sits outside #if DEBUG) (#2637)
  • Generated schemas/tool-definitions.json is missing 10 production tools — generator skips 5 register*Tools categories (#2636)
  • Pre-commit hook crashes: planYaml.ts uses js-yaml APIs removed in v5 (blocks all commits) (#2635)
  • Clarify maxDurationSeconds behavior for iOS stream-copy remux (#2627)
  • Add iOS simulator videoRecording start-stop MP4 integration test (#2628)
  • Keep plan-executable tools available inside criticalSection (#2614)
  • highlight on iOS has no working path for non-SDK apps: runner-overlay fallback disabled by default (AUTOMOBILE_IOS_LIVE_HIGHLIGHTS) (#2607)
  • videoRecording stop fails on iOS simulator: mov→mp4 FFmpeg finalize produces no output and the error hides the cause (#2606)
  • getAppPermissions fails on iOS simulator: sqlite3 called with ‘.mode json’ + SQL in one positional arg (‘extra argument’) (#2603)
  • Daemon restart desyncs connected MCP clients: all tool calls + resource reads return opaque ‘Session not found’ with no auto-recovery (#2599)
  • clipboard get on Android returns empty success when the read is denied by ClipboardService (background a11y), and cmd clipboard fallback doesn’t exist (#2596)
  • changeLocalization silently fails on Android: reports success but the system locale never changes (invalid ‘cmd locale set-locales’, no-op fallback, no verification) (#2595)
  • sqlQuery: INSERT/UPDATE/DELETE … RETURNING on Android commits the mutation but returns an error (RETURNING not recognized by isReadQuery) (#2594)
  • CtrlProxy APK refresh blocks every tool call on slow/no network (~30s each); local ops like sqlQuery hang offline (#2590)
  • tool_calls.duration_ms is never populated (NULL for all rows) — per-call timing not recorded (#2588)
  • iOS startDevice/listDeviceImages returns “Available images: none” despite a booted, available simulator (#2572)
  • MCP tool errors discard subprocess stderr / daemon-log context, surfacing only opaque messages (#2562)
  • Multi-daemon detection false-positive: a single daemon’s own shell wrapper is counted as an “other” daemon (#2561)
  • Daemon inherits spawner cwd; a deleted cwd makes forked children fail ENOENT, misreported as “Android emulator not found” (#2560)
  • Concurrent instances crash on startup with SQLiteError: database is locked (no busy_timeout) (#2559)
  • openLink lacks an MCP request-timeout floor; slow deeplinks fail with -32001 (#2558)
  • junit-runner and manager.ts hardcode @latest, defeating consumer version pinning (#2386)
  • Detect Compose interop content hiding and signal OCR fallback (#2374)
  • launchApp rejects ‘packageId’ parameter — LLM commonly uses wrong field name (#2217)

[v0.0.38] - 2026-06-25

Added

  • feat(android): accessibilityFocus — set/clear TalkBack cursor focus (#2503) (android, a11y)
  • feat(ios): biometricAuth — Touch ID / Face ID simulation via simctl Darwin notifications (#2497) (ios)
  • feat(ios): getNotificationPolicy — read per-app notification authorization on simulators via BulletinBoard (#2496) (ios, research)
  • feat(ios): postNotification — deliver simulated push to target bundle via simctl push (#2495) (ios)
  • feat(ios): deviceSnapshot — capture and restore simulator settings (includeSettings) (#2494) (ios)
  • feat(ios): setDeviceState — Do Not Disturb mode fidelity and physical-device support (#2493) (ios, research)
  • feat(ios): getDeepLinks — URL scheme & universal link discovery via Info.plist (#2486) (ios)
  • feat(ios): dragAndDrop — coordinate drag via XCUITest CtrlProxy runner (#2481) (ios)

Fixed

  • fix(ios): daemon runs the published-release CtrlProxy runner, not source — new runner commands fail “Unknown command type” against a stale binary (#2539) (ios)
  • fix(ios): CtrlProxy WebSocket and AutoMobile SDK server collide on port 8766 — all iOS observe/gesture ops fail (Expected 101) (#2538) (ios)
  • fix(daemon): signal/exception handlers registered inside main() after dynamic imports — startup window with no cleanup (regression from #2465) (#2532) (release engineering)
  • fix(ios): observation stream double-pushes initial hierarchy frame on cold subscribe (#2530) (ios)

Other

  • Client can silently use a daemon of a mismatched version (@latest spawn + restart cooldown) (#2452)
  • Crash/force-kill leaves stale PID and socket files; no exit-time cleanup (#2451)
  • Device disconnects are not surfaced to observation-stream subscribers (#2450)
  • Screenshot backoff stops after initial burst; live view freezes on static screens (#2449)
  • Observation stream pushes no initial frame on subscribe; idle devices show blank (#2448)
  • Observation-stream request_observation command is a no-op; socket clients cannot force a frame (#2447)
  • Daemon stream socket paths are not discoverable, causing silent connect failures on env mismatch (#2446)
  • Device pool never prunes shut-down devices, wedging discovery until daemon restart (#2445)
  • Daemon readiness inferred from PID/socket-file existence, not an actual connection (#2444)
  • Device held ~30s when a client dies before its first heartbeat (#2443)
  • iOS device pool never auto-boots an installed-but-shutdown simulator to satisfy criteria (#2442)
  • Daemon version skew is only reconciled one direction; stale daemon can serve newer clients (#2441)
  • Add a fast --version flag; today it hangs by falling through to the stdio server (#2440)

[v0.0.37] - 2026-06-24

Other

  • No changes.

[v0.0.36] - 2026-06-23

Other

  • installApp succeeds but app not present for launchApp/openLink (device resolution incoherence) (#2387)

[v0.0.35] - 2026-06-10

Other

  • launchApp times out on iOS when clearAppData is true (#2368)

[v0.0.34] - 2026-06-04

Other

  • No changes.

[v0.0.33] - 2026-06-04

Other

  • No changes.

[v0.0.32] - 2026-06-02

Changed

  • Dead Code Detection: Threshold Exceeded (#2313) (automated, dead-code)

Other

  • Can’t pin the on-device CtrlProxy release independently of the daemon (#2293)
  • retryIfNoChange fires false-positive retries during activity transitions (#2283)

[v0.0.31] - 2026-05-27

Changed

  • Dead Code Detection: Threshold Exceeded (#1874) (automated, dead-code)

Other

  • Only 2 of 7 daemon CLI flags log a startup confirmation (#2286)
  • CtrlProxy getLatestHierarchy 100ms fresh-data wait too short for contended environments (#2285)
  • Issue 3: SelectionStateTracker ignores --no-ui-perf-mode and dominates CI ADB overhead (#2284)
  • retryTapIfNoChange throws ReferenceError: isTalkBackEnabled is not defined (#2282)
  • Bug: ReferenceError ‘isTalkBackEnabled is not defined’ in tapOn retryIfNoChange path (#2277)
  • bug(ios): observe returns “received Android hierarchy for iOS device” inside conversation views (#2275)

[v0.0.30] - 2026-05-20

Other

  • Remove tapClickableParent from tapOn schema — redundant with auto-escalation (#2248)

[v0.0.29] - 2026-05-20

Other

  • SelectAllText accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2231)
  • InputText accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2229)
  • ImeAction accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2230)
  • PinchOn accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2228)
  • Daemon WebSocket observation-stream setup crashes: AdbExecutor passed to AdbClientFactory consumer (#2224)
  • ClearText accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2226)
  • ExecuteGesture accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2225)
  • Clipboard accessibility-service path crashes: AdbExecutor passed to AdbClientFactory consumer (#2227)
  • Add runtime shape guard to *CtrlProxyClient.getInstance() factories (#2223)
  • observe waitFor screenshot loop: Operation cancelled every ~130ms until session heartbeat timeout (#2216)
  • Navigation screenshot path passes undefined platform causing ‘Unsupported platform’ error (#2215)
  • PerformanceAudit crashes with ‘J.create is not a function’ in 0.0.28 build (#2214)

[v0.0.28] - 2026-05-19

Added

  • feat: Android emulator telephony and SMS simulation (#1579) (android)
  • iOS: Implement ScreenCaptureKit simulator window capture (#1096) (ios)
  • iOS: Implement Swift helper for AVFoundation device capture (#1095) (ios)

Changed

  • refactor: extract test helper for CommandHandlerTests boilerplate (#1879) (ios, testing)

[v0.0.27] - 2026-05-18

Added

  • IDE Plugin: Display exported YAML in Record Test UX after finishing (#1073) (intellij plugin)
  • epic: detect image/media loading via network and view hierarchy correlation (#1015) (android, research, ai)
  • feat: correlate network requests with media views for loading detection (#1014) (android, ai)
  • Extend focus navigation to handle scroll-then-focus for off-screen elements (#472) (android, a11y)

Changed

  • refactor: extract sendCommand helper to eliminate WebSocket delegate boilerplate (#1880)
  • Chore: Test multi-device execution (#764)

Other

  • PlanMigrator: notification.timeout → awaitTimeout (#2120)
  • Plan execution ADB contention: skip screenshots and cancel orphaned jobs (#2119)
  • Tap resilience: ghost tap detection and pre-tap stability (#2118)
  • No way to configure accessibility service flags at runtime (#2099)
  • Reduce ADB overhead during plan execution (#2098)
  • Stability failures with remote emulators and long-running tool calls (#2097)
  • Tapping notifications inside collapsed Android groups opens app generically instead of deep-linking (#2096)
  • Ghost taps - touch events fail to register regardless of input method (#2081)
  • ADB pipe congestion from event-driven hierarchy broadcasts causes off-screen bounds (#2080)
  • No way to opt into observe step capture from CI without modifying test code (#1973)
  • executePlan timeout too short for long UI plans - premature Operation cancelled in CI (#1972)
  • No MCP tool for setting Android SCHEDULE_EXACT_ALARM app op (#1967)
  • No MCP tool for toggling Android Do Not Disturb policy access (#1966)
  • executePlan silently continues past observe waitFor timeout instead of failing the step (#1963)
  • tapOn diagnostics lost when surfaced through executePlan - no visibility into tap mechanics (#1961)
  • Android screenrecord produces corrupt/truncated video files on stop (#1960)
  • Support segmented video recording to chain multiple screenrecord sessions past the 180-second Android cap (#1959)
  • No way to capture per-step observe snapshots for CI debugging (#1958)
  • No opt-in mechanism for pre-tap element stability verification (#1950)
  • Navigation screenshots add constant I/O pressure to CI emulators (#1947)
  • Queued MCP forward requests burn timeout budget while waiting in serialization queue (#1946)
  • HTTP server requestTimeout kills long plans + id:unknown error responses cause silent hangs (#1944)
  • executePlan MCP timeout too short - premature Operation cancelled (#1943)
  • Streamable HTTP SSE auto-reconnect triggers 409 session teardown (#1942)
  • Concurrent MCP socket forwards corrupt shared HTTP session (#1939)
  • Create Homebrew formula for AutoMobile (#978) (release engineering, env)

[v0.0.26] - 2026-05-06

Other

  • WebSocket timeout cascade causes daemon blindness after slow hierarchy extraction (#2079)

[v0.0.25] - 2026-05-06

Other

  • Daemon mode ignores CLI flags (dismiss-keyboard, no-ui-perf, etc.) (#2065)

[v0.0.24] - 2026-05-01

Other

  • observe returns iOS hierarchy despite setActiveDevice to Android emulator (#2053)
  • ensureConnected should check if target simulator is still booted before relaunching CtrlProxy (#2052)

[v0.0.23] - 2026-04-30

Other

  • No changes.

[v0.0.22] - 2026-04-30

Other

  • No changes.

[v0.0.21] - 2026-04-30

Other

  • No changes.

[v0.0.20] - 2026-04-29

Other

  • No changes.

[v0.0.19] - 2026-04-29

Other

  • Daemon leaks unix-domain socket FDs; accepted peers never closed (backpressure + keepalive gap) (#2008)
  • CI cannot configure daemon flags without pre-starting manually - no JUnit runner integration (#1971)
  • No way to programmatically close the notification shade - pressButton “back” is fragile (#1969)
  • No MCP tool for granting Android runtime permissions - permission dialogs block CI tests (#1965)
  • observe waitFor matches wrong element in lists - no way to scope by container (#1962)
  • No screen state captured when executePlan step fails - blind debugging in CI (#1957)
  • tapOn silently taps stale coordinates when accessibility tree changes between observe and tap (#1948)
  • Emulator crash leaves active sessions hanging until full MCP timeout (#1945)
  • ECONNREFUSED on daemon MCP hop due to IPv4/IPv6 mismatch on Linux CI (#1938)
  • Add AutoMobileAPI protocol and default implementation for dependency injection (#1937)
  • Add delegate-based network recording API as primary integration path (#1936)
  • Add configuration options to disable crash/signal handler subsystems (#1935)
  • Add AutoMobileSDK product to root Package.swift for SPM consumers (#1934)
  • iOS SDK walker: surface visual properties for pure SwiftUI shapes via CALayer introspection (#1926)

[v0.0.18] - 2026-04-17

Other

  • iOS: text entry fails despite focused UITextField with react native (#1925)

[v0.0.17] - 2026-04-16

Added

  • startDevice: accept generic parameters and return/boot matching device (#1887)
  • Add resource for installed app metadata (version, build number) (#1886)
  • Support iOS app installation in installApp (#1885) (ios)
  • Add uninstallApp tool (#1884)

[v0.0.16] - 2026-04-03

Added

  • IDE Plugin: Implement screen stream display in Layout Inspector (#1033) (android, ios)
  • Server: Implement screen stream receiver and relay to IDE plugins (#1032)
  • Feature: iOS UserDefaults Inspection and Management (#1022) (ios, devxp, testing)
  • feat: identify media-displaying views in hierarchy by class and role (#1013) (android, a11y)
  • feat: Android version matrix testing in CI (#835) (android, ci, testing)

Changed

  • Dead Code Detection: Threshold Exceeded (#1648) (automated, dead-code)

Fixed

  • tapOn fails to match text with Unicode curly apostrophe (U+2019) (#1798) (ios)
  • Daemon disconnect cascade causes 6GB+ log flood and crash-restart loop (#1773)

Other

  • iOS: Add rotate support via CtrlProxy (#1859)
  • iOS: Add systemTray support via CtrlProxy (#1858)
  • iOS: Add recentApps support via CtrlProxy (#1857)
  • iOS inputText fails with dismissKeyboard enabled: isDismissKeyboardAfterInputEnabled is not a function (#1840)
  • setActiveDevice should allow launchApp when both platforms are connected (#1839)
  • inputText: should not require dismissKeyboard, default to false (#1836)
  • tapOn: error message when ‘action’ is omitted is unclear (#1835)
  • Auto-disable stylus handwriting on Android emulators (#1834)
  • CtrlProxy iOS broken on Xcode 26: checksum mismatch + simctl spawn failure (#1833)
  • startDevice returns generic DEVICE_NOT_FOUND when AVD userdata is corrupt (#1672)
  • feat: iOS simulator live locale changes (SpringBoard restart + AppleLanguages) (#1613)
  • test: increase Android test coverage for changeLocalization (#1612)
  • feat: add setCalendarSystem MCP tool (rename to calendar) (#1611)
  • bug: doctor --ios always fails with “undefined is not an object (evaluating ‘…runtimes.filter’)” on Xcode 26.2 (#1448)
  • ci: run JUnitRunner emulator tests on macOS/Windows/Linux matrix (#959) (android, ci, testing)

[v0.0.15] - 2026-03-26

Other

  • No changes.

[v0.0.14] - 2026-03-26

Added

  • feat: implement iOS clipboard operations (get/copy/paste/clear) (#1501) (ios)
  • feat: add boomerang support to VoiceOverSwipeExecutor (#1451) (ios, a11y)
  • feat: VoiceOver Phase 4 — documentation, example scripts, and parity review (#1366) (documentation, ios, a11y)
  • feat: VoiceOver Phase 3 — accessibility focus tracking and rotor support (#1365) (ios, a11y)
  • feat: VoiceOver Phase 2 — adapt tapOn and swipeOn for VoiceOver gestures (#1364) (ios, a11y)
  • feat: VoiceOver Phase 1 — detection via UIAccessibility.isVoiceOverRunning (#1363) (ios, a11y)
  • feat: AutoMobileBiometrics.overrideResult() SDK hook for deterministic biometric testing (#1362) (android, ios, testing)
  • feat: expand vision fallback to support element search in swipeOn, pinchOn, dragAndDrop (#1361) (android, ios, ai)
  • feat: add accessibility MCP tool to enable/disable TalkBack and VoiceOver (#1360) (android, ios, a11y)
  • feat: TalkBack Phase 4 — accessibility focus tracking in observations and polish (#1359) (documentation, android, a11y)
  • feat: TalkBack Phase 3 — adapt swipeOn to use two-finger swipe and accessibility scroll actions (#1358) (android, a11y)
  • feat: TalkBack Phase 2 — adapt tapOn to use ACTION_CLICK when TalkBack is enabled (#1357) (android, a11y)
  • feat: capture and expose network request logs for media correlation (#1012) (android)
  • feat(ios): Code signing configuration UI in Xcode Companion app (#914) (ios)
  • Implement automated mitmproxy certificate installation for Android (#465) (android, chore)
  • Research mitmproxy integration architecture for automated certificate trust (#464) (android, research)
  • Xcode companion app: menu bar mode for quick access (#407) (ios, devxp)
  • Xcode companion app: execution log and error view (#406) (ios, devxp)
  • Xcode companion app: feature flag toggles (#405) (ios, devxp)
  • Xcode companion app: performance/timing history view (#404) (ios, devxp)
  • Xcode companion app: navigation graph rendering view (#403) (ios, devxp)
  • iOS Managed Apple IDs/profiles: detect restrictions + document test plan guidance (#365) (ios, devxp)
  • iOS Managed App Configuration: surface policy-driven failures + guidance (#364) (ios, devxp)
  • Xcode Source Editor Extension: plan template/run/open commands (#362) (ios, devxp)
  • Xcode companion app: test recording flow + plan generation (#361) (ios, devxp)
  • Xcode companion app: MCP transport selection + dev server discovery (#359) (ios, devxp)
  • Xcode companion app: scaffold macOS app + MCP connection shell (#358) (ios, devxp)
  • IDE plugin: sandbox testing and runIde validation (#259) (devxp, intellij plugin)
  • IDE plugin: backwards compatibility + matrix testing (#245) (release engineering, testing, intellij plugin)
  • Add iOS support for accessibility audit mode (#103) (ios, a11y)
  • mitmproxy network call inspection (#34)

Changed

  • chore: extend lychee link checking to cover CONTRIBUTING.md and root markdown files (#1457) (ci, devxp)
  • chore: fix CONTRIBUTING.md dead link to local-development.md (#1456) (documentation, dead-code)
  • chore: add git-lfs setup to hot-reload dev environment bootstrap (#1455) (devxp)
  • Dead Code Detection: Threshold Exceeded (#1369) (automated, dead-code)
  • refactor: rename XCTestServiceApp to CtrlProxy and ios directory to control-proxy (#1356) (ios)
  • refactor: rename AccessibilityService to CtrlProxy and gradle subproject to control-proxy (#1355) (android)
  • chore: remove demoMode MCP tool (#1352) (dead-code)
  • refactor: replace rawViewHierarchy tool with raw flag on observe (#1351) (dead-code)
  • chore: remove MCP HTTP transport (#1350) (dead-code)
  • Dead Code Detection: Threshold Exceeded (#1293) (automated, dead-code)
  • Tighten XcodeExtension signing once .appex exists (#921) (ios)

Fixed

  • Startup benchmark flake: FIFO stderr line truncation drops STARTUP_BENCHMARK prefix (#1563) (performance, testing)
  • App view hierarchy disappears when keyboard/EditText is focused (#1488) (android)
  • bug: CtrlProxy reboots multiple times per minute in hot reload and normal MCP use (#1354) (ios)
  • bug: hot reload reboots iOS simulator unexpectedly (#1353) (ios, devxp)

Other

  • feat: iOS simulator support for changeLocalization tool (#1578)
  • Install Fails without SSH Configured (#1559)
  • research: iOS accessibility scroll action equivalent to Android scroll_forward/scroll_backward (#1452) (ios, a11y, research)
  • test: add unit tests for VoiceOverSwipeExecutor (#1450) (ios, a11y, testing)
  • Release: sign + notarize macOS companion app (#375) (ios, release engineering, devxp)
  • CI: add macOS job for Xcode companion app + Source Editor Extension build (#373) (ios, ci)

[v0.0.13] - 2026-02-13

Other

  • Add CI checks for host control Docker scripts across macOS/Linux/Windows (#981) (ci, env)
  • Publish to official MCP registry (#26) (release engineering)
  • Publish AutoMobile on Docker Hub (#25) (release engineering)

[v0.0.12] - 2026-02-11

Other

  • No changes.

[v0.0.11] - 2026-02-11

Added

  • IDE plugin: always use active (white) toolbar icon (#1214) (intellij plugin)
  • Remove feature flag for video test recording (#1203) (video)
  • IDE plugin: show ‘Device Disconnected’ when observed device becomes unavailable (#1202) (intellij plugin)
  • IDE Plugin: Add full-window FileEditor mode for dashboard (#1167) (intellij plugin)
  • feat: iOS version matrix testing in CI (#836) (ios, ci, testing)
  • Support custom accessibility rules (#104) (devxp, a11y)

Changed

  • refactor: ViewHierarchy has near-clone findFocusedElement / findAccessibilityFocusedElement (#1191)
  • refactor: UIStateExtractor reimplements ElementParser traversal and property extraction (#1190)
  • refactor: BugReport.traverseNode() reimplements ElementParser inline (#1189)
  • refactor: DebugSearch reimplements ElementParser, TextMatcher, and ElementFinder inline (#1188)
  • chore: upgrade GitHub Actions upload-artifact and download-artifact to v4.6+ (#1158) (ci)
  • Dead Code Detection: Threshold Exceeded (#1143) (automated, dead-code)

Fixed

  • IDE plugin: device disconnected notification is too aggressive (#1244) (intellij plugin)
  • iOS: toggle switch tap does not trigger view hierarchy or screenshot update (#1227)
  • bug: IDE plugin settings page fails to load feature flags with MCP error -32603 (#1213) (intellij plugin)
  • Bug: IDE plugin crashes with IllegalArgumentException when opening test plan YAML file (#1205) (intellij plugin)
  • Bug: failing JUnit Runner test does not produce a failing JUnit test result (#1204) (testing)
  • iOS: Unable to observe system permission dialogs in view hierarchy (#1147) (ios)

Other

  • CI: add Xcode 26 to iOS build and test matrix (#1207) (ios, ci)
  • CI: auto-retry iOS jobs when no simulator runtimes are installed on macOS runner (#1206) (ios, ci)
  • CI: add macOS job for iOS Accessibility Bridge build + XCTest runner tests (#372) (ios, ci)
  • Publish AutoMobile Android SDK on Maven Central (#122) (android, ci, release engineering)
  • Publish AutoMobile JUnitRunner Library (#121) (android, ci, release engineering, testing)

[v0.0.10] - 2026-02-06

Added

  • Support custom accessibility rules (#104) (devxp, a11y)

Other

  • chore: upgrade GitHub Actions upload-artifact and download-artifact to v4.6+ (#1158)
  • Publish AutoMobile Android SDK on Maven Central (#122) (android, ci, release engineering)
  • Publish AutoMobile JUnitRunner Library (#121) (android, ci, release engineering, testing)

[v0.0.9] - 2026-02-04

Added

  • Test Runners: Cascade MCP tool failures to JUnitRunner/XCTestRunner via executePlan response (#1078) (android, ios, testing)
  • IDE Plugin: Add Cancel button to Record Test entry screen (#1075) (intellij plugin)
  • IDE Plugin: Add ‘Refine’ button to simplify exported test plans with AI (#1074) (intellij plugin, ai)
  • IDE Plugin: Merge Exploratory Test into Record Test UX (#1072) (intellij plugin)
  • IDE Plugin: Expose startTestRecording MCP tool (#1071) (intellij plugin)
  • IDE Plugin: Expose exportPlan MCP tool for Finish Recording (#1070) (intellij plugin)
  • [IDE Plugin] Wire up StreamingFailuresDataSource for real-time failure updates (#1066) (intellij plugin)
  • [SDK] Add handled exceptions API for non-fatal error reporting (#1065) (android)
  • [IDE Plugin] Implement RealStorageDataSource for key-value storage inspection (#1064) (intellij plugin)
  • [MCP Server] Add storage inspection tools and Unix socket push channel for key-value data (#1063)
  • [AccessibilityService] Add WebSocket message types for storage data and real-time sync (#1062) (android)
  • [SDK] Add SharedPreferences/DataStore reading API for key-value storage inspection (#1061) (android)
  • Live performance data for currently selected app (#1060) (performance, intellij plugin)
  • Navigation Graph should only accept named nodes (#1059)
  • Navigation Graph Fog Mode (#1058)
  • Research: iOS real-time screen streaming options (#1034) (ios, research)
  • Android: Implement video server JAR (VirtualDisplay + MediaCodec) (#1031) (android)
  • Research: Android real-time screen streaming architecture (MediaProjection/MediaCodec) (#1030) (research)
  • Feature: Android SharedPreferences Inspection and Management (#1021) (android, devxp, testing)
  • Feature: Crash and ANR Monitoring via ADB, simctl, and AccessibilityService (#1020) (android, ios, devxp, testing)
  • Feature: Database Inspection and Management for Android AutoMobile SDK (#1019) (android, devxp, testing)
  • feat(mcp): add setUI tool for declarative form field population (#986) (android, ai)
  • IDE plugin: Compose charting for performance timelines (#306) (android, intellij plugin)
  • IDE Plugin: Display recent performance debug data (#283) (android, performance, intellij plugin)
  • IDE plugin: MCP resource viewer UI (#255) (intellij plugin)
  • IDE plugin: add source mapping support (#247) (intellij plugin)

Changed

  • refactor: move src/features/observe/accessibility/ to src/features/observe/android/ (#1123) (android)
  • refactor: consolidate screenshot utilities (#1121)
  • refactor: decompose SwipeOn - extract overlay detection and scroll-until (#1120) (android)
  • refactor: decompose ViewHierarchy - separate screenshot handling (#1119) (android)
  • refactor: decompose TapOnElement - extract focus navigation (#1118) (android)
  • refactor: replace getInstance() singletons with constructor injection (#1117)
  • refactor: add interfaces for ObserveScreen, Window, AwaitIdle (#1116)
  • refactor: decompose XCTestServiceClient using delegate pattern (#1115) (ios)
  • refactor: migrate raw setTimeout/setInterval to Timer interface (#1114)
  • refactor: replace inline retry logic with DefaultRetryExecutor (#1113)
  • refactor: consolidate ad-hoc caches to use TTLCache (#1112)
  • Decompose Explore.ts (1870 lines) (#1108)
  • Decompose AccessibilityServiceClient.ts (4652 lines) (#1107) (android)
  • Migrate remaining AdbClient instantiations to AdbClientFactory (#1106) (android)
  • Dead Code Detection: Threshold Exceeded (#1027) (automated, dead-code)

Fixed

  • pressButton should properly await fresh view hierarchy before returning observation (#1051)

Other

  • perf: explore queueMicrotask optimization for FakeTimer (#1130) (devxp, performance)
  • Navigation nodes should preserve aspect ratio instead of cropping screenshots (#1052) (android, devxp, intellij plugin)
  • Research: DevXP for work profile app install tracking (#754) (android, devxp, research)

[v0.0.8] - 2026-01-24

Added

  • View hierarchy contains duplicate elements from merged sources (#999) (performance)
  • criticalSection: accept normalized params in nested steps (#960)
  • Abstract other macOS CLI tools through host control daemon (#932) (ios, env)
  • Abstract xcodebuild commands through host control daemon for Docker support (#931) (ios, env)
  • Abstract simctl commands through host control daemon for Docker support (#930) (ios, env)
  • feat(ios): Xcode provisioning profile integration for physical device deployment (#913) (ios)
  • feat(ios): Add iproxy port forwarding lifecycle management for physical devices (#912) (ios)
  • feat(ios): download XCTestService.ipa from GitHub releases instead of building from source (#906) (ios, release engineering, devxp)
  • Automatic wakefulness check and unlock on Android emulator boot (#879) (android, devxp)
  • feat: streamlined development workflow for iOS XCTestService updates (#878) (ios, devxp)
  • iOS: Interactive installer with Xcode/simulator validation (#871) (ios)
  • iOS: Doctor tool for iOS dependency verification (#869) (ios)
  • iOS: MCP resources for simulator sessions and installed apps (#868) (ios)
  • iOS: Parallel multi-simulator test orchestration (#867) (ios)
  • iOS: Session context for multi-simulator tool execution (#866) (ios)
  • iOS: Multi-simulator session allocation in daemon (#865) (ios)
  • iOS: Integrate visual highlights with bug report generation (#864) (ios)
  • iOS: Integrate visual highlights with video recording (#863) (ios, video)
  • iOS: MCP tool for visual highlighting during debugging (#862) (ios)
  • iOS: WebSocket commands for visual highlight control (#861) (ios)
  • iOS: Visual highlight overlay for XCTest service (#860) (ios)
  • iOS: Expose navigation graph as MCP resource (#859) (ios)
  • iOS: Implement identifyInteractions tool (#858) (ios)
  • iOS: Implement explore tool for automatic app discovery (#857) (ios)
  • iOS: Navigation graph building and exploration (#856) (ios)
  • iOS: MCP tools and resources for video recording (#855) (ios, video)
  • iOS: Integrate video recordings with FFmpeg post-processing (#854) (ios, video)
  • iOS: Video recording capture backend using simctl (#853) (ios, video)
  • iOS: Add comprehensive tests for simulator snapshot feature (#852) (ios, testing)
  • iOS: Implement simulator snapshot restore (#851) (ios)
  • iOS: Implement simulator snapshot capture using simctl (#850) (ios)
  • feat: built-in Claude plugin for marketplace distribution with AutoMobile skills (#848) (release engineering, devxp)
  • feat: optimize CLAUDE.md for progressive disclosure and automatic validation updates (#847) (documentation, devxp, ai)
  • feat: simplify MCP tool schema - move selector id/text to top-level parameters (#845) (devxp)
  • feat: seamless release workflow - consolidate bump version and changelog into single Release workflow (#844) (ci, release engineering)
  • feat: automatically match target device light/dark mode to host system settings (#837) (android, ios, devxp)
  • feat: harden regex parsing for device data (#834) (android, ios)
  • feat: streamlined development workflow for Android/iOS embedded service updates (#831) (android, ios, devxp)
  • ci: only run iOS CI checks when iOS or TypeScript code changes (#829) (ios, ci, devxp)
  • ci: only run Android CI checks when Android or TypeScript code changes (#828) (android, ci, devxp)
  • MCP resource URIs are confusing and inconsistent (#804) (devxp)
  • Integrate focus-based navigation into tapOn tool (transparent to MCP consumers) (#471) (android, a11y)
  • Set up release keystore for production builds (#431) (android, ci, release engineering)
  • Validation: implement all_fast_validate_checks.sh aggregator (#371) (ci, devxp)
  • doctor: iOS checks for missing companion app + download link (#363) (ios, devxp)
  • XCTest Runner: timing capture + publish timing history (#356) (ios, testing)
  • XCTest Runner: implement AutoMobileTestCase + plan executor (#355) (ios, testing)
  • Daemon: add iOS simulator discovery + session allocation (#354) (ios, devxp)
  • simctl integration: status bar demo mode configuration (#352) (ios)
  • simctl integration: app install/launch/terminate + capability reporting (#351) (ios)
  • simctl integration: simulator lifecycle management (#350) (ios)
  • AXe automation layer: coordinate translation + gesture injection (#349) (ios)
  • AXe automation layer: MCP tool handlers + WebSocket client (#348) (ios)
  • Accessibility Bridge: emit view hierarchy change events over WebSocket (#347) (ios)
  • Accessibility Bridge: implement element lookup + bounds + focus state (#346) (ios)
  • IDE plugin: real-time performance streaming + cache (#305) (android, performance, intellij plugin)
  • Enhanced contrast detection for gradients and overlays (#102) (a11y)

Changed

  • Upgrade json-schema-validator to 3.0.0 (requires Jackson 3 migration) (#967) (android, dependencies)
  • Remove unused kotlinx-datetime dependency (#966) (android, dependencies)
  • Remove p99 from MCP Tool Throughput Benchmarks (#950) (performance)
  • Improving TypeScript dead code detection (#946) (devxp, dead-code)
  • Dead Code Detection: Threshold Exceeded (#939) (automated, dead-code)
  • Reduce slow wakeAndUnlock unit tests (<100ms) (#919) (testing)
  • chore: remove checkForeground parallel mode - single dumpsys is 12.9x faster (#872) (android, performance)
  • chore: cleanup top-level leftover planning markdown files (#849) (documentation)
  • chore: set up GitHub Sponsors for project donations (#846)
  • chore: update changelog for v0.0.7 release (#843) (documentation, release engineering)
  • chore: set up release key signing for iOS libraries (#842) (ios, release engineering)
  • chore: set up Dependabot for iOS Swift Package Manager dependencies (#841) (ios, dependencies)
  • chore: set up Dependabot for Android Gradle dependencies (#840) (android, dependencies)
  • chore: update Python/uv dependencies in /scripts/github (#839) (dependencies, python:uv)
  • chore: update TypeScript dependencies - research major version upgrades (#838) (dependencies)
  • docs: clean up and organize documentation (#830) (documentation)
  • Chore: Test notification triggering (#765)

Fixed

  • MCP startup benchmark sometimes hangs without reasonable timeout (#1002) (ci, performance)
  • setActiveDevice does not single out iOS simulators for observe (#1001) (ios)
  • rawViewHierarchy tool doesn’t support iOS (#1000) (ios)
  • iOS: Cannot detect or launch system apps (Settings, Fitness, etc.) (#984) (ios)
  • iOS: Home button press and homeScreen tool not working (#983) (ios)
  • MCP tools/list fails due to tapOn schema using union type at root (#973) (ai)
  • Security: Update qs to fix arrayLimit bypass DoS vulnerability (#964) (dependencies)
  • Security: Update @modelcontextprotocol/sdk to fix ReDoS vulnerability (#963) (dependencies)
  • Security: Update hono to fix JWT Middleware algorithm confusion (#962) (dependencies)
  • Security: Update hono to fix JWK Auth Middleware JWT algorithm confusion (#961) (dependencies)
  • Handle corrupted migrations in daemon startup (#947)
  • bug: hot reload development workflow not working (#832) (devxp)
  • Bug: Auto-generated bump versions PR does not trigger CI workflows (#812) (ci, release engineering)
  • Upgrade Bun to 1.3.6 to fix CI segmentation fault crashes (#811) (ci, dependencies)
  • Accessibility service state detection issues after automatic setup (#801) (android, a11y)
  • Prevent automated changelog PR from erroring on fork origin (#793) (ci, release engineering)
  • Fallback to uiautomator when AccessibilityWindowInfo.root returns null for active window (#775) (android, a11y)

Other

  • docs: add reveal/collapse wrappers for demos to reduce page distraction (#987) (documentation)
  • Add CI checks for host control docker scripts across macOS/Linux/Windows (#980)
  • ci: run TypeScript Node build/test on macOS/Windows/Linux matrix (#958) (ci, testing)
  • ci: run interactive installer on macOS/Windows/Linux matrix (#957) (ci, release engineering, testing)
  • Add recorded GIF demo to interactive install script documentation (#953) (documentation)
  • AGP 9.0 bump fails due to org.jetbrains.kotlin.android plugin (#896) (android, ci, automated, dependencies)
  • Dependabot Android PRs fail CI due to missing signing secrets (#895) (android, ci, automated, dependencies)
  • iOS: First-run path documentation from setup to first task (#870) (documentation, ios)
  • chore: research slim Docker image for Android emulator management (#833) (android, env, research)
  • Codex setup missing in install docs (#825) (documentation, ai)
  • Explore automatic retry for flaky emulator tests in CI (#808) (flaky test, ci, research)
  • Benchmark NPM Unpacked Size (#796) (release engineering, research)
  • Reduce NPM Unpacked Size (#795) (release engineering, performance)
  • Accessibility Bridge distribution without App Store (#376) (ios, release engineering)
  • CI: audit workflows to keep Linux for non-iOS checks and macOS only where required (#374) (ios, ci, devxp)
  • XCTest Runner: configuration via env vars + sample test target docs (#357) (documentation, ios, testing)
  • Run AutoMobile self tests on Emulator.wtf (#77) (android, ci, testing)
  • iOS ViewHierarchy WebSocket Accessibility Service/App (#33) (ios)

[0.0.7] - 2026-01-15

Added

  • Add configurable fade animation for highlights (1-5 second duration) (#656) (android, devxp)
  • Add smooth ink-line path drawing for freehand annotations (#655) (android, devxp)
  • Add runtime permission handling for drawing overlays (#654) (android, devxp)
  • Integrate visual highlights with video recording for reproduction videos (#653) (devxp)
  • Integrate visual highlights with bug report generation (#652) (devxp)
  • Add MCP tool for visual highlighting during debugging (#651) (devxp)
  • Add Node.js client for visual highlight control (#650) (devxp)
  • Add WebSocket commands for controlling visual highlights (#649) (devxp)
  • Add drawing API for shapes in AccessibilityService overlay (#648) (android, devxp)
  • Add cmdline-tools installation to doctor MCP tool (#620) (android, devxp, ai)
  • Detect Homebrew avdmanager when system images are in $ANDROID_HOME (#619) (android, devxp)
  • Detect old avdmanager with JAXB error and provide helpful message (#618) (android, devxp)
  • Add Device Owner/Device Admin setup for advanced operations and CA certificate management (#615) (android, devxp)
  • Complete implementation of Last Screenshot MCP resource (#613)
  • Feature: Enable element search across both main hierarchy and window hierarchies in tapOn/interaction tools (#543) (android)
  • Feature: Keep screen awake on physical devices during automation (#536) (android)
  • Implement Android AccessibilityService clipboard operations (#500) (android)
  • Implement focus path calculation and navigation engine (#470) (android, a11y)
  • Implement focus position tracking and accessibility tree traversal (#469) (android, a11y)
  • Design focus-based navigation algorithm for TalkBack element targeting (#468) (android, a11y, research)
  • Implement network traffic capture MCP tools with mitmproxy (#466) (android)
  • Implement postNotification MCP tool with SDK hook and cmd notification fallback (#463) (android)
  • Implement setNetworkState MCP tool for Wi-Fi/cellular/airplane mode control (#462) (android)
  • Implement clipboard MCP tool with ADB and helper APK fallback (#461) (android)
  • Implement biometricAuth MCP tool with emulator fingerprint support (#460) (android, research)
  • Add accessibility focus tracking to observations (#459) (android, a11y)
  • Adapt swipeOn tool for TalkBack using two-finger swipe and scroll actions (#458) (android, a11y)
  • Adapt tapOn tool for TalkBack mode using ACTION_CLICK (#457) (android, a11y)
  • Implement TalkBack auto-detection and infrastructure (#456) (android, a11y)
  • Add capability detection for settings-based accessibility toggle (#409) (android, devxp)
  • Implement adb settings-based accessibility service toggle (#408) (android, devxp)
  • Add optional device labels to device-scoped tool calls (#388) (android)
  • Block MCP tool calls during executePlan (#330) (devxp)
  • Video recording: Android + iOS capture backends (#326) (android, ios, video)
  • Video recording: MCP tools/resources + CLI config (#324) (devxp, video)
  • Video recording: core service + archive retention (#323) (video)
  • Interactive install script with gum + animated AutoMobile logo (#322) (env, devxp)
  • Implement hybrid iOS automation architecture (#319) (ios)
  • Feature Request: Implement pinch-to-zoom gesture in accessibility service (#264) (android, a11y)
  • IDE plugin: MCP feature flags UI (#256) (intellij plugin)
  • IDE plugin: navigation graph rendering (#253) (intellij plugin)
  • IDE plugin: Unix socket transport for MCP attachment (#252) (intellij plugin)
  • Explore scrollToward/contentDirection for swipeOn semantics (#249) (android, devxp)
  • IDE plugin: support TCP/HTTP transport for bun dev mode (#246) (devxp, intellij plugin)
  • Add visual fallback for selected-state detection (#242) (android, devxp, ai)
  • Add identifyInteractions MCP tool to suggest available actions (#224) (android)
  • Add dry run mode for explore tool call (#223) (android)
  • Allow whitelisting navigation graph nodes and edge tool calls (#222) (android)
  • Add await element option to tapOn for waiting on next UI state (#219) (android)
  • Support tapOn for non-unique text within a specific container (#211) (android)
  • Cancel in-progress MCP commands when AI agent or JUnitRunner disconnects (#204) (android, devxp)
  • startDevice should error if AVD already running (#176) (devxp)
  • openSystemTray should avoid redundant swipe when tray already open (#173) (android, devxp)
  • Add retry mechanism for transient CI failures (Maven 403, network issues) (#172) (ci, devxp)
  • MCP Resource: Installed Apps per Device (#163) (android)
  • MCP Resource: Connected Devices (#162) (devxp)
  • MCP Resource: Available Emulators/Simulators List (#161) (devxp)
  • Doctor Tool for Onboarding and Diagnosis (#160) (devxp)
  • Expose tool call history as MCP resource (#130) (devxp)
  • Expose navigation graph nodes as individual MCP resources (#129)
  • Expose navigation graph as MCP resource for IntelliJ plugin (#128) (android, intellij plugin)
  • Expose internal debugging as MCP resource (#127) (devxp)
  • Include Debug Information in MCP Tool Error Responses (#108)
  • Back stack awareness (#78)
  • IntelliJ IDE plugin (#67) (android, devxp)
  • Permission Audit & Capability Inventory (auditPermissions) (#59)
  • Sensitive Data Exposure Scanner (scanDataLeakage) (#57)
  • Element Search Fallbacks (#54)
  • TalkBack Navigation Simulator (simulateTalkBack) (#53)
  • Dark Mode Consistency Checker (#50)
  • Locale & System Configuration Manager (#49)
  • Battery & Charging State Simulator (#48)
  • Sensor Simulation Framework (#47)
  • Live Interactive Element Inspector (#43)
  • HTTP Request Mocking & Recording (mockNetwork) (#42)
  • Network Condition Simulator (simulateNetworkCondition) (#41)
  • ANR Risk Detector (profileAnrRisk) (#39)
  • Navigation graph: Handle bottom sheets, popups, and dialogs (#28)
  • Navigation graph: Handle scroll position as UI state (#27)
  • Retain and Reuse Navigation (#10)
  • clipboard get action returns empty string after successful copy operation (#778)
  • systemTray find with both title AND body criteria always fails to find notifications (#777)
  • Tool registration regression: interaction tools silently failed to register (#745) (ai)
  • dragAndDrop schema allows empty selectors; runtime rejects (#686) (devxp)
  • dragAndDrop should check accessibility service availability (enabled + installed) (#681) (android, a11y)
  • Android drag requests never execute; dragAndDrop always times out (#680) (android, a11y)
  • Preserve double-tap behavior in TalkBack mode (#672) (android, a11y)
  • Dead code detection job fails with ‘Argument list too long’ when issue count is high (#641) (ci, devxp)
  • Navigation graph MCP resources remain empty after active app observation (#614)
  • AutoMobile fails to detect installed Android system images (#612) (android, env)
  • Material3 navigation text labels missing from accessibility hierarchy due to sibling occlusion bug (#591)
  • installApp MCP tool fails with ‘adb: unknown command dump’ (#587) (android)
  • MCP observe responses are excessively large due to unfiltered data (#539) (ai)
  • IDE plugin: AutoMobile tool window ignores IntelliJ theme (#335) (android, intellij plugin)
  • swipeOn direction parameter causes AI agents to swipe opposite of intended direction (#226) (android, devxp)
  • swipeOn tool description causes AI agents to swipe on screen instead of targeting lists (#225) (android, devxp)
  • Selected state not correctly interpreted from view hierarchy (#213) (android)
  • Git state becomes dirty from .mcp.json and .gitignore changes on branch/worktree checkout (#212) (devxp)
  • Stale view hierarchy returned to AI agents after interactions (#205) (android, devxp)
  • MCP client fails to connect at startup with handshaking error (#186) (env, devxp)
  • AutoMobile CLI hangs and doesn’t exit after executePlan completes (#109)
  • Large MCP response warning on Accessibility Service websocket timeout (#86) (devxp)
  • Observe call happening right after an action that should have included observation (#66)
  • Add stub listDevices MCP tool (#781) (devxp, ai)
  • Add stub listApps MCP tool (#780) (devxp, ai)
  • Add keyboard MCP tool with open/close/detect actions (#779) (devxp, ai)
  • Google Weather app filtered out from listApps MCP resource (#715)
  • Accessibility service filters out Android home launcher widgets from view hierarchy (#714)
  • Make identifyInteractions a debug-only MCP tool (#673)
  • Add polling support to tapOn action with searchUntil parameter (#662)
  • Add optional waitFor parameter to observe MCP tool (#658)
  • Add overlay window capability to AccessibilityService (#647)
  • tapOn should use parent clickable element when matched element is not clickable (#646)
  • swipeOn container selection should avoid overlaying clickable elements (#645)
  • Playground app: Add accessibility semantics to navigation components (#571)
  • Research TalkBack/VoiceOver MCP tool behavior and create design doc (#430) (a11y, research)
  • Experiment: Toggle AutoMobile accessibility service via adb settings (#384) (android, a11y, research)
  • Feature Request: Implement drag-and-drop gesture and MCP tool call (#265)
  • swipeOn tool needs better container parameter schema, docs, examples (#263)
  • tapOn tool needs better container parameter schema, docs, examples and validation (#262)
  • explore should stay within current foreground app (#174)
  • [Android] Automatic Work Profile adaptation (#35) (android)
  • Debug Interactions (#11)
  • Retain Navigation in Memory (#9)
  • Android Library SDK (#8)
  • Android WebSocket server (#7)
  • Dockerize AutoMobile (#5) (env)
  • Database for memory and settings (#2)
  • Rewrite internals with interfaces (#1)

Changed

  • Cache installed apps list in SQLite and update via package broadcast receivers (#750) (performance)
  • Optimize observe: Make screenshot capture async/non-blocking (#749) (performance)
  • Optimize launchApp: Run detectTargetUser and checkInstalled in parallel (#748) (performance)
  • Add strict ‘exactly one’ selector enforcement to swipeOn.lookFor (#740) (android, testing, chore)
  • Add strict ‘exactly one’ selector enforcement to pinchOn container (#739) (android, testing, chore)
  • Add strict ‘exactly one’ selector enforcement to tapOn tool (#738) (android, testing, chore)
  • Clean up MCP response message when searchUntil doesn’t need to poll (#700)
  • Add toolResults parsing in AutoMobilePlanExecutor for JUnitRunner (#697) (android, testing)
  • Create Kotlin serialization data classes for tool results in :test-plan-validation (#696) (android, testing)
  • Enhance tapOn response to include selectedElement metadata (#694) (android, testing)
  • Add selectionStrategy parameter to tapOn tool (#693) (android, testing)
  • Add boomerang field to swipeOn for dry-run gesture testing (#675) (devxp, ai)
  • Convert listApps to MCP resource with query support to reduce context usage (#674) (devxp, ai)
  • Optimize Docker publish job cache export settings to reduce build time by ~60% (#640) (ci, performance)
  • Improve error output in startup benchmark script (#639) (ci, performance)
  • Convert daemon management tools to unix socket requests (#608) (ai)
  • Merge enableDemoMode and disableDemoMode into unified demoMode tool (#605) (ai)
  • Merge localization tools into unified changeLocalization tool (#604) (ai)
  • Restrict executePlan and criticalSection tools to daemon mode only (#603) (ai)
  • Refactor deviceSnapshot MCP tools (#601) (ai)
  • Move test recording from MCP tools to unix socket interface (#600) (ai)
  • Refactor MCP video recording tools (#596) (ai)
  • Evolve MCP tool call openSystemTray (#595) (ai)
  • Move identifyInteractions and getNavigationGraph to debug-only tools (#594) (ai)
  • Validate accessibility service version compatibility even when skipAccessibilityDownload is true (#580) (android)
  • Consolidate MCP benchmark PR comments into a single unified comment (#576) (ci, devxp)
  • Optimize accessibility service setup: rename skipAccessibilitySetup to skipAccessibilityDownload (#570) (performance)
  • Feature: Merge window hierarchies into main hierarchy for unified view (#544) (android)
  • Write integration tests for AccessibilityService focus tracking (#533) (android, a11y, testing)
  • Write unit tests for AccessibilityFocusTracker (#532) (testing)
  • Implement dead code detection for TypeScript (#518) (ci, devxp, testing)
  • Memory leak detection and profiling for TypeScript MCP server (#512) (performance, testing)
  • Additional performance benchmarks: observe latency, device boot, test plan execution (#510) (performance, testing)
  • Implement MCP server and daemon startup time benchmark (#509) (devxp, performance, testing)
  • Implement MCP tool call throughput benchmark (#508) (performance, testing)
  • Add comprehensive tests for device snapshot feature (#506) (testing)
  • Implement full app data backup and restore for ADB snapshots (#505) (android, testing)
  • Refactor: Convert all ‘java’ directories to ‘kotlin’ in Android project structure (#504) (android, chore)
  • CI: Cache Android system images to reduce emulator test setup time from 11+ min to <1 min (#497) (android, ci, devxp, performance)
  • IDE plugin: YAML autocomplete for test plan files (#493) (devxp, intellij plugin)
  • CI: Split IDE Plugin validation into separate Build and Test jobs (#486) (ci, intellij plugin)
  • ‘On Merge’ workflow should require all jobs to pass before publishing to Docker Hub (#475) (ci, release engineering)
  • Change explore tool to navigate known graph instead of building it (#445) (devxp)
  • Skip long-running CI jobs for documentation-only PRs (#438) (documentation, ci, devxp, performance)
  • Skip CI checks for accessibility service SHA256 update PRs (#437) (ci, performance, chore)
  • Optimize MCP tools context usage to reduce token consumption (#434) (devxp, performance, ai)
  • Update accessibility setup flow to prefer settings-based toggle (#410) (android, devxp)
  • executePlan schema: multi-device + criticalSection (#392) (devxp, testing)
  • JUnitRunner/Daemon: allocate devices for plan labels (#391) (android, testing)
  • executePlan: multi-device labels + implicit parallelism (#390) (android, testing)
  • Add criticalSection tool call for serialized multi-device steps (#389) (android, testing)
  • IDE plugin: test plan YAML linting (#387) (devxp, intellij plugin)
  • Validate executePlan YAML on read/author (#386) (devxp, testing)
  • Add YAML validation across repo (#385) (devxp, testing)
  • Validation: add XML auto-format/fix script (#370) (ci, devxp)
  • Validation: add shell script auto-fix via shfmt (#369) (ci, devxp)
  • Validation: add TypeScript test validation script (#368) (ci, devxp, testing)
  • Validation: add TypeScript build validation script (#367) (ci, devxp)
  • Validation: add ESLint validation + auto-fix scripts (#366) (ci, devxp)
  • Xcode companion app: core UI surfaces (nav graph, performance, feature flags, logs) (#360) (ios, devxp)
  • Accessibility Bridge distribution: bundle vs on-demand download/caching (#353) (ios, release engineering)
  • Feature: enforce MCP context thresholds via benchmark script (#339) (devxp, performance)
  • Feature: estimate MCP context usage (tools, resources, operations) (#338) (devxp, performance)
  • Recorded test plan migrations + MCP versioning (#331) (devxp)
  • IDE plugin: migrate all UX to Jewel + Compose (#328) (android, intellij plugin)
  • Add curl-based interactive installer entrypoint in README + docs/install (#327) (documentation, env, devxp)
  • Video recording: FFmpeg backend with hardware acceleration (macOS/Linux) (#325) (performance, video)
  • Add AutoMobile tests/plans for Playground docs/using demos (#321) (android, testing)
  • Playground app: add demo flows for docs/using workflows (#320) (android, devxp)
  • IDE plugin: add test recording and YAML plan generation (#318) (android, intellij plugin)
  • Add MCP resources for test timings and performance results (#317) (performance)
  • Feature: Extract Android ‘Displayed’ time metrics from logcat for startup profiling (#311) (android, performance)
  • IDE Plugin: Display recent UI performance results (#282) (android, performance, intellij plugin)
  • IDE Plugin: Display historical test timing data for visual analysis (#281) (android, performance, testing, intellij plugin)
  • JUnitRunner: Use historical test timing to optimize execution order (#280) (android, testing)
  • MCP Daemon: Provide historical test timing to JUnitRunner on startup (#279) (android, testing)
  • MCP Daemon: Record test execution timing in SQLite database (#278) (testing)
  • Rely on view hierarchy updates for navigation destination instead of SDK navigation events (#277) (android)
  • Add GHA workflow to update CHANGELOG from issues since last tag (#274) (release engineering)
  • Add manually triggered GHA workflow for version bumping (#273) (release engineering)
  • Track historical accuracy of predictive UI state (#221) (android, performance)
  • Add predictive UI state to observations based on navigation graph (#220) (android, performance)
  • Start test recording via in-app overlay or accessibility service shortcut (#218) (android)
  • Auto-update accessibility service APK SHA256 via PR when source changes (#217) (android, ci, release engineering)
  • Enable AccessibilityService to filter out views completely hidden by overlays (#214) (android, performance)
  • Track Compose recomposition counts in observation results (#202) (android, devxp, performance)
  • Auto-detect and upgrade accessibility service APK when SHA mismatch (#199) (android, release engineering, devxp)
  • Add Codex MCP client installation docs (#184) (documentation, devxp)
  • Revamp Hot Reload Development Workflow (#164) (devxp)
  • Session State Management to Reduce Required Tool Parameters (#159) (devxp)
  • Dynamic MCP Tool Loading via Workflow-Based Selection (#158) (devxp)
  • Test parallel execution across multiple devices (#151) (testing)
  • Update core tools to respect sessionUuid for device targeting (#150) (testing)
  • Integrate session context into tool execution (#149) (testing)
  • Update CLI to accept –session-uuid parameter (#148) (testing)
  • Add daemon commands for device/session queries (#147) (testing)
  • Make UI stability thresholds configurable (#138) (performance)
  • Analyze and prevent JUnitRunner test pollution (#134) (android, devxp, testing)
  • CI: Run Playground Automobile tests on emulator (#132) (android, ci, testing)
  • Expose latest observation as MCP resource (#131) (devxp)
  • CI: Auto-install accessibility APK for JUnitRunner emulator tests (#126) (ci, performance)
  • MCP Server Daemon for CLI (#125) (performance, testing)
  • Optimize accessibility audit performance with contrast caching (#105) (performance, a11y)
  • Add comprehensive unit tests for accessibility audit checks (#101) (devxp, a11y)
  • Add ESLint rule to prevent .js extensions in TypeScript imports (#90) (devxp)
  • Touch latency testing implementation (#85) (devxp, performance)
  • Migrate test runner from Mocha to Bun’s built-in test runner (#81) (ci, devxp)
  • Natural Language Test Commands (#56)
  • Navigation Graph Test Coverage and Recommendations (#55) (testing)
  • –accessibility-audit mode where WCAG violations fail tests (#52)
  • Flaky Test Detection & Quarantine (#51)
  • Device State Snapshot & Restore (#46) (devxp, performance)
  • Test Recording & Playback with Smart Locators (#45)
  • Parallel Multi-Device Test Orchestration (#44)
  • Visual Regression Testing (compareScreenshot) (#40)
  • –mem-perf-audit mode where leaks, excessive GC, memory pressure, etc fail tests (#38)
  • App Startup Performance Analyzer (profileAppStartup) (#37)
  • –ui-perf-audit mode where jank and poor FPS fail tests (#36)
  • Consolidate scroll, swipeOnScreen, and swipeOnElement into swipeOn (#30)
  • Create monkeyNavigate tool for efficient graph exploration (#29)
  • systemTray find returns cached observation instead of system tray when tray is closed (#776) (android)
  • gfxinfo not reaching stability after launchApp for simple UX (#699) (performance)
  • Test plan/IDE validator doesn’t validate dragAndDrop params (#687) (devxp, intellij plugin)
  • dragAndDrop uses stale cached hierarchy (can drag wrong coords) (#684) (android)
  • dragAndDrop uses fixed 5s timeout; long gestures always fail (#683) (android, performance, a11y)
  • dragAndDrop dropDelay default mismatch with schema/docs (#682) (documentation)
  • MCP Startup Benchmark PR comment has mangled output with escaped newlines (#575) (ci, devxp)
  • AccessibilityService: Hierarchy optimization removes clickable elements with text labels (#572) (android)
  • JUnit runner + MCP daemon parallel execution completely broken (3 critical bugs) (#541) (android, testing, ai)
  • CI: Android Emulator Tests Failing Due to Disk Space Exhaustion (#522) (android, ci)
  • 3 JUnit Runner emulator tests are skipped due to missing test plan file (#473) (android, testing)
  • GitHub Actions runner: No space left on device during Docker Hub publish (#435) (ci, release engineering, env)
  • Build Docker Image CI failing: MCP stdio protocol ENOENT /workspace/src/db/migrations (#382) (ci, env)
  • Update Changelog workflow should use AUTO_MOBILE_PR_TOKEN for PRs (#297) (ci, release engineering)
  • Bump Versions workflow fails because ripgrep is missing (#296) (ci, release engineering)
  • Flaky ClockAppAutoMobileTest fails to reach MCP server in CI (#257) (flaky test, testing)
  • listApps returns all system apps for every profile, causing huge MCP response (#215) (android, performance)
  • Improve long press implementation and add playground testing areas (#203) (android, testing)
  • Flaky accessibility-service WebSocketServerIntegrationTest in CI (#197) (android, flaky test, ci, testing)
  • Navigation tests fail with Robolectric OnBackPressedDispatcher incompatibility (#190) (android, ci)
  • Playground emulator tests fail: koog-agents dependency classloading issue (#189) (android, ci, testing)
  • CI: Android emulator tests failing with shell exit code 1 (#156) (android)
  • JUnit Runner Emulator Tests failing with shell syntax error (#140) (android, ci)
  • Migrate from better-sqlite3 to bun:sqlite for Bun compatibility (#118) (enhancement)
  • JUnit Runner: Test Timeout When Running Multiple Tests Together (#107)
  • PluginException: TestPlanInspection shortName mismatch (#768)
  • Chore: Test clipboard tool (#767)
  • Chore: Test system tray lookFor (#766)
  • Chore: Test biometrics stubbing (#763)
  • Chore: Test takeScreenshot fallback tool (#762)
  • Add unit tests for accessibility APK download/verification paths (#730) (android, testing)
  • Harden accessibility APK download (HTTP status + curl fallback + integrity check) (#729) (android, release engineering, env)
  • Use unique, OS-portable temp path for accessibility APK download (#728) (android, release engineering, env)
  • APK download fails on macOS due to sha256sum dependency (#727) (android, release engineering, env)
  • Add tests for occlusion filtering behavior (#719) (android, performance, testing)
  • Update tool-definitions.json for tapOn selectionStrategy and selectedElement (#695) (documentation, android, testing)
  • Add dragAndDrop test coverage; fakes/interface lack requestDrag (#685) (devxp, testing)
  • Research effectiveness of current navigation graph implementation (#676) (documentation, research)
  • Enhancement: Hybrid hierarchy combining accessibility service + UIAutomator for apps with poor accessibility (#588)
  • Change accessibility service SHA256 update to run daily instead of on every main merge (#577)
  • CI: bun pm trust heapdump exits 1 in memory leak detection (#569)
  • CI failures after #562: native addon build errors (#568)
  • Standardize naming convention: auto-mobile for Maven artifacts, automobile for package names (#540) (android, release engineering, chore)
  • Build and deploy AccessibilityService APK with focus tracking (#534) (android, devxp)
  • CI: Optimize Android emulator test daemon warmup (currently ~90s overhead) (#527) (android, ci, devxp, performance)
  • Memory leak detection and profiling for IntelliJ IDE Plugin (#515) (devxp, performance, testing, intellij plugin)
  • Memory leak detection and profiling for JUnitRunner library (#514) (android, performance, testing)
  • Memory leak detection and profiling for Android AccessibilityService (#513) (android, performance, a11y, testing)
  • Validate and test VM snapshot emulator console commands (#507) (android, testing, research)
  • End-to-end testing for clipboard MCP tool (#501) (testing)
  • Refactor gradle modules: extract shared test plan validation into android/test-plan-validation (#492)
  • Standardize environment variable naming: AUTOMOBILE_ vs AUTO_MOBILE_ prefix (#483) (documentation, env, devxp, chore)
  • Optimize slow TypeScript unit tests (35 files exceed 100ms) (#481) (performance, testing)
  • Add Gradle test report patterns to root .gitignore (#476) (android, testing, chore)
  • Optimize Android emulator test job runtime and reduce flakiness (#446) (android, flaky test, ci, performance)
  • Enable auto-merge on accessibility service update PR (#436) (ci, devxp, chore)
  • Document settings-based accessibility toggle (#412) (documentation, devxp)
  • Test settings-based accessibility toggle on API 29 & 35 (#411) (android, devxp, testing)
  • Research: validate Android design-doc experiments with adb (#393) (android, research)
  • Clarify bug reproduction doc with snapshot and MCP action links (#345) (documentation)
  • Link test recording and YAML plan workflow from user docs (#344) (documentation, android)
  • Call out accessibility service enablement in install/usage docs (#343) (documentation, android)
  • Add decision guide for MCP vs IDE plugin vs JUnitRunner vs SDK (#342) (documentation, android)
  • Add Android first-run path from device setup to a concrete task (#341) (documentation, android)
  • Review docs/ directory for accuracy and add implementation citations (#276) (documentation)
  • Setup Trusted Publishing for npm packages with GitHub Actions (#275) (release engineering)
  • Refactor Tap and Long Press tabs into unified screen with real-time duration tracking (#266)
  • Optimize JUnitRunner heartbeat mechanism for faster daemon timeout detection (#232) (android, devxp, performance, testing)
  • Docker Hub publish job fails: missing bun installation (#188) (ci, release engineering, env, devxp)
  • Phase 3b: JUnitRunner Direct Socket IPC (170ms/test optimization) (#145) (android, performance, testing)
  • Optimize JUnitRunner performance based on #133 research (#135) (android, ci, devxp, performance)
  • Analyze and optimize JUnitRunner performance bottlenecks (#133) (ci, performance)
  • Performance Research, Analysis, and Upgrade of Emulator CI jobs (#123) (android, ci, performance)
  • Register Maven central namespace (#120) (android, release engineering)
  • Enable JUnit Runner tests in GitHub Actions CI (#110) (android, ci, devxp)
  • Improve Android user profile parsing to use structured data instead of regex (#106) (android, devxp)
  • Run Android AutoMobile self tests on an Android Emulator in GHA (#94) (ci, devxp)
  • Android CI Perf Improvements (#93) (ci, devxp, performance)
  • Rename monkeyNav MCP tool call to explore (#80) (devxp)
  • Migrate from pnpm to bun for peak performance (#79) (ci, devxp)
  • Convert from npm to pnpm (#63)
  • Skip Docker CI if Dockerfiles and package.json did not change (#62)
  • Document Claude Code installation and usage (#31) (documentation)
  • Publish scoped package on NPM (#19) (release engineering)

Fixed

  • Bug: Duplicate/embedded observe in launchApp causing bloated MCP responses (#751) (performance)
  • Fix swipeOn coordinate calculation and overlay detection bugs (#722)
  • Bug: swipeOn with lookFor scrolls in wrong direction repeatedly (#671) (android)
  • Fix: Taps via accessibility service were being interpreted as long presses (#666) (android)
  • Bug: launchApp not correctly observing app state after launch (#537) (android)
  • Bug: tapOn schema validation error - container field expects object but receives string (#535)
  • Flaky test: planExecutionLock ‘allows MCP tool calls when no plan is executing’ times out in CI (#482) (flaky test, ci, testing)
  • Fix Android emulator CI job failures - 13m wasted on bugs, Gradle times out (#447) (android, ci)
  • Regression: JUnitRunner tests only using 1 device instead of device pool (#444) (testing)
  • Bug: AutoMobile incorrectly identifies system notification permission dialog as permission controller (#402)
  • Bug: Work profile apps fail observation due to hardcoded u0 user profile in regex patterns (#314) (android)
  • Fix FakeAccessibilityServiceManager interface import path (#731) (android, testing)
  • Flaky test: Session Lifecycle with Device Reuse sometimes returns different device (#548) (flaky test, ci, testing)
  • Fix MonkeyNavigate integration test timeouts (#73)
  • Flaky test: AccessibilityServiceClient WebSocket connection failure handling (#72) (flaky test)
  • Flaky test: AccessibilityServiceClient WebSocket connection failure timeout (#68) (flaky test)

Deprecated

  • Enhance devices resource with pool status and deprecate listDevices tool (#606) (ai)

Removed

  • Remove deprecated listApps MCP tool (#713)
  • Remove daemon_available_devices tool and forward usage to listDevices (#607) (ai)
  • Remove listSnapshots tool - create automobile:snapshots resource instead (#602) (ai)
  • Remove listPerformanceAuditResults MCP tool (#599) (ai)
  • Remove getTestTimings tool (#598) (ai)
  • Remove listVideoRecordings tool - already exposed via automobile:video/archive resource (#597) (ai)
  • Remove duplicate ‘Publish Docker Image’ workflow - Docker publishing already handled by ‘On Merge’ workflow (#474) (ci, release engineering, chore)
  • Remove KotlinPoet and automated test authoring references (#200) (documentation, android)
  • Remove installPlatformDependencies now that AutoMobile is dockerized (#177)
  • Remove getAllConfigs/setDeviceMode/resetConfig MCP tool calls (#175)
  • Delete source mapping and automatic test authoring (#4)
  • Delete iOS implementation (#3)

Security

  • Deep Link Security Validator (validateDeepLinkSecurity) (#58)
  • Security: Insecure temporary file creation in daemon manager (#157)
  • CodeQL check failing in CI (#141) (ci)

[0.0.6] - Unreleased

Changed

  • Placeholder: started fork; release notes not recorded.

[0.0.5] - 2025-07-22

Added

  • Add ADB command auto retry

Changed

  • Improve view hierarchy search for elements with auto retry
  • Refactor ConfigurationManager

Fixed

  • Test authoring fixes

[0.0.4] - 2025-07-08

Added

  • Automate Accessibility Service install and enablement on first ADB command for a device
  • Check APK SHA256 before installing
  • Allow element search to restrict to specific containers in the view hierarchy

Changed

  • Increase accessibility node inspection for better view hierarchy data
  • Filter unnecessary view hierarchy data to reduce observe payloads
  • Parallelize and cache observation and idling steps
  • Refactor BaseVisualChange
  • Reduce tool calls to make it easier for agents to determine tool call selection

[0.0.3] - 2025-07-08

Added

  • Automate Accessibility Service install and enablement
  • Check APK SHA256 before installing
  • Allow element search to restrict to specific containers in the view hierarchy

Changed

  • Increase accessibility node inspection for better view hierarchy data
  • Filter unnecessary view hierarchy data to reduce observe payloads
  • Parallelize and cache observation and idling steps
  • Refactor BaseVisualChange
  • Reduce tool calls to make it easier for agents to determine tool call selection

[0.0.2] - 2025-07-01

Added

  • Accessibility service with availability checks
  • Active window caching
  • Device session management

Changed

  • Improved docs for setup and installation
  • More test coverage

[0.0.1] - 2025-06-24

Added

  • Initial release