Highlights
This release makes session cleanup safer, replay failures easier to understand, and the SDK more useful for integrations.
- No more leaked device claims after failed script saves — closing a session now releases the device and removes the session even when close-time
.adpersistence fails. - Clearer, safer Maestro failures — resolved target labels and
runFlowpaths appear in diagnostics, sensitiveinputTextremains redacted, and malformed environment entries return typedINVALID_ARGSerrors. - Public Limrun runtime — cloud and provider integrations can now import
LimrunRuntimefromagent-device/limrunwithout depending directly on@limrun/api. - Fail-closed CLI parsing — extra positional arguments are rejected instead of silently ignored, preventing malformed agent plans such as
open app url closefrom partially executing. - Runnable Node.js SDK examples — new examples cover client sessions, batch orchestration, Metro runtime resolution, contracts, and typed error handling.
- More stable replay progress output — terminal output remains intact when the viewport resizes or reflow ends.
- Stronger release confidence — expanded iOS simulator smoke coverage, replay-compat and mutation gates, property-based testing, concurrency checks, and narrowly controlled timeout-only CI retries.
Compatibility note
Commands with excess positional arguments now fail with INVALID_ARGS. Any scripts relying on previously ignored trailing arguments must use the command’s documented syntax.
What's Changed
- fix(android): stamp status-bar chrome during the walk instead of reconstructing it downstream (#1319) by @thymikee in #1359
- fix(apple): parse parenthesized xctrace physical device format by @devin-ai-integration[bot] in #1360
- Generalize subprocess stub tests to support multiple platforms by @thymikee in #1362
- chore: remove dead code and tune fallow's dead-code rules by @thymikee in #1363
- chore: remove dead type re-exports, prune stale suppressions, gate unused-types by @thymikee in #1364
- chore: remove verified dead code and migration scaffolding (~700 LOC) by @thymikee in #1367
- test: serialize client-metro and harden the unit suite against ambient daemon env by @thymikee in #1365
- chore(deps): resolve dependabot alerts by @thymikee in #1372
- refactor(cli): decompose runCli into explicit phase functions by @thymikee in #1373
- refactor(interaction): resolve the CapturedSnapshot name collision by @thymikee in #1371
- refactor(commands): derive pass-through command bindings with a generic BoundOf helper by @thymikee in #1368
- fix: select iOS simulator by installed app by @thymikee in #1376
- fix(android): preserve fixed siblings after snapshot filtering by @thymikee in #1378
- feat(events): enrich session event details by @szdziedzic in #1379
- fix: report bundle sizes with two decimal MB precision by @thymikee in #1382
- fix(interaction): direction-named, selector-first off-screen recovery hints (#1366) by @thymikee in #1374
- fix(daemon): explicit abort message on uncommitted repair close by @jibin7jose in #1383
- feat(replay): recorded landmark identity for wait, is coverage — read-only step identity (#1349) by @thymikee in #1381
- fix(daemon): keep an active replay session's daemon alive over the CLI path by @thymikee in #1390
- feat: parameterize sensitive recorded inputs by @thymikee in #1369
- feat: add WebView accessibility lab by @thymikee in #1397
- fix(cli): compact stale device status by @thymikee in #1388
- docs: restructure AGENTS.md and CONTEXT.md for progressive disclosure by @thymikee in #1402
- fix(replay): preserve cwd scope for opened sessions by @Bortlesboat in #1401
- feat: add first-class Vega VVD TV support by @thymikee in #1396
- docs(adr): rules-first ADR restructure + ADR 0017 proposal (unified event journal) by @thymikee in #1399
- feat(apple): injectable Apple runner transport seam for provider interactors by @thymikee in #1389
- fix(gestures): fail pre-removal gesture forms at .ad parse time (#1216) by @thymikee in #1393
- refactor(boundaries): put shared contracts below their consumers, gate the result by @thymikee in #1405
- feat: strengthen agent help benchmarks by @thymikee in #1404
- fix: select app-bearing simulator for replay by @thymikee in #1387
- fix: support xctrace-only iOS physical devices by @thymikee in #1375
- fix(replay): bounded retry on pre-dispatch capture racing app launch (#1385) by @thymikee in #1386
- feat(scripts): dependency-graph report over the layering gate's model by @thymikee in #1410
- feat(bench): renderer-pinned samples, topic-coverage gate, error-recovery quizzes; trim skillgym to agentic checks by @thymikee in #1411
- docs: architecture principles mapped to enforcing gates and open ledgers by @thymikee in #1428
- docs: bless the works-today iOS SpringBoard/widget workflow (#1296 PR A) by @thymikee in #1395
- fix: update vulnerable dependencies by @thymikee in #1434
- fix(daemon): keep close-time script-save failures from leaking the session/device claim by @thymikee in #1392
- test: property-based testing foundation (fast-check) over parse/print and geometry kernels by @devin-ai-integration[bot] in #1437
- refactor(contracts): declare shared vocabulary below its consumers, ratchet what remains by @thymikee in #1435
- fix(cli): reject excess positionals by @Bortlesboat in #1433
- test: frozen replay-compat corpus with expected verdicts (#1417) by @devin-ai-integration[bot] in #1436
- test: ratchet mutation score over enumerated decision kernels by @devin-ai-integration[bot] in #1441
- test(daemon): seeded concurrency torture lane for session/lease/lock invariants by @devin-ai-integration[bot] in #1439
- test: nightly parser fuzz lane — parser input fails as typed AppErrors, never hangs (#1414) by @devin-ai-integration[bot] in #1438
- fix(ci): upload hidden diagnostics by @thymikee in #1443
- test: gate public command surface against commands.md reference by @devin-ai-integration[bot] in #1446
- chore(deps): Renovate config, packageManager-derived pnpm in CI, repo-wide format by @devin-ai-integration[bot] in #1444
- test(ci): gate PRs on changed-line coverage (#1418) by @devin-ai-integration[bot] in #1447
- test: enumerate error-code recovery quizzes in a unit-lane gate by @devin-ai-integration[bot] in #1445
- test: smoke every package.json export subpath from the packed package by @thymikee in #1452
- fix(replay): resolve Maestro failures and resize progress by @thymikee in #1450
- test(replay): split session-replay-vars.test.ts by actual subject (#1460) by @thymikee in #1468
- refactor(daemon): table-ify handleSessionCommands by @thymikee in #1467
- build(android): unify the 4 helper build/package scripts behind one parameterized pair by @thymikee in #1466
- refactor(layering): declare R1-R3 as a policy table, and test them by @thymikee in #1449
- feat(scripts): blast-radius query — dependents, owning gates, live-coverage owners (#1425) by @devin-ai-integration[bot] in #1470
- test(apple): split the 3,487-line core index.test.ts along its import boundaries by @thymikee in #1472
- feat: expose Limrun runtime by @thymikee in #1476
- test(kernel): cover all six errors.ts exports, kernel-errors mutation 55.19% → 86.26% by @thymikee in #1475
- obs: repo-health snapshot command aggregating existing analyzers into one JSON by @devin-ai-integration[bot] in #1471
- test(ios): expand simulator e2e coverage by @thymikee in #1408
- ci: fold single-grep jobs into steps, call named pnpm scripts by @thymikee in #1465
- feat(examples): add runnable Node.js SDK examples under examples/sdk/ by @thymikee in #1469
- ci(android): trust cached fixture APKs by @thymikee in #1479
- Remove SkillGym suite and repo-health snapshot infrastructure by @thymikee in #1480
- docs: propose daemon module boundaries by @thymikee in #1451
- test(ci): single-retry policy for enumerated contention-flaky files (timeouts only) by @devin-ai-integration[bot] in #1448
New Contributors
- @jibin7jose made their first contribution in #1383
- @Bortlesboat made their first contribution in #1401
Full Changelog: v0.20.0...v0.20.2