Skip to content

0.0.88

Choose a tag to compare

@github-actions github-actions released this 25 Oct 22:13
· 1439 commits to main since this release

Added

  • prototype: transition choreography — transition.delayMs, container stagger, and a blurReplace transition (#15247) (android, ios, workstream:prototype-motion-platform, contract, phase:3-transitions)
  • prototype(ios): advertise capabilities by OS version instead of one static list (#15242) (ios, workstream:prototype-motion-platform, phase:1-foundations, contract)
  • feat(ios): tools fail with a typed device_service_disabled error when a required simulator service is disabled (#15223) (ios)
  • feat(ios): report what disabling simulator services breaks, for AutoMobile and for apps (#15222) (ios)
  • feat(ios): apply an opt-in CPU-lean launchd profile before a simulator's first boot (#15217) (ios, performance)
  • feat(ios): provision new simulators from a settled template clone (#15216) (ios, performance)
  • perf(daemon): disconnect sweep while sessions are held re-lists the whole host inventory every 10 s (simctl list, per-emulator adb avd name, 375 log lines per minute) (#15092) (ios, performance, daemon)
  • follow-up(#15051): use a repository-boundary-checked helper for caller-selected Spotlight marker paths (#15070)
  • follow-up(#15055): bind iOS ProtoViewer permission-denial and response delivery to the request's consent epoch (#15061)
  • automotive: detect the automotive form factor in device traits (#14917) (android, automotive)
  • android: restore the IME keyboard behaviour profile on session release (keyboard setProfile, persona) (#14705) (android)
  • prototype(ios): shimmer style and advertise prototype_loading_states_v1 (#14689) (ios, a11y)
  • prototype(ios): render the chart node with Swift Charts and advertise prototype_chart_v1 (#14679) (ios, a11y)
  • prototype: platform vocabulary contract — platform action, platform events, /platform state, requires, capability gates (#14294) (android, ios)
  • prototype: data-driven rich text — linkify mentions, hashtags and URLs; spans from data (#14233) (android, ios, a11y)
  • prototype: chat lists — reverse layout, stick-to-bottom, scrollTo action and a keyboard-attached composer (#14232) (android, ios, needs-device-verify)
  • prototype: chart node — line, area, bar and ring bound to /data (#14209) (android, ios, a11y)
  • prototype: motion and gestures — animated style changes, horizontal slide transitions (drawers), zoomable images (#14208) (android, ios, a11y)
  • prototype: loading and empty states — skeleton shimmer and emptiness conditions (#14207) (android, ios, a11y)
  • feat(android): observe and control media sessions (playback state, metadata, transport commands) (#14117) (android)
  • feat(android): windowing — split-screen launch, picture-in-picture enter/exit, freeform/desktop window resize (#14115) (android, research)
  • feat(android emulator): setSensor for emulator sensors (light, proximity, gyroscope, magnetic field, pressure, temperature, humidity, orientation) (#14114) (android)
  • feat(perf android): capture a Perfetto trace around steps and dump the app heap (captureTrace, heapDump) (#14113) (android, performance)
  • feat(perf android): measureStartup — cold/warm/hot launch timing over N iterations with percentiles (#14112) (android, performance)
  • feat(installApp android): install app bundles (.aab via bundletool, .apks sets, split APKs) with grant-all and downgrade options (#14111) (android)
  • feat(getDeepLinks android): report App Links verification state and allow approving / re-verifying domains (#14110) (android)
  • System-alert policy: auto-handle OS permission and system alerts during plans (iOS SpringBoard alerts, Android permission controller) (#14106) (android, ios)
  • Tool: statusBar — deterministic status bar for screenshots and video (simctl status_bar, Android SystemUI demo mode) (#14105) (android, ios)
  • feat(displayConfig android): runtime screen-size override, navigation mode (gesture / 3-button) and display-cutout emulation (#14101) (android)
  • pressButton (iOS): add the action and camera hardware buttons via XCUIDevice.Button (#14100) (ios, research, needs-device-verify, physical-device)
  • inspectPackageSigning (iOS): report signing identity, team, entitlements and provisioning profile (#14099) (ios, needs-device-verify)
  • appLifecycle (iOS): state-preserving kill of a backgrounded app for state-restoration tests (#14098) (ios, research, needs-decision)
  • postNotification (iOS Simulator): pass category, mutable-content and a raw APNs payload instead of dropping actions/images (#14097) (ios, research, needs-device-verify)
  • crashApp (physical iOS): crash the target via devicectl device process signal (#14096) (ios, needs-device-verify, physical-device)
  • feat(pressButton android): system actions — lock screen, power dialog, quick settings, screenshot, split screen (#14095) (android)
  • getDeepLinks (physical iOS): read URL schemes and associated domains from the installed bundle (#14094) (ios, needs-device-verify, physical-device)
  • getPreference/setPreference (physical iOS): route UserDefaults through the connected SDK (#14093) (ios, needs-device-verify, physical-device, sdk)
  • displayConfig theme (physical iOS): set light/dark via XCUIDevice.appearance (#14092) (ios, research, needs-device-verify, physical-device)
  • setDeviceState location (physical iOS): simulate location via XCUIDevice.location (#14091) (ios, needs-device-verify, physical-device)
  • feat(android): trigger background work and memory pressure — run JobScheduler/WorkManager jobs, fire alarms, send trim-memory (#14090) (android)
  • displayConfig: add increaseContrast, reduceMotion and boldText (iOS Simulator + Android) (#14088) (android, ios, a11y, research)
  • displayConfig (iOS Simulator): support fontScale via simctl ui content_size (Dynamic Type) (#14087) (ios, a11y)
  • Tool: accessibilityAudit — run the platform's native accessibility audit (XCUITest performAccessibilityAudit, Android ATF) (#14086) (android, ios, a11y)
  • feat(setDeviceState android): power state — battery level/charging, battery saver, Doze, App Standby bucket, data saver, thermal status (#14084) (android)
  • feat(visual): compareScreenshot tool for visual regression against a named baseline (#14083) (android, ios, testing)
  • feat(logs): getLogs tool with logcat filters that survive process death (tag, priority, regex, buffers, since-last-action) (#14082) (android, devxp)
  • feat(android): sendBroadcast tool for app-targeted intents (#14081) (android)
  • feat(launchApp android): launch with an intent (component, action, data URI, categories, extras, flags) (#14080) (android, needs-device-verify)
  • feat(a11y android): perform semantic and custom accessibility actions (expand, collapse, dismiss, set progress, scroll in direction, app-defined) (#14077) (android, a11y)
  • feat(displayConfig android): accessibility display settings (high-contrast text, color inversion, color correction, magnification, bold text) (#14076) (android, a11y)
  • feat(audit): on-demand audit tool for accessibility, performance and memory audits (#14075) (android, ios, performance, a11y)
  • feat(device-sim): declarative device-state profile engine (apply / verify / revert) (#14067) (android, ios, needs-decision)
  • epic(device-sim): adversarial device-state fixture engine (rooted Android, broken iOS simulator, fault/chaos catalog) (#14064) (research, epic, needs-decision)
  • feat(device-condition): battery / thermal / Doze / standby fault injectors with paired resets (#14063) (android, testing)
  • provisioning: persona selector in provisionDevice spec and session requirements (contract change) (#14058) (android)
  • feat(device-condition): extend EmulatorConsoleClient with power/sensor/network/finger/avd-snapshot verbs (#14057) (android)
  • android: OEM persona catalog — versioned facets with evidence status, modeled on KeyboardProfile (#14055) (android)
  • android: OEM display persona composing displayConfig, setPosture, cutout/nav-mode overlays and force-dark (#14052) (android)
  • android: OEM background-kill profiles — standby bucket, Doze, RUN_ANY_IN_BACKGROUND and force-stop recipes (#14051) (android, testing)
  • feat(device-condition): session-scoped deviceCondition surface on setDeviceState (#14050) (android)
  • android: DeviceTraits reader for manufacturer/brand/skin props, replacing the duplicated ro.kernel.qemu probes (#14046) (android)
  • mcp: automobile:prototype/native resource returning the spec, assets and a Compose or SwiftUI host file (#13729) (devxp)
  • ios: AutoMobilePrototype library product in the root Package.swift plus an iOS simulator CI build (#13728) (ios, ci)
  • android: publish the prototype renderer to Maven Central with an API check (#13727) (android, ci)
  • android: stable public Compose API for embedding a prototype (AutoMobilePrototype) (#13725) (android)
  • ios: move the renderer layers out of PrototypeAgent.swift so host code is separable (#13723) (ios)
  • prototype: capability contract so embedded renderers never silently drop spec features (#13722) (android, ios)
  • prototype: request routing for embedded renderers (via: "host" without AutoMobile) (#13721) (android, ios)
  • ProtoViewer prerequisite: daemon HTTP ingress authentication hardening (#13624)
  • prototype: hand-ported reject-only Swift validator + shared parity corpus (critical path) (#13620)
  • ios: ProtoViewer app (list, open/switch, relaunch/reset, delete, share, import) (#13619)
  • android: ProtoViewer app (list, open/switch, relaunch/reset, delete, share, import) (#13618)
  • android: extract the prototype renderer and saved store from CtrlProxy (single mechanical PR) (#13617)
  • prototype: .automobile-proto bundle format, strict zip reader and canonical export (#13616)
  • feat(mcp): publish tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) and title in tools/list (#13541)
  • feat(mcp): return recording start/stop as MCP tasks (Tasks extension) (#13090)
  • prototype(android): accept the launcher's pin confirmation dialog automatically, with capture-based launcher matchers (#12266) (android)
  • feat(mcp): adopt Tasks extension for long-running device operations (#4668)

Changed

  • test: daemon health-check tests fail when run in one process with test/server (leaked log-sink stall state); androidModulesCiUnitTests depends on Bun.Glob dot handling (#15279) (testing)
  • refactor(types): narrow the remaining wide client parameters to Pick<> interfaces (#15278) (testing)
  • refactor(test): finish converting private-member reach-ins to typed testHooks (iOS client, daemon harnesses) (#15277) (testing)
  • main-red: ktfmt flags AutoMobilePrototypeLoadingStatesTest.kt (#14870)
  • follow-up(#14355,#14167): direct-mode readiness for embedded createMcpServer and cross-device setActiveDevice rebind (#14843) (daemon)
  • test: 33 daemon unit test files fail when heartbeat timing env overrides are set in the runner (#14750) (needs-human)
  • follow-up(#14639): empty binding that adopts a leftover simulator still loses a third of its timeout (#14643) (ios, daemon)
  • follow-up(#12226): Make the dark gallery exercise device-controlled theming (#14589) (android, triaged)
  • follow-up(#12226): Include prototype content in the Close-control goldens (#14588) (android, triaged)
  • follow-up(#12226): Capture the two sheet variants separately (#14586) (android, triaged)
  • follow-up(#12226): Interpolate repeated list-item text before recording it (#14585) (android, triaged, p1-followup)
  • follow-up(#12226): Do not make the clipped dialog render the golden output (#14584) (android, triaged)
  • follow-up(#12226): Make the light bottom-sheet baseline exercise light mode (#14583) (android, triaged)
  • follow-up(#13029): Scope action globs to their consumer filters (#14582) (triaged)
  • follow-up(#13029): Pin all four required context names (#14581) (triaged)
  • follow-up(#13029): Count composite uploads for every workflow invocation (#14580) (triaged)
  • follow-up(#13029): CodeRabbit finding in workflow-artifact-name-uniqueness.bats (#14579)
  • follow-up(#13029): Parse composite uploads without depending on key order (#14578) (triaged)
  • follow-up(#13029): Include composite uploads in the artifact-name collision guard (#14577)
  • follow-up(#13094): Preserve grep failures while allowing zero matches (#14575) (triaged)
  • follow-up(#13094): Allow the Swift test count to be zero (#14574) (triaged)
  • follow-up(#13094): Move grep options before operands for macOS (#14573)
  • follow-up(#13781): Preserve UID fallback when subprocess execution is denied (#14571) (android, triaged)
  • follow-up(#13782): Restrict the release forwarding exemption (#14570) (triaged)
  • follow-up(#13787): Disable rename detection when collecting local changes (#14569) (triaged)
  • follow-up(#13787): Make the baseline guard work in jj workspaces (#14568) (triaged)
  • follow-up(#13787): Reject replacement baseline entries with reused issue IDs (#14567) (triaged)
  • follow-up(#13790): Disable rename detection when selecting lint modules (#14565) (triaged)
  • follow-up(#13812): Remove entity headers when redirects switch to GET (#14562) (android, triaged)
  • follow-up(#13812): Preserve non-POST methods across 301 and 302 redirects (#14561) (android, triaged, p1-followup)
  • follow-up(#13815): Update the loopback guidance for the new deny policy (#14558) (ios, triaged)
  • follow-up(#13815): Let cancellation and deadlines outrank late policy errors (#14557) (ios, triaged)
  • follow-up(#13815): Preserve non-POST methods across 301 and 302 redirects (#14556) (ios, triaged, p1-followup)
  • follow-up(#13815): Register blocked_destination in the shared event contract (#14555) (ios)
  • follow-up(#13825): Expire cached skew after a backward host-clock step (#14551) (triaged)
  • follow-up(#13826): Classify benchmarking address space as non-public (#14547) (triaged, p1-followup)
  • follow-up(#13826): Preserve non-POST methods across 301 and 302 redirects (#14546) (triaged, p1-followup)
  • follow-up(#13829): Keep the required iOS launch scheme in first-release scope (#14544) (triaged)
  • follow-up(#13829): Define the bundle ID before requiring its comparison (#14543) (triaged)
  • follow-up(#13830): Run iOS tests when the shared capability fixture changes (#14537) (ios, triaged)
  • follow-up(#13830): Include every gated spec feature in required capabilities (#14536) (triaged)
  • follow-up(#13835): Preserve proto for unknown-flag validation (#14534) (triaged)
  • follow-up(#13835): Route doctor help before startup work (#14533) (triaged)
  • follow-up(#13836): Enforce the per-attempt timeout around each reopen (#14532) (triaged)
  • follow-up(#13837): Mark the host-only opacity helper as internal API (#14530) (android, triaged)
  • follow-up(#13837): Restore coverage reporting for the extracted renderer (#14529) (android, triaged)
  • follow-up(#13839): Keep the test-seam ratchet on the moved manager (#14526) (triaged)
  • follow-up(#13841): Keep snapshot argument types in the schema-drift ratchet (#14525) (triaged)
  • follow-up(#13841): Keep moved managers in the test-seam ratchet (#14524) (triaged)
  • follow-up(#13850): Join preparations even when the close snapshot fails (#14523) (daemon)
  • follow-up(#13857): Prevent shutdown from unlinking a successor token (#14521) (daemon)
  • follow-up(#13864): Declare the routing fixture as a Gradle test input (#14518) (android)
  • follow-up(#13864): Route shared fixture edits through native CI (#14517) (android, triaged)
  • follow-up(#13864): Run the new Android routing test in CI (#14516) (android, triaged, p1-followup)
  • follow-up(#13865): Restore repeated beforeEach spies after every test (#14515) (triaged)
  • follow-up(#13868): Do not await optional cache writes during live discovery (#14514) (triaged)
  • follow-up(#13870): Verify child identity before restarting its replacement (#14513) (triaged)
  • follow-up(#13870): Reserve time after the first post-setup probe (#14512) (triaged)
  • follow-up(#13871): Pin heartbeat timings instead of inheriting process env (#14511) (daemon, triaged)
  • follow-up(#13873): Preserve the default deadline for adopted remote runners (#14509) (triaged)
  • follow-up(#13876): Register the capability fixture with Android validation (#14507) (android, triaged)
  • follow-up(#13878): Preserve Git environment-based repository discovery (#14506) (triaged)
  • follow-up(#13879): Keep caller cancellation active after reply timeout (#14505) (daemon, triaged, p1-followup)
  • follow-up(#13895): Run repository scans for paths outside the allowlist (#14499) (triaged)
  • follow-up(#13897): Parse integer timeout values as decimal (#14498) (triaged)
  • follow-up(#13897): Keep PGID coordination active after calibration (#14497) (triaged)
  • follow-up(#13899): Bound the complete fleet sample instead of each phase (#14496) (triaged)
  • follow-up(#13901): Reset misses for same-PID runner replacements (#14494) (triaged)
  • follow-up(#13901): Reset misses after a confirmed healthy start (#14493) (triaged)
  • follow-up(#13901): Fence stale probes when rearming supervision (#14492) (triaged)
  • follow-up(#13904): Keep the client alive for prepared-release retries (#14490) (daemon, triaged)
  • follow-up(#13906): Anchor the enlarged backstop to notice receipt (#14489) (daemon, triaged)
  • follow-up(#13912): Expose serialization on consumers' compile classpath (#14486) (android, triaged)
  • follow-up(#13914): Allow updated bytes for an existing font face (#14483) (ios, triaged)
  • follow-up(#13916): Make PID ownership checking atomic with deletion (#14480) (daemon)
  • follow-up(#13917): Surface pending registry upgrades as unknown ownership (#14476) (daemon, triaged)
  • follow-up(#13918): Keep the launch nonce out of public environment docs (#14474) (triaged)
  • follow-up(#13920): Keep the resolver warm-up outside timed hooks (#14473) (triaged)
  • follow-up(#13922): Clear observe leases when the device incarnation changes (#14472) (triaged)
  • follow-up(#13922): Match telemetry demand to its subscription filters (#14471)
  • follow-up(#13925): Preserve retryable probe errors on database resources (#14469) (triaged)
  • follow-up(#13934): Keep sampling for telemetry subscribers during backfill (#14461) (daemon, triaged)
  • follow-up(#13935): Avoid unlinking a successor's owner sidecar (#14460) (daemon)
  • follow-up(#13935): Treat a generation mismatch as an unknown holder (#14459) (daemon)
  • follow-up(#13937): Include Package.swift in the iOS path filter (#14457) (triaged)
  • follow-up(#13939): Publish the new completeHierarchy precondition (#14455) (triaged)
  • follow-up(#13941): Keep the checker alive in the signal-cleanup test (#14452)
  • follow-up(#13941): Declare the sourced helpers as Turbo inputs (#14451) (triaged)
  • follow-up(#13964): Match coverage workers to acquired host slots (#14448) (triaged)
  • follow-up(#13968): Refresh the destination window after dispatch (#14447) (triaged)
  • follow-up(#13976): Resolve nested labels to the outermost plan owner (#14445) (daemon, triaged)
  • follow-up(#13976): Keep leases scoped to devices used by the invocation (#14444) (daemon, triaged)
  • follow-up(#13976): Cancel the captured derived-session execution (#14443) (daemon, triaged)
  • follow-up(#13978): CodeRabbit finding in GeneratedViewIdTest.kt (#14441) (android, triaged)
  • follow-up(#13979): Target the active Android user when enabling dumps (#14439) (android, triaged)
  • follow-up(#13980): Preserve the tool registry before sharing this test (#14437) (triaged)
  • follow-up(#13980): Keep singleton-mutating screenshot tests isolated (#14436) (triaged)
  • follow-up(#13981): Preserve standalone selection actions as interactions (#14435) (triaged)
  • follow-up(#13983): Capture the active bound fixture before checking advertisement (#14434) (daemon, triaged)
  • follow-up(#13984): Keep retrying when capture and event timestamps are equal (#14433) (triaged)
  • follow-up(#13984): Drain once before trusting cached SDK absence (#14432) (triaged)
  • follow-up(#13986): Keep process-exit wakeups from restarting the poller (#14430) (triaged)
  • follow-up(#13987): Keep the daemon budget below the proxy timeout (#14429) (daemon)
  • follow-up(#13989): Narrow traversal matching to Android framework extras (#14428) (android, triaged)
  • follow-up(#13990): Run dependency consumers for manifest-only bumps (#14426) (triaged)
  • follow-up(#13990): Include global preloads in the changed graph (#14425) (triaged)
  • follow-up(#13991): CodeRabbit finding in DaemonStartup.ts (#14424) (daemon, triaged)
  • follow-up(#13991): CodeRabbit finding in DaemonHttpTokenProviderTest.kt (#14423) (android, triaged)
  • follow-up(#13991): Document the transient startup response (#14422) (daemon, triaged)
  • follow-up(#13991): Skip POSIX metadata checks when sweeping Windows claims (#14420) (daemon, triaged)
  • follow-up(#13991): Update documentation for the required endpoint argument (#14419) (daemon, triaged)
  • follow-up(#13991): Trigger native CI for the shared endpoint fixture (#14418) (daemon, triaged)
  • follow-up(#13991): Avoid sweeping an in-progress removal claim (#14416) (daemon, triaged, p1-followup)
  • follow-up(#13994): Treat successful uncorrelated SDK responses as activity (#14414) (triaged)
  • follow-up(#13999): Keep a live reaper for the synthetic owner (#14413)
  • follow-up(#14000): Advertise that cancellation retries need a fresh ID (#14412) (daemon)
  • follow-up(#14010): Cancel the retry wait when acquisition aborts (#14409) (daemon, triaged)
  • follow-up(#14013): Reap the synthetic owner without relying on PID 1 (#14407) (triaged)
  • follow-up(#14020): Resolve dirty state before exiting --version (#14406) (triaged)
  • follow-up(#14024): Limit the computed-read exemption to the adapter (#14404) (triaged)
  • follow-up(#14024): Reject member-expression environment keys (#14403) (triaged)
  • follow-up(#14025): Document the per-tool timeout override precedence (#14402) (daemon)
  • follow-up(#14026): Merge shared progress before rewriting the ledger (#14401) (daemon, triaged)
  • follow-up(#14029): Restore the owner without requiring hard-link support (#14400) (daemon)
  • follow-up(#14034): CodeRabbit finding in SdkHierarchyClient.swift (#14399) (ios, triaged)
  • follow-up(#14034): CodeRabbit finding in SdkEndpointResolver.swift (#14398) (ios, triaged)
  • follow-up(#14034): Invalidate the cache on every foreground-aware SDK path (#14397) (ios, triaged)
  • follow-up(#14042): Preserve the recovery refusal kind (#14392) (daemon)
  • follow-up(#14043): Commit dedupe state only after persistence succeeds (#14391) (triaged)
  • follow-up(#14049): Check raw adb states for serial visibility (#14389) (triaged)
  • follow-up(#14133): Document the unset connection-timeout floor (#14388)
  • follow-up(#14161): Regenerate the tool contract with connection-local semantics (#14386) (triaged)
  • follow-up(#14164): Preserve accessibility-focused baseline nodes (#14384) (android, triaged)
  • follow-up(#14164): Shorten the property key for pre-O devices (#14383) (android, triaged)
  • follow-up(#14167): CodeRabbit finding in setActiveDevice.ts (#14381) (triaged)
  • follow-up(#14167): Update the direct-mode appearance-sync documentation (#14380) (triaged)
  • follow-up(#14206): Normalize session IDs before direct appearance lookup (#14379) (daemon, triaged)
  • follow-up(#14206): Normalize session IDs before gesture-device lookup (#14378) (daemon, triaged)
  • follow-up(#14347): Ignore timed-out probes during pending replacement (#14377) (daemon, triaged)
  • refactor(ios): declare the SDK-to-CtrlProxy wire models once in a shared package (#11885) (ios, needs-device-verify, sdk)
  • build(android): add an automobile.android-library convention plugin for the 16 duplicated android {} blocks (#11881) (android, devxp)
  • refactor(ctrl-proxy): make CtrlProxyActions take typed requests and be suspend; remove the overload ladder and runBlocking bridges (#11878) (android)
  • refactor(ctrl-proxy): emit every WebSocket response through the typed protocol classes; delete hand-built JSON (#11877) (android)
  • ci: stop committing README test-count badges to main; publish shields endpoint JSON instead (#11871) (ci)
  • refactor(daemon,ctrlProxy): add public test seams for the state tests reach into (about 795 private-internals casts) (#11865) (testing)
  • refactor(types): type consumers to existing interfaces instead of concrete clients (#11863) (testing)
  • chore(dead-code): delete or relocate production-unreachable modules and prune the stale allowlist (#11854) (dead-code)
  • refactor(models): make src/models a types-and-pure-functions leaf (#11853)
  • refactor(android-cmdline-tools): extract pure parsers/classifiers from AdbClient and AndroidEmulatorClient, backed by captured fixtures (#11850) (android, testing)
  • refactor(config): declare every environment variable in one typed registry (#11848) (devxp)
  • refactor(ctrlproxy): one registry interface for CtrlProxy client/manager instance lifecycle (#11847)
  • refactor(observe/android): move the inbound message router, port-forward ownership and event persistence out of AndroidCtrlProxyClient (#11846) (android)
  • refactor(selectors): finish resolver unification with one entry point and no side matchers (#11838)
  • refactor(action): type the observedInteraction pipeline and replace its flag bag with named profiles (#11834)
  • refactor(tap): split TapOnElement.executeWithReadScope into named, typed phases (#11833)
  • refactor(tap): extract the tap dispatch and search helpers duplicated between TapOnElement and TapAnyElement (#11832)
  • refactor(daemon): split DaemonMcpProxy into lifecycle reconciliation, liveness keeper, session binding and forwarder (#11816) (daemon)
  • refactor(daemon): split UnixSocketServer into connection, router, loopback pool and route modules (#11815) (daemon)
  • refactor(daemon): one input/* request preamble instead of six copies (#11814) (daemon)
  • refactor(devices): rename DeviceSessionManager to device readiness and remove its process-wide current device from daemon paths (#11810) (daemon)
  • refactor(devicePool): split DevicePool by operation over a shared DeviceTable (#11807) (daemon)
  • refactor(daemon): typed dependency object and explicit wiring module for Daemon instead of 22 positional parameters (#11805) (daemon)
  • refactor(daemon): give session release one options object and one entry point (#11800) (daemon)
  • chore(typecheck): type-check test/ behind a count baseline (#11787) (devxp, testing)
  • epic(audit): test-suite type safety and seams (#11780) (epic)

Fixed

  • test(daemon): perSourceIosLiveness.test.ts hangs at 100% CPU on origin/main (host-dependent), stalls changed-unit shard (#15323)
  • bug(ios): app-container consumers resolve pre-installed apps into the shared template on cloned simulators (putAppFile, clear data, snapshots, preferences) (#15320) (ios, daemon)
  • bug(ios): keep-booted reset falls back to erase on every template-cloned simulator because the residue reader rejects the template's app-container path (#15314) (ios, performance, daemon)
  • bug(ios): provisionDevice from a template clone fails with 'not available in the device pool' (2 of 22 minimal-profile clones) (#15295) (flaky test, ios)
  • bug(ios): name-only crash cleanup in a second daemon deletes another daemon's ready template simulator (#15290) (ios, daemon)
  • bug(ios): provision fails non-retryably when simctl list devices --json times out during a boot burst above ~24 simulators (#15289) (ios, performance, daemon)
  • bug(ios): capacity gate derives maxBooted = 10 on a 16-core / 128 GB host because the memory term sums per-process RSS (#15288) (ios, performance, daemon)
  • ci(windows): macOS-only test skip is logged but ~300 macOS-only files still run on Windows (#15237) (ci, testing)
  • ios: runner start flight ceiling counts launch-queue wait, so late-admitted launches are cancelled and requeued (#15227) (ios, daemon)
  • bug(ios): disabling every iOS device resource makes MobileCal and diagnosticd spin (#15218) (ios, performance)
  • iOS first observe on six simultaneously cold-booted sims: ~62 s degraded, then connection_lost after cancelled queued launches (#15214) (ios, daemon)
  • Session broker: release of a crashed Android emulator hangs in cleanup_pending while another daemon's emulator has no resolvable AVD name (#15213) (android, daemon)
  • iOS setUIState clear on Safari's address field reports failure although the field is cleared (text.input step with empty text) (#15212) (ios)
  • test(ci): daemon liveness/restart unit rows sit near the 100 ms budget and fail broad-affected PR runs (#15192) (testing)
  • bug(ios): first observe of several new simulators can still time out; assertCanSetup re-check does not wait for the pool transition (#15188) (ios, daemon)
  • daemon: an Android CtrlProxy client gets registered under an iOS simulator UDID (#15187) (daemon)
  • bug(ios): cold observe on more sims than the launch concurrency returns degraded ok:true for queued launches (#15184) (ios, performance)
  • bug(ios ctrlproxy): launch-progress sampler fails when the process table exceeds the ps maxBuffer (#15183) (ios, performance)
  • bug(observe): screenshot retention still evicts inside the 10-minute guarantee at 3 and 6 busy simulators (#15182) (ios, performance)
  • bug(ios): several brand-new simulators first-observed together decline the hierarchy service start (#15181) (ios, daemon)
  • bug(daemon): device held by a plain-daemon session shows no allocation claim; broker keeps probing and quarantining it (#15180) (android, daemon)
  • bug(session-broker): every iOS mockNetwork release escalates to erase through a stale Android CtrlProxy client (#15179) (ios, daemon)
  • bug(session-broker): android keep-booted clean reset deletes ringtone, alarm and opa settings present at session start (#15178) (android, daemon)
  • bug(session-broker): android snapshot reset waits out the whole budget after the emulator dies post snapshot load (#15177) (android, daemon)
  • bug(daemon): sessionless observe boots a simulator that killDevice is shutting down or has shut down (#15176) (android, ios, daemon)
  • bug(ios): setUIState clear on Safari's address field reports failure although the field is cleared (#15175) (ios)
  • bug(prototype): Android prototype save via ProtoViewer fails on API 37 (#15174) (android)
  • session-broker (android): keep-booted Doze revert unforces deep Doze without waking a slept screen (#15168) (android, daemon)
  • ios: a running daemon reboots simulators that were shut down externally while its runner is attached (#15164) (ios, daemon)
  • bug(ios ctrlproxy): concurrent cold runner launches still stall in 2 of 5 pairs after #15103 (progressing launch killed at 90 s, 120 s tool timeout) (#15163) (ios, performance)
  • bug(ios): setUIState still cannot confirm focus on Safari's address field after #15132 (6 of 6 runs) (#15162) (ios)
  • bug(android): session-release Doze restore reports failed (cleanup:failed) although the device is already ACTIVE (#15161) (android, daemon)
  • session-broker reset: narrow iOS shared-file/opened-url coverage and network-mock push-failure residual (#15159) (daemon)
  • bug(daemon): refresh-driven add and cancelled cold-boot kill can still republish a dying unpooled device (follow-up to #15151) (#15157) (daemon)
  • daemon: socket reachability probe treats any connect error as 'nobody home', so a live peer can lose its socket (#15156) (daemon)
  • bug(daemon): killDevice on an unpooled device is invisible to the pool insertion fence, so a concurrent pickup can republish a dead device (#15151) (daemon)
  • Windows: auxiliary socket reclaim always refuses a stale socket (identity unreadable, EACCES) (#15148)
  • session-broker reset: remaining fail-closed gaps after the #15105 incarnation fix (iOS unrevertible rows, settings restore, recording fail-open) (#15147) (daemon)
  • setUIState (iOS): field search swipe can start on Safari's bottom bar and open the tab overview (#15135) (ios)
  • session-broker (android): keep-booted device-state revert runs Doze commands with no read-back (#15110) (android, daemon)
  • setUIState (iOS): cannot confirm focus on Safari's address field (#15109) (ios)
  • rotate (Android): still reports success while the display stays portrait (partial #15024) (#15108) (android)
  • session-broker (ios): erase reset waits on boot capacity without bound while unowned simulators hold the cap (#15107) (ios, daemon)
  • session-broker: fixed 5 s Android CtrlProxy rebind and 30 s iOS sanitize budgets destroy or erase devices under host load (#15106) (android, ios, daemon)
  • session-broker (android): keep-booted reset reports clean but leaves journaled mutations; journal and reset scope use different incarnation shapes (#15105) (android, daemon)
  • bug(observe ios): simulator booted after daemon start is never pooled, so sessionless observe returns a degraded ok result forever (#15093) (ios, daemon)
  • perf(observe): 128 MB global screenshot cap holds about 39 iOS PNGs, so 6+ busy simulators evict screenshots before their retention guarantee (#15091) (ios, performance)
  • perf(ios ctrlproxy): flat 60 s runner launch window kills and relaunches contended concurrent launches (startDevice 116-144 s at 3 launches at once) (#15090) (ios, performance)
  • perf(ios observe): per-observe lock-state probe (simctl spawn notifyutil, 2 s timeout) times out for 60% of calls at 12 simulators and sets observe latency (#15089) (ios, performance)
  • ci: ProtoViewer apps are not exercised by CI — :protoviewer unit tests never run, no assemble, no iOS launch smoke (#15064) (android, ios, ci, testing)
  • perf(ios): daemon's 30 s /sdk-events poll keeps OSLogReader permanently awake (45 s idle window), so idle simulators still cost ~35% of a core (#15060) (ios, performance)
  • Unit tests over the 100ms budget in CI: brokerAndroidReset keep-booted cleaner (140ms) and livenessScenarioMatrix #10656 window (101ms) (#15059) (ci)
  • releaseSession: alreadyReleased:true is returned for sessions the daemon never had (and for unfinished cleanup) (#15052) (daemon)
  • SimulatorResidueReader unit tests fail on windows-latest: host path separators applied to simctl POSIX paths (#15048) (ios, ci)
  • follow-up(#15040): Doze restore on session release verifies with a single read; sessionless doze off doesn't re-plug a pre-set USB charge (#15042) (android, needs-device-verify)
  • UnixSocketServer: closed listener stays reachable on Windows with Bun 1.4.4 (2 integration tests skipped) (#15035) (ci)
  • perf(dev env): Spotlight (mds_stores ~180% CPU) indexes worktrees, scratch/, DerivedData and simulator build output (#15032) (devxp, performance)
  • perf(daemon): daemon spawns simctl repeatedly for booted simulators while idle (#15031) (performance, daemon)
  • perf(ios ctrlproxy): idle CtrlProxyUITests-Runner burns ~47% CPU building XCElementSnapshot trees and flushing XCTest debug logs with no request in flight (#15030) (ios, performance)
  • perf(ios ctrlproxy): OSLogReader polls OSLogStore every 1 s even with no consumer, costing ~55% CPU per simulator in OSLogService plus host diagnosticd (#15029) (ios, performance)
  • pressButton home on Android returns failure 'No visual change observed' when the device is already on the home screen (#15028) (android)
  • Android keep-booted reset: fixed 2 s adb caps in the cleaning phase destroy the device under load (#15027) (android, daemon)
  • Broker provisioning: a foreign emulator with an unresolvable AVD name blocks cold boot with a non-retryable provision_failed (#15026) (android, daemon)
  • iOS erase reset: a simulator that waited in bootQueue is destroyed on retryable discovery_incomplete instead of being retried (#15025) (ios, daemon)
  • rotate (Android): reports success while the display stays in portrait when auto-rotate is on and the foreground app follows the sensor (#15024) (android, needs-device-verify)
  • main red: Detekt ComplexCondition + CyclomaticComplexMethod in IcuRegexCompatibilityTest.constructorCall (#15023) (android, ci)
  • rotate (Android): document that a plain direct rotate with auto-rotate on reports failure by design (#15022) (android)
  • rotate (Android): the 500 ms rotation wait times out on every call on a loaded emulator (#15021) (android)
  • setActiveDevice with several devices and no platform returns an untyped error, while platform-only ambiguity returns ambiguous_device_target (#15020) (daemon)
  • stdio proxy hung in initialize for more than 5 minutes after a daemon restart with an acquisition in flight (1 of 3, not reproduced) (#15019) (daemon)
  • Reset receipt phases omit the maxConcurrentResetBoots queue wait, so total reset time exceeds the sum of phases by the wait (#15018) (daemon)
  • iOS keep-booted reset leaves out-of-band residue that grows by one item per reuse, with no cap or erase escalation (#15017) (ios, daemon)
  • broker: shut-down AVDs with unresolved power state are charged as orphans and exhaust the binding budget (#15016) (daemon)
  • Stale CtrlProxy APK is never replaced when the service is already enabled and connected (same versionName) (#15007) (android)
  • setDeviceState power doze off leaves the device asleep, unplugged and in forced deep Doze (#15006) (android, needs-device-verify)
  • systemAlerts deny/allow policy taps a permission dialog still animating in, then reports it "still showing" (#15005) (android, ios, needs-device-verify)
  • prototype(ios): chart marks expose plot coordinates as accessibility labels (#15004) (ios)
  • iOS rotate failure on the home screen leaves the device in landscape (#15003) (ios, needs-device-verify)
  • iOS sendKeys in Safari reports 'nothing was typed' though the URL field got the text (#15002) (ios, needs-device-verify)
  • Android keep-booted clean release leaves the live wm density override and uimode night mode applied (#15001) (android, daemon)
  • Android reset/capture inventory probes every adb device (incl. other daemons' emulators) with display probes under a 2 s cap, so baselines are lost under load (#15000) (android, needs-device-verify, daemon)
  • Library-mode secure binding rejection says "bound into a request" for setData/appendData/emit/platform paths (#14999) (android, ios)
  • Android wipe-data reset fallback always destroys the device: stop() fails on a 2 s inventory poll while the emulator is still exiting (#14998) (android, needs-device-verify, daemon)
  • ProtoViewer (Android): every import fails with "library: Storage" because bundle staging lists unreadable ancestors (/data, /data/user/0) (#14997) (android)
  • main-red: IcuRegexCompatibilityTest rejects dynamic Regex in PrototypeSpecContract.kt:24 (from #14982) (#14989) (android)
  • main red: :protocol:detektMain fails on PrototypeStrictPolicy.secureLibraryError (complexity/length), from #14970 (#14983) (android, ci)
  • ci: CircleCI ios-playground-tests fails to link PlaygroundTests (undefined AutoMobileSdkWire symbols) since #12943 (#14980) (ios, ci)
  • follow-up(#14975): ProtoViewer Android render guard misses layout/draw errors and StackOverflowError; revoked local-network permission not re-checked at startup (#14976) (android)
  • follow-up(#14965): Android keep-booted journal reset ignores a deviceSnapshot session (#14966) (android, daemon)
  • Android baseline capture gives each adb step a fixed 2 s with no retry, so host load discards the baseline and the device is destroyed (#14956) (android, daemon)
  • rotate (Android): a failed unlocked landscape rotate leaves user_rotation=1, and a later portrait rotate does not reset it (#14955) (android)
  • iOS: pressButton home on SpringBoard (home page 2) fails with 'No visual change observed' instead of succeeding or reporting already-home (#14954) (ios)
  • iOS: keyboard close fails in Safari on hardware-keyboard simulators (taps an off-screen 'Go' key) although detect reports closed (#14953) (ios)
  • Android snapshot reset destroys every session that made a mutating tool call (no snapshot load, no wipe-data fallback) (#14952) (android, daemon)
  • Android reset baseline rejects the stock API 37 'dropbox:' secure settings keys, so keep-booted/snapshot reset never runs (#14945) (android, daemon)
  • provisioning: never auto-select a Wear OS, TV or Automotive system image for a default Android device (#14900) (android, android-wear)
  • Session broker: device session bound during preparation is cancelled by the 4 s heartbeat monitor while the baseline is captured, failing the acquisition non-retryably (#14835) (android, ios, daemon)
  • iOS 27 simulator: pressButton home / homeScreen fail while Spotlight is open (press_failed, Spotlight stays foreground) (#14827) (ios)
  • CI: iOS Device Capture to WHEP cleanup pkills every AutoMobile daemon on the self-hosted Mac host (source of the 'external SIGTERM' in manual tests) (#14826) (ci, testing)
  • prototype(ios): shared motion bound fixtures are not rejected by the Swift loader (PrototypeSizeBoundsTests red on main) (#14801) (ios)
  • prototype(android): loading-states fixture renders blank on the emulator (#14793) (android)
  • Admission wait for a resetting device expires just before the reset finishes, then pays a full cold create (#14791) (performance, needs-human, daemon)
  • Journal: iOS increaseContrast mutations are never recorded in the session mutation journal (#14790) (ios, daemon)
  • Manual-test broker harness rejects limits.maxConcurrentResetBoots and counts ambroker-* verify fixtures against the 4-device cap (#14789) (testing)
  • Session broker adopts a leftover same-named simulator from a previous registry and reports admission:create without any reset (#14788) (ios, daemon)
  • iOS keep-booted 'privacy reset all' leaves a baseline app's privacy grant in TCC (contacts for Safari survives a clean release) (#14787) (ios, daemon)
  • iOS keep-booted reset always falls back to erase on iOS 27: absent-key 'defaults delete' wording not recognized (AppleCalendar) (#14786) (ios, performance, daemon)
  • follow-up(#14779): grants created before a daemon restart leave down timing out (unverified grants) and a pooled sim Booted (#14780) (daemon)
  • main red: manualTestBrokerLiveAdapter 'acquire distinguishes a non-broker name from a protected device (protected=true)' throws Tampered batch manifest (#14778) (ci)
  • main red: refusalWireContract flags EmulatorConsolePortExcludedError and DaemonRestartOptionsUnknownError as unclassified coded errors (#14770) (ci)
  • Broker Android reset dispatch never reaches the baseline reset on a real device: fallbackReason 'lacks its original acquired transport identity' (#14744) (android, daemon)
  • Broker Android acquisition boots its AVD on emulator-5554 (no console-port floor/exclusion); harness then refuses info on its own grant (#14743) (android, daemon)
  • A live stdio proxy auto-restarts a dead private daemon with default options: drops --embedded-sdk/--debug and binds shared port 3000 (#14742) (daemon)
  • statusBar clear (Android) leaves sysui_demo_allowed=1 after an override that enabled it (#14741) (android)
  • sendBroadcast reports delivered:true for a nonexistent receiver component and for an uninstalled package (#14740) (android)
  • getLogs (iOS Simulator): subsystem-only attribution returns 0 lines for apps that log under other subsystems (#14739) (ios)
  • audit (Android): contrast check samples the background as text colour, reporting ~1.16:1 on high-contrast Settings titles (#14738) (android, a11y)
  • performanceTrace: 0-byte Perfetto trace on Android (pulled before flush); malformed xctrace and 90 s stop on iOS Simulator (#14737) (android, ios, performance)
  • displayConfig iOS Simulator: boldText fails when the accessibility key is absent; fontScale 0.8 (extra-Small) poisons later calls (#14736) (ios, a11y)
  • main red: validateMarkdownRepoPaths flags docs/design-docs/atc-build-integration.md -> src/cli.mjs (#14723) (documentation, ci)
  • Local gates fail on pristine main in the sandbox: validateMarkdownRepoPaths, fastValidationRegistryCoverage, oxlintConfigScoping.integration, integrationSafeTier, appFileService rollback (#14717) (ci, devxp)
  • main red: :protocol:detektMain CyclomaticComplexMethod in PrototypeObjectRules.visitObject (15 > 14) (#14716) (android, ci)
  • main red on macOS: IosCtrlProxyBuilder 'codesign require flag yes' expects false after #14354 made yes truthy (#14686) (ios, ci)
  • bug(ios): userDefaults preference container lookup gets one 10s get_app_container attempt with no retry and reports the wrong timeout (#14683) (ios)
  • Daemon shutdown during an in-flight broker acquisition fails it as non-retryable provision_failed instead of session_broker_stopping, so the proxy never re-prepares (#14673) (needs-human, daemon)
  • setUIState toggle by label text on iOS taps the row/label, never flips the switch, and retries 3x (#14659) (ios, needs-human)
  • Long-lived proxies thrash the shared daemon on dirty-state change: version-string mismatch with identical build ID restarts the daemon on every call (#14658) (needs-human, daemon)
  • setUIState dropdown on a platform Spinner reports verification failure (observed undefined) after a successful selection and retries 3x (#14657) (android)
  • follow-up(#13029): Include shared actions in their consumer path filters (#14576)
  • follow-up(#13778): Re-cut and pin the Control Proxy APK (#14572) (android)
  • follow-up(#13787): Compare lint baselines with the actual PR base (#14566) (triaged)
  • follow-up(#13790): Lint reverse dependents of changed libraries (#14564) (triaged, p1-followup)
  • follow-up(#13812): Add the blocked error to the TypeScript event contract (#14560) (android)
  • follow-up(#13812): Re-cut the Android runner so the policy ships (#14559) (android)
  • follow-up(#13824): Wait for delayed toggle state before retrying (#14553) (triaged, p1-followup)
  • follow-up(#13824): Keep settling the dropdown-opening tap (#14552) (triaged)
  • follow-up(#13825): Include the device incarnation in cache identity (#14549) (triaged, p1-followup)
  • follow-up(#13825): Invalidate cached skew when DeviceState changes the clock (#14548) (triaged, p1-followup)
  • follow-up(#13826): Decode the /48 NAT64 layout instead of its suffix (#14545) (triaged, p1-followup)
  • follow-up(#13829): Reject imports with missing referenced assets (#14542) (triaged, p1-followup)
  • follow-up(#13829): Define an Android inbox route the importer accepts (#14541) (triaged)
  • follow-up(#13829): Use a pin-capable iOS transport for the egress policy (#14540) (needs-device-verify, triaged, p1-followup)
  • follow-up(#13829): Declare the permission needed for promised LAN access (#14539) (triaged)
  • follow-up(#13836): Avoid an unbounded read after reporting a timeout (#14531) (triaged)
  • follow-up(#13837): Update every renamed Compose-report fixture reference (#14528)
  • follow-up(#13837): Add the new renderer to Maven release delivery (#14527) (android)
  • follow-up(#13852): Keep warm resource refreshes cancellable (#14522) (daemon, triaged)
  • follow-up(#13857): Publish the token only after claiming the control socket (#14520) (daemon)
  • follow-up(#13857): Restrict daemon credentials to loopback daemon endpoints (#14519) (ios)
  • follow-up(#13871): Drive reclaim through the heartbeat-first production path (#14510) (daemon, triaged)
  • follow-up(#13873): Seal symlink identity in codesign cache keys (#14508) (triaged, p1-followup)
  • follow-up(#13881): Add the backpressure page to the MkDocs classification (#14504)
  • follow-up(#13881): Keep device epochs separate in coalescing keys (#14503) (daemon)
  • follow-up(#13890): Remove the stale test typecheck baseline (#14502)
  • follow-up(#13894): Avoid deleting sibling data for direct XML inputs (#14500) (triaged, p1-followup)
  • follow-up(#13899): Start the capacity-sample budget after replacement lookup (#14495) (daemon, triaged)
  • follow-up(#13903): Retry stopping prepares instead of polling a missing receipt (#14491) (daemon)
  • follow-up(#13907): Route bound-proxy inventory calls before session injection (#14487) (daemon)
  • follow-up(#13912): Add prototype-compose to the release publication set (#14484) (android)
  • follow-up(#13914): Validate the complete spec before rendering (#14482) (ios, needs-device-verify, triaged)
  • follow-up(#13915): Preserve high measured RSS for in-flight simulators (#14481) (triaged, p1-followup)
  • follow-up(#13916): Refresh control-socket identity after recovery rebinds (#14478) (daemon)
  • follow-up(#13916): Keep degraded observation streams in the recovery loop (#14477) (daemon)
  • follow-up(#13917): Keep the recursive scan inside the timed test (#14475) (testing, triaged)
  • follow-up(#13924): Share one timeout across the rollback sequence (#14470) (daemon, triaged, p1-followup)
  • follow-up(#13925): Preserve typed probe errors through the highlight handler (#14467) (triaged, p1-followup)
  • follow-up(#13931): Reduce the regression test below the unit-test time limit (#14466) (android, testing, triaged)
  • follow-up(#13931): Re-cut and pin the Android CtrlProxy artifact (#14465) (android)
  • follow-up(#13932): Tell clients to retry eviction with a new request ID (#14463) (daemon, triaged, p1-followup)
  • follow-up(#13932): Preserve zero as an absolute device cap (#14462) (daemon, triaged)
  • follow-up(#13936): Preserve the full timeout for non-retryable iOS paths (#14458) (daemon, triaged, p1-followup)
  • follow-up(#13938): Re-cut the APK that carries this refactor (#14456) (android)
  • follow-up(#13939): Hash the uncapped raw hierarchy for snapshot validation (#14454) (triaged, p1-followup)
  • follow-up(#13939): Include interaction state and identity in the layout digest (#14453) (triaged, p1-followup)
  • follow-up(#13941): Reserve the full pool before running uncapped (#14450) (daemon, triaged)
  • follow-up(#13950): Restore the shared connection-loss notifier (#14449) (triaged, p1-followup)
  • follow-up(#13968): Force fresh extraction for quiet-tree polls (#14446) (triaged, p1-followup)
  • follow-up(#13977): Track inventory mutations across sockets (#14442) (daemon, triaged, p1-followup)
  • follow-up(#13978): Ship a rebuilt control-proxy APK (#14440) (android)
  • follow-up(#13979): Re-cut the Android runner with this change (#14438) (android)
  • follow-up(#13985): Re-cut the Android runner artifact (#14431) (android)
  • follow-up(#13989): Re-cut the APK before relying on this filtering (#14427) (android)
  • follow-up(#13991): Honor the full startup window before exhausting retries (#14415) (android, triaged, p1-followup)
  • follow-up(#14003): Republish identity after the stream rebinds (#14411) (daemon, triaged, p1-followup)
  • follow-up(#14005): Settle receipt-less pre-prepare timeouts (#14410) (daemon, triaged)
  • follow-up(#14010): Reconnect before retrying prepare (#14408) (daemon, triaged, p1-followup)
  • follow-up(#14020): Preserve dirty state in the frozen daemon version (#14405) (triaged, p1-followup)
  • follow-up(#14034): Publish the runner containing this cache (#14396) (ios)
  • follow-up(#14036): Defer serialization until after the screenshot backpressure check (#14395) (daemon)
  • follow-up(#14041): Update the stale shutdown test seam (#14394) (daemon)
  • follow-up(#14043): Fingerprint nodes beyond the serialized prefix (#14390) (triaged, p1-followup)
  • follow-up(#14161): Use the effective connection key for device pins (#14385) (triaged, p1-followup)
  • follow-up(#14164): Re-cut the downloadable CtrlProxy APK (#14382) (android)
  • Healthy emulators quarantined and getAndroid fails device_lost when a 2 s 'emu avd name' probe times out under host load (#14333) (android)
  • prototype(android): a horizontal pager or carousel inside a horizontal scroll crashes the renderer, and the validator accepts it (#14165) (android)
  • timeouts: Kotlin junit-runner and Swift XCTestRunner daemon clients give up before the daemon's tools/call budget (#14132)
  • daemon: identity-recovery restart deferrals classify active_operations as unavailable (early operator guidance) (#14079) (daemon)
  • shake: tool description says "iOS Simulator only" but an Android emulator implementation exists (#14078) (documentation, android)
  • systemTray close does not dismiss the iOS 27 Notification Center cover sheet (reports 'tray remained open') (#14033) (ios)
  • daemon handoff: owned-record restore needs a no-clobber path that works without hard links (#14032) (daemon)
  • Session broker proxy: final release retry can request a replyBudgetMs above its own remaining timeout (#14012) (daemon)
  • Session broker: stored 'cancelled' preparation receipts should advertise retryRequires: new_request_id (#14011) (daemon)
  • test(bats): host-heavy-run 'pool is empty again after a run and after a killed run' races: 'sleep 2 ""' exits at once, kill finds no process (#14004) (testing)
  • main red: proxyResultMintedSession/sessionPlatformRouting expect listDevices/listDeviceImages hidden for bound proxies, plus BATS Shell Tests failing (blocks Dependabot PRs) (#13998)
  • verify-runtime-deps.sh sources ~/.bashrc under set -e and exits 1 silently on a developer host (#13959)
  • observe(android): SafeAreaAuditor treats every node as interactive because baseline accessibility actions count, so ~2/3 of gesture-region warnings are false (#13955) (android)
  • Type-aware lint (tsgolint) and tsgo typecheck run unbounded and outside the host test-slot cap (#13910) (performance)
  • test-ts.sh changed lane runs each shard as one bun --isolate process that grows to ~13 GB RSS (#13909) (performance, testing)
  • prepush-node.sh duplicates full-program type-checks and unit runs, including in --changed mode (#13889) (performance)
  • validate-bun-test-timings.sh ignores the JUnit path it is given and runs a full 14-shard unit lane (#13888) (performance, testing)
  • test-ts.sh unit shards survive a killed caller: own process groups, no signal-forwarding trap (#13887) (testing)
  • test-ts.sh sizes unit shards and --parallel from host cores per invocation with no host-wide cap (#13886) (performance, testing)
  • ci: main red on On Merge: prototypeToolCapabilityGateParity iOS gestures case fails on ubuntu (#13885) (ci)
  • ci: main red on On Merge: Windows-only unit and integration test failures (paths, ctime cache, token rename) (#13884) (ci)
  • ci: main red on On Merge: ktfmt fails on two android build-logic .gradle.kts files (#13883) (ci)
  • ci: main red on On Merge: BATS typecheck-baseline #5 and compose-compiler-report #6/#7 (#13882) (ci)
  • Daemon handoff: launch readiness accepts whichever daemon answers the socket, cleanup can delete a successor's PID record, and one orphaned aux-socket listener makes every new daemon exit (#13863) (daemon)
  • Boot capacity (iOS): derived simulator limit averages RSS of just-booted simulators, so in-flight boots raise the limit (iOS sibling of #12036) (#13862) (ios, performance, needs-device-verify)
  • Session broker iOS clean reset reboots the erased simulator with a raw simctl boot that bypasses the iOS boot admission gate, oversubscribing the host when releases overlap acquisitions (#13861) (ios, needs-device-verify, daemon)
  • Managed re-own: binding_ownership_unconfirmed has no time or attempt bound, and non-recoverable claim refusals (scope_not_valid, binding_missing, device_assigned_elsewhere) retry forever (#13860) (daemon)
  • Readiness auto-start (no deviceId) boots the first available simulator/AVD by UDID, including shut-down ambroker- broker devices that generic auto-start excludes (#13859) (android, ios, needs-device-verify, daemon)
  • Session broker: an unresolved idle-device eviction fails the request as non-retryable session_preparation_failed, and over-cap admission evicts the only compatible idle device instead of reusing it (#13858) (daemon)
  • Session broker: drainAndReset turns any error, including a busy registry write or a simctl inventory timeout, into device destruction, so reuseCleanDevices loses warm devices under load (#13856) (daemon)
  • Disconnect monitor: any running plan defers device-loss handling for every device, and plan-time loss confirmation is Android-only, so a dead iOS simulator is never released while plans run (#13855) (ios, daemon)
  • Android: ADB transport loss after dispatch (connection terminated / error: closed) is untyped; device_transport_unavailable needs dispatched: unknown so single-use openLink callers know whether to reissue (#13822) (android)
  • iOS CtrlProxy under load: supervisor restarts a live runner after one missed 2 s health probe; codesign/spctl re-run on every launch with no timeout; first-launch 2x health window is capped by the 30 s shared deadline (#13821) (ios, performance, needs-device-verify)
  • iOS boot capacity: 'ours' is an in-memory UDID set, so after a daemon restart broker-held simulators are reported as externalDevices; warm-match log names simulators held by other sessions (#13820) (ios, daemon)
  • Binding replacement: pre-delete boot-capacity check reserves nothing, so a concurrent boot takes the freed slot and the replacement is refused capacity_exhausted after deleting its device (#13818) (daemon)
  • Session broker: release during an unadopted restart handoff fails untyped ('belongs to another daemon process generation'), and session_broker_unavailable carries no retryable flag during startup/shutdown (#13817) (daemon)
  • Broker proxy: a recoverable daemon_stalled tool error is returned as terminal broker_session_ended (retryable:false, relaunch_session_request) while the proxy still holds and later resumes the session (#13816) (daemon)
  • cli: doctor --help runs the full unfiltered doctor instead of printing help (#13811)
  • systemTray clearAll on a grouped app: shade not readable after dismissal (read timed out), nothing cleared on API 37 (#13810) (android)
  • simctl: any call under an abort signal loses the 60 s per-command cap, and the binding spec resolver reads runtimes/devicetypes 4x per reconcile uncached (#13809) (ios, performance)
  • iOS SDK capability probe: a 1 s get_sdk_capabilities timeout is reported as 'app does not expose the AutoMobile SDK' (#13808) (ios, needs-device-verify)
  • iOS readiness: typed boot timeouts are rewrapped as plain errors and runner-setup fails after one attempt, so load-induced failures surface as non-retryable platform_command_failed (#13807) (ios, needs-device-verify)
  • iOS boot cleanup: failed/cancelled boots run a 10 s unverified simctl shutdown and kill() reports confirmed immediately, leaving orphaned booted simulators (#13806) (ios, needs-device-verify)
  • provisionDevice (binding create): a retryable readiness timeout deletes the just-created, booted iOS simulator, so every retry pays a fresh create + cold boot (#13805) (ios, performance, needs-device-verify)
  • readiness (iOS): after setup, one 2 s hierarchy probe miss force-restarts the runner under the 30 s health window, so a cold relaunch is aborted (post-setup sibling of #7908) (#13804) (ios, needs-device-verify)
  • Session broker: startup recover() destroys orphaned devices serially before the control socket binds, and one slow delete stalls every later cleanup (#13802) (performance, daemon)
  • Binding reconciler: 5 s boot-capacity deadline is shorter than the gate's 15 s fleet sample and never cancels it, so loaded iOS hosts get spurious discovery_incomplete and stacked simctl/ps samples (#13801) (ios, performance, needs-device-verify, daemon)
  • Session broker: prepareSession reply timeout sends a cancel frame that aborts the daemon-side preparation, so status recovery can only read a (often non-retryable) failure (#13800) (daemon)
  • Session broker shutdown: restart-handoff mark waits behind the in-flight recovery pass and preparations inside a 200 ms stage, so live sessions are retired as session_owner_exited after a restart (#13799) (daemon)
  • Session broker: release-broker-session runs the iOS reset or journal delete inline with no bound or cancellation, outlasting the 240 s CLI timeout (worst when racing a heartbeat release) (#13798) (daemon)
  • timeouts: client and daemon resolve tools/call budgets from separate environments; the client backstop cancels openLink/observe the daemon would still wait for (#13797) (daemon)
  • routing: listDevices/listDeviceImages with a platform argument are forwarded on the autolocked device lane instead of host:inventory (#13796) (daemon)
  • push streams: a slow subscriber gets every frame appended without backpressure, buffering up to ~30 s of screenshots in the daemon heap (#13795) (performance, daemon)
  • disconnect monitor (iOS): a failed simctl sweep resets the miss streak, so a lost simulator may never be confirmed on a loaded host (#13793) (ios, needs-device-verify, daemon)
  • daemon: strictly-older daemon takeover is deferred without bound and its admission RPC uses the 120 s default under the startup lock (#13792) (daemon)
  • systemTray open on iOS 27 reports the tray closed: Notification Center hierarchy matches no detector hint (#13605) (ios, needs-device-verify)
  • Android UI-stability wait is a fixed 68 ms for Settings, SystemUI and launchers, and measures the pre-action package (#13563) (android, needs-device-verify)
  • tapOn/tapAny effect: the screen-change fingerprint includes the SystemUI status bar, so a clock tick reads as a screen change (#13561) (android)
  • bug(daemon): disconnect monitor counts a TTL-cached device list as an independent sweep toward the 3-miss threshold (#13551) (daemon)
  • setUIState (iOS): field that already holds text is not re-focused when the keyboard is closed (#13539) (ios)
  • prototype(android): via:"device" request ignores timeoutMs above 10 s (default OkHttp readTimeout wins) (#13455) (android)
  • Follow-ups from post-merge review of #12613–#12650: API ≤30 sendKeys chunking, lint and fake gaps (#12733) (android, needs-device-verify)
  • IDE recording: a device switch leaves a stale Stop button, and a recording started while unregistered has no owner so Stop fails after rotation (#11366) (intellij plugin, video, desktop)
  • IDE: screenshot and SELECT still carry the desktop sessionUuid, so reads fail between a release and the rotation (#11364) (intellij plugin, desktop)
  • desktop appearance: choice is lost on every session rotation, and an observer's explicit light/dark is never applied on claim (#11363) (intellij plugin, desktop)
  • test(prototype-ux): Android screenshot harness ignores spec.theme; add real dark-mode baselines and --theme both preview (#11217) (android, testing)

Security

  • Bump Bun to 1.4.4: refreshed NSS roots drop emSign ECC Root CA - G3 (eMudhra key compromise) (#14979) (dependencies, needs-decision)
  • follow-up(#14972): ProtoViewer Android network switch — cancel in-flight requests on switch-off, provenance band on spec-opened windows, switch state when local-network permission is denied (#14973) (bug, android)
  • iOS keep-booted reset leaves a user-trusted root CA in the simulator trust store (simctl keychain reset does not clear tsettings) (#14828) (bug, ios, daemon)
  • feat(android): set and clear a secure lock-screen credential (PIN/password/pattern) with session restore (#14107) (enhancement, android, testing)
  • docs/decision(device-condition): document the hardware-attestation ceiling + explicit refusals (#14074) (documentation, needs-decision)

Other

  • test(daemon): perSourceIosLiveness.test.ts produces no results and hangs a whole-directory bun test run (#15325) (testing)
  • session-broker (ios): after an erase reset, listDevices reports the broker-idle simulator with poolStatus null and no heldBy (#15233)
  • session-broker (ios): support reuse.ios fallback "destroy" (delete + recreate) for keep-booted, never erase (#15232)
  • perf(ios): capacity gate uses measured settled cost and a boot-concurrency limit instead of cores/2 (#15220) (ios, performance, daemon)
  • research(ios): measure minimal service profiles, clone combinations, idle drift and concurrent first boots (#15219) (ios, performance, research)
  • prototype(ios): forward the per-call timeoutMs to the prototype agent instead of the fixed 15 s request timeout (#15116)
  • feat(android): Android TV — focusNavigate (and a select key if enter is not enough) (#14947) (android)
  • feat(android): form-factor vocabulary — tv, watch and automotive in device matching and provisioning (#14946) (android)
  • flake: mcpForwardByteParity 'every refusal fixture crosses both paths unchanged' times out at 20 s in the safe integration tier (#14695)
  • main red: anthropicInputSchemaSubset pins 93 advertised tools, setSensor (#14605) made it 94 (#14687)
  • First mutating call from a session owner after a daemon restart is refused with non-retryable device_owned_by_other_session (#14668)
  • follow-up(#14390): TelemetryEventBuffer receipt hook so buffered-mode iOS layout dedupe can confirm writes (#14625)
  • docs(session-broker): device reuse modes, reset configuration and cap sizing guidance (#14366) (documentation, daemon)
  • ci: a fixture-only change under test/fixtures/prototype-spec does not run the Android renderer tests (#14166) (android, ci)
  • docs: openLink/observe timeout env rows should say the 120 s connection timeout still floors the budget when neither variable is set (#14138) (documentation)
  • perf(android): startup-validation serial probe misses emulators adb lists as offline (#14131) (performance)
  • spike(device-condition): verify -writable-system ⇄ snapshot persistence + capability-probe checklist (#14053) (android, research)
  • flake: check-no-new-direct-security.bats test 6 teardown 'rm -rf' fails with Directory not empty (#14019)
  • Emulator teardown retries a soft emu kill forever; never escalates to a forced kill or quarantines the binding (#14018) (needs-human)
  • Unit timing: proxyServerLazyToolList first test over 100ms budget on ubuntu CI (cold import) (#14016)
  • main red: IOSCtrlProxyClient.ts is 1001 non-blank lines (file-size ratchet) after #13984 + #13994 combined (#14014)
  • daemon handoff: PID-record and aux-socket owner-sidecar removal are check-then-unlink (cross-process TOCTOU) (#14002)
  • ci: Windows unit lane fails on proxyResultMintedSession listDevices/listDeviceImages and simctl bootstatus abort tests (seen on PRs 13982, 13986) (#14001)
  • CtrlProxy unit test AutoMobilePrototypeParityScreenshotTest fails with IllegalStateException (required check red on unrelated PR) (#13997)
  • push streams: serialize each push frame once per broadcast instead of once per subscriber (#13993)
  • perf(ios): boot verification and broker baseline reset use full-enrichment simctl list (k+1 io enumerate each) to read one simulator's state (#13972) (performance, needs-device-verify)
  • perf(android): runner readiness resetSetupState wipes the caches it just filled, so 5 CtrlProxy adb reads run twice per fresh-device acquisition (#13971) (performance)
  • perf(android): emulator launch always waits the full 5 s startup-validation timer before readiness polling starts (6/6 launches) (#13970) (performance)
  • perf(android): waitForEmulatorReady releases the caller on a fixed 500 ms tick, adding ~0.28 s to every acquisition after the poller is ready (#13969) (performance)
  • perf(ios runner): every hierarchy request on a no-SDK simulator app runs 9 failed loopback probes and logs a warning (#13967) (ios, performance)
  • perf(ios): runner performance_update frames (1/s) reset the SDK-event poll backoff, so /sdk-events is polled every 2 s forever (#13966) (ios, performance)
  • perf(ios): every received hierarchy is persisted and pushed as a full-tree layout_events row (10-158 KB each) (#13965) (ios, performance)
  • perf(ios): runner startup sleeps a fixed 500 ms after /health although /health and the WebSocket share one listener (#13963) (ios, performance)
  • perf(ios): every observe spends a fixed ~100 ms polling /sdk-events for a screen identity that rarely arrives (#13962) (ios, performance)
  • perf(ctrlproxy android): every inbound frame eagerly full-parses JSON and compiles a Regex just to build a Log.d line (#13958) (android, performance)
  • perf(ctrlproxy android): findAccessibilityFocus issues 2N+1 extra binder calls per capture when no window has accessibility focus (#13957) (android, performance)
  • perf(ctrlproxy android): volatile SPANS/traversal extras bloat 10-14% of the wire and are hashed into StructuralHasher (#13954) (android, performance)
  • perf(ctrlproxy android): latest_hierarchy.json is rewritten on every hierarchy change and request though nothing reads it (#13953) (android, performance)
  • perf(ctrlproxy android): generated view-id costs a SHA-256 lookup and 16 String.format calls per node without a resource-id (#13952) (android, performance)
  • perf(mcp): outputSchema is 82% of tools/list (333 of 406 KB); observation schema inlined repeatedly, costs ~240 ms of client Ajv compile (#13951) (performance)
  • perf(daemon): PerformanceMonitor demand probe oversamples (telemetry filter ignored, device-stream wakes iOS) (#13921) (performance, daemon)
  • Proxy acquisition: re-prepare on session_broker_stopping instead of polling status (#13898)
  • Session broker restart-handoff refusals: retryAfterMs cadence and log level (#13847)
  • Session broker close(): first restart-handoff mark has no try/catch (#13846)
  • BrokerSessions.releasePrepared drops the session on any error, including retryable session_restart_handoff_pending (#13845)
  • Session broker: abandon during shutdown fails untyped ("Session broker is stopping") (#13844)
  • perf(session broker): trimmed idle tombstones are never pruned and every admission scans failed receipts x all resource rows under the write lock (#13803) (performance, database, daemon)
  • perf(daemon): PerformanceMonitor samples every session device every 500 ms with no subscriber (iOS: full ps aux per device per metric; Android: dumpsys gfxinfo reset per tick) (#13794) (performance, daemon)
  • manual-test broker scenario #12452-prep-timeout cannot pass when the 1ms deadline expires before prepare is sent (#13743) (testing)
  • tool_calls.error_type is '_' for thrown ActionableError (constructor.name is minified in dist) (#13655)
  • launchApp loses device_transport_unavailable: ListInstalledApps swallows the typed adb error (follow-up to #13607) (#13654)
  • provisionDevice refuses a new uniquely-named AVD with discovery_incomplete when any sibling emulator's AVD identity is momentarily unresolved (#13609)
  • tool_calls records every tool call as status='success' with no error or device_id, including calls that returned errors (#13608)
  • Android: a transient "device '' not found" on a healthy session device fails launchApp/openLink/observe immediately with untyped, non-retryable errors (#13607)
  • perf(ci): On Merge runs TypeScript coverage (10 min) plus a second ubuntu unit lane on every push to main (#13569) (performance)
  • perf(test): 470 spyOn-only unit files can run in shared processes (354 s isolated vs 16 s shared, 0 failures) (#13568) (performance)
  • perf(test): test/lint whole-tree AST guards re-parse the repo per file (46 s, 7.9 GB) and pre-push runs them twice (#13567) (performance)
  • perf(test): unit shard 0 shared process is OOM-killed on the 4x8 runner (8 of 10 PR runs); toolRegistryIsolation alone holds 2 GB (#13566) (performance)
  • perf(ci): Fast Validation scripts-referenced takes 300-330 s on CI and gates every needs: fast-validation job (#13565) (performance)
  • perf(actions): every action spawns adb shell date +%s%3N to re-measure clock skew (#13564) (android, performance)
  • perf(actions): a tapOn computes 30-40 full-tree md5(JSON.stringify) fingerprints, re-hashing the unchanged previous tree on every poll (#13562) (performance)
  • perf(daemon): tools/list costs ~24 ms of event-loop CPU per call (403 KB, re-copied and zod-validated on the loopback hop) (#13550) (performance, daemon)
  • perf(startup): source-checkout version stamping spawns git synchronously at every process start (+2.1 s) (#13549) (performance)
  • perf(daemon): startup readiness waits on serial simctl discovery (~90% of in-process startup; linear in booted simulators) (#13548) (performance, daemon)
  • perf(daemon): idle daemon re-runs full simctl/adb discovery every 10 s (3 subprocess spawns, ~3% of a core) (#13547) (performance, daemon)
  • perf(observe): a cached observation re-collects elements and deep-compares them on every skeleton projection (+30-70% sanitize cost) (#13545) (performance)
  • perf(observe): structuredContent keeps the extras that the text part strips (full observe sends 3.5x the bytes) (#13544) (performance)
  • perf(observe): observe cache put is on the response path, writes 800 KB pretty-printed JSON per observation and stats every cache file (#13543) (performance)
  • perf(observe): skeleton projection recomputes toSearchable and re-filters IME keys per duplicate group (3-10x the cost of the full projection) (#13542) (performance)
  • tapAt (ios): explicit snapshotId taken before a pinch/screen change is not rejected as stale (#13476) (needs-device-verify)
  • Review findings: design-doc and env-var doc inaccuracies (#13320)
  • Review findings: lint and ratchet guard bypasses (#13317)
  • Review findings: test fakes and contracts that diverge from production or cannot fail (#13316)
  • Review findings: late bind() after socket teardown forget() recreates a dead session-key binding (#13053) (#13296)
  • chore(dead-code): prune unused exports in daemon core files (follow-up to #11854) (#13227)
  • Review findings on #13148 and #13150: old runner APKs still advertise prototype_display_id_v1; pre-31 sendKeys chunks lose committed progress (#13164)
  • MCP Tasks server: settle/input persistence failures, key reuse, protocol negotiation, lease keepalive incarnation (review findings on #13119, #13128) (#13143)
  • test: prototypeToolGestures 'ios refuses gestures before show or asset upload' fails when test/server runs as one directory (#13130)
  • prototype textField: Android trailing IconButton stays enabled when the field is disabled; iOS number/decimal/phone pads expose no submit control (#12998)
  • test(prototype-ux): record Linux screenshot baselines for flow/grid and the drifted materialSliderChipCard case, then drop pending (#12416)
  • Android API 36+: obtain the physical panel id on foldables without the blocked Display.getUniqueId() reflection (#12233)
  • test(contracts): extend fake-vs-real behavioural contracts beyond 9 of 185 fakes (#11868) (testing)
  • ci: 100ms unit-test budget is the top PR failure — fix recurring over-budget tests (#11574) (flaky test, ci, testing)
  • prototype: iOS/Android asymmetries the host does not report (identifier fallback to id, bottomSheet swipe, icon coverage, iconVariant) (#11552)
  • testing: four lifecycle mutants survive every test (h2, o2, r1, K1); delete the redundant guards k, k3, j2 (#11442) (testing, desktop, daemon)
  • test(prototype-ux): device acceptance in the Playground and a manual-test recipe (#9309) (android, testing)

CtrlProxy APK

SHA256 Checksum: de6b78a022dcb62ff862b137076ac7202866a9896bda6d04be20dd7ab1ae377d

Download the APK from the release assets below.

CtrlProxy iOS IPA

SHA256 Checksum: 4fddc878276c9ea0a86008ea45422a41c31885cec70d5060b1ad573d45e8b893

Download the IPA from the release assets below.

video-server jar

SHA256 Checksum: 092ad380e2cc80e763f1d91944113a79e343d8514178439bb2016bf52d9b5e92

Download automobile-video.jar from the release assets below.

macOS screen-capture-helper

SHA256 Checksum: bb0696c32e2ef61ebfede73a844817660e6a5aebbc8258dcc03e487afa294fb4

Download screen-capture-helper-macos-universal.zip from the release assets below.

iOS simulator prototype agent

SHA256 Checksum: cc644a6dc81fd4aab561e2b7e8c1ba80a320a5b68da1729b650e750fd1b726e2

Download AutoMobilePrototypeAgent.dylib (universal arm64 + x86_64, ad-hoc signed) from the release assets below.

iOS simulator prototype viewer

SHA256 Checksum: 3fdabb1600c84db71ec8dbd089d8e741c1260bbf7631c48b5505b017713c7d22

Download AutoMobilePrototypeViewer.zip (universal arm64 + x86_64, ad-hoc signed) from the release assets below.

macOS network-filter

SHA256 Checksum: ab1455dc7d737d4fc003ffaf11b5d2033c8b70f8648e059d7beef6164ce76336

Download automobile-network-filter-macos-universal.zip from the release assets below.

Desktop App

Native installers are attached below: macOS .dmg (signed & notarized), Windows .msi, and Linux .deb.