Repository navigation
What's Changed
- feat(http): expose the control plane over HTTP by @V3RON in #68
- feat: on-demand component installation for iOS runtimes and Android system images by @V3RON in #69
- feat(ios): opt-in slim simulators (closes #87) by @V3RON in #89
- fix(daemon): let the daemon exit while a detached lease is outstanding by @V3RON in #90
- docs(adr): 0003 — one typed daemon contract behind every frontend by @V3RON in #92
- feat(contract): declare every daemon operation once, negotiate protocol ranges by @V3RON in #93
- feat(daemon): one dispatcher for every transport, roles, ownership, admin credential by @V3RON in #94
- feat(client): a typed, single-connection daemon client by @V3RON in #95
- feat(cli): render the contract; move token operations into the daemon by @V3RON in #96
- feat(mcp): derive tool schemas from the contract, delete the session cache by @V3RON in #97
- fix(contract): a lease grant returns a device projection, not the whole record by @V3RON in #98
- docs: document the contract, the client, the security model, and 0.3.0's breaks by @V3RON in #99
- fix(client): make abort actually cancel, and keep the mismatch escape hatch alive by @V3RON in #100
- fix(daemon,http): one error table for both transports; fail a bind failure loudly by @V3RON in #102
- fix(mcp,contract): scope lease_status to this session; restore the §1 boundary test by @V3RON in #103
- fix(client): stop swallowing a second crash on the same lease by @V3RON in #104
- fix(contract,daemon): narrow status.get, close the stop-during-start window by @V3RON in #105
- fix(http,mcp,docs): one answer per operation across transports by @V3RON in #106
- test(cli): restore coverage deleted under a false justification by @V3RON in #107
- fix(daemon): reject instead of hanging when the socket claim loses the race by @V3RON in #108
- feat(devices): Simlock-owned device roots for iOS and Android by @V3RON in #111
- fix: resolve hardware verification findings B2, D1, D2, D3 by @V3RON in #113
- docs(adr): 0004 TTL-first leases, 0005 gateway and worker modes by @V3RON in #121
- docs: describe TTL-first leases end state, accept ADR 0004 (PR C) by @V3RON in #122
- chore: ignore agent worktrees under .claude/worktrees/ by @V3RON in #133
- docs: describe gateway and worker modes end state, accept ADR 0005 (#120) by @V3RON in #127
- feat(cli,mcp)!: clients renew their own leases (ADR 0004, PR A) by @V3RON in #124
- feat!(daemon,contract): one TTL-first lease on every transport (ADR 0004, PR B) by @V3RON in #125
- feat(contract,daemon,http,cli): device.exec runs simctl/adb on the worker and streams output (ADR 0005, #116) by @V3RON in #128
- feat(gateway,ports,http,cli): gateway skeleton — config.mode, uplink, worker views, worker.* (ADR 0005, #117) by @V3RON in #129
- feat(gateway,core,contract,daemon): fleet queue, routing, and lease + exec forwarding (ADR 0005, #118) by @V3RON in #130
- test(gateway,e2e): prove drain, WORKER_UNREACHABLE and reconnect rebuild end to end (ADR 0005, #119) by @V3RON in #131
- test(e2e): prove the gateway happy path over the CLI and HTTP (ADR 0005) by @V3RON in #132
- fix(lefthook): exclude docs/** from the format pre-commit job by @V3RON in #135
- docs: split end-user docs from maintainer/agent docs by @V3RON in #134
- docs(delivery): GitHub Issues as spec and queue — kind:state labels, issue forms, spec templates by @V3RON in #136
- chore(skills): spec-session, triage-bug, and deliver skills for the delivery rule by @V3RON in #137
- ci(issues): enforce the delivery label rules with one issue-state workflow by @V3RON in #138
- docs(delivery),chore(skills): plain-language rule and triage fixes from the first live triage by @V3RON in #140
- docs(delivery),chore(skills),ci(issues): blocked state, task demotion, request close, claim release by @V3RON in #142
- fix(ios): write the download-lock separator as \0 instead of a raw NUL byte by @V3RON in #143
- feat(core): create a new device identity for each lease under lease.identity fresh by @V3RON in #145
- docs(delivery),chore(skills): two blind reviews before every PR — rule 14 and the review skill by @V3RON in #146
- feat(cli,mcp): take the requester id from the agent session by @V3RON in #165
- fix(ios): report downloaded runtimes whose disk nothing can reclaim by @V3RON in #144
- feat(config,android): configure emulator launch options from the config file (#148) by @V3RON in #149
- docs(adr): 0006 — events and the daemon log are two records; docs follow the implementing PR by @V3RON in #175
- test(e2e): stop gateway and restart tests from sitting out 30s waits by @V3RON in #176
- docs(adr): 0007 — a lease request chooses the device mode by @V3RON in #182
- docs(adr): 0008 — the catalog pairs models with runtimes, and status carries host facts by @V3RON in #183
- feat(core,http): store lease requests and replay them by idempotency key by @V3RON in #185
- feat(bus,cli,config): keep business events on disk so the history survives a restart by @V3RON in #184
- feat(daemon,cli): daemon log records every request and background failure; daemon logs --follow by @V3RON in #187
- docs(adr): 0009 — gateway routing is a list of stages, and a request that cannot be served fails at once by @V3RON in #196
- refactor(gateway): routing is an ordered list of stages by @V3RON in #197
- feat(catalog,gateway,cli): the catalog pairs each model with its installed runtimes by @V3RON in #198
- feat(contract,core,http,cli): report the device mode as mode on every surface by @V3RON in #199
- test(e2e): read the nested lease grant in the slow lanes by @V3RON in #200
- feat(gateway): a worker that answers NO_CAPACITY is asked once per change of its state by @V3RON in #201
- feat(daemon,gateway,cli): status and the worker list report host facts by @V3RON in #203
- feat(catalog,gateway,cli): the catalog lists every accepted Android name and every installed image by @V3RON in #202
- feat(contract,core,ios,cli,http,gateway): a lease request chooses slim or full; ios.defaultMode sets the default by @V3RON in #204
- feat(gateway): a worker is sent only requests its catalog says it can serve by @V3RON in #207
- docs(adr): 0010 — components are installed, recorded and removed through one owner in the core by @V3RON in #222
- feat(core,contract,daemon,gateway,cli): count each device against the RAM budget by its mode, and report the budget in status by @V3RON in #223
- test(e2e): the slim lane reaches Simlock's device set, and the suite keeps one test per claim by @V3RON in #205
- fix(ios,docs): stop saying iOS runtimes cannot be downloaded by @V3RON in #224
- feat(core,ios,android,daemon): lease-triggered downloads go through one installer in the core by @V3RON in #225
- feat(core,contract,daemon,gateway,cli): status lists the installs in progress by @V3RON in #227
- feat(contract,daemon,http,cli,client): simlock component install installs a component from the CLI, the client and HTTP by @V3RON in #228
- feat(core,ios,android,contract,daemon,cli,client,http): simlock component list shows every installed component, its size, and who installed it by @V3RON in #229
- feat(android,contract,gateway,cli): mark custom Android models in the catalog, and document where models come from by @V3RON in #230
- feat(core,drivers,daemon,cli,contract): doctor names each missing prerequisite and how to install it by @V3RON in #231
- feat(contract,gateway,daemon,http,cli,client): simlock component install installs on a gateway's workers by @V3RON in #232
- feat(core,contract,http,mcp): a lease request reports the downloading stage while it waits on a download by @V3RON in #233
- feat(core,ios,android,contract,daemon,cli,client,http,gateway): simlock component remove removes a component Simlock installed by @V3RON in #234
- feat(core,contract,drivers,gateway,cli,http,mcp): a lease request names the Android image tag by @V3RON in #235
- docs(cli): a gateway routes a request that uses a model's other name by @V3RON in #244
- fix(drivers): a devices.xml that cannot be checked is unreadable, not a catalog failure by @V3RON in #245
- fix(core): one driver's failing catalog no longer fails catalog.get for every platform by @V3RON in #246
- fix(core): wake the lease queue after every handoff grant by @V3RON in #247
- feat(ios,core,docs): component remove removes an iOS runtime whose only other simulators were never used by @V3RON in #249
- fix(android): cancel the shutdown wait's timer so a stopped daemon exits by @V3RON in #250
- fix(android): list a devices.xml profile avdmanager also prints in customModels by @V3RON in #248
- fix(ports,drivers): read an installer's progress at each carriage return by @V3RON in #251
- fix(android): read devices.xml RAM from <d:ram unit>, the shape Android Studio writes by @V3RON in #262
- fix(drivers): read an installer's percentage written with a decimal comma by @V3RON in #265
- fix(core): a removal of a recorded version that is no longer installed says none is installed by @V3RON in #267
- fix(ios): wait while simctl lists a removed runtime as deleting before verifying the removal by @V3RON in #268
- docs(adr): 0010 is Accepted by @V3RON in #281
- fix(core,daemon): redact gateway.token in the start log line and daemon.started by @V3RON in #279
- fix(docs): move loop.md to docs/internal/ and drop HTTP-API.md's internal-doc pointer by @V3RON in #278
- fix(android): refuse to ready a device another emulator answers for by @V3RON in #282
- fix(android): skip a console port another instance's emulator is listening on by @V3RON in #269
- test(android): the two-instance fake answers emu avd path by @V3RON in #287
- fix(cli): write config.json owner-only from config set by @V3RON in #266
- fix(android): reserve a console port per daemon process, not per device by @V3RON in #283
- fix(http,gateway): serve GET /v1/leases/{id} on a gateway and name the worker on its leases by @V3RON in #285
- fix(ios,core,daemon): state the leftover download's measured size, round progress fractions, and end a successful install at 100% by @V3RON in #290
- docs(adr): 0011–0013 — the web console by @V3RON in #277
- feat(contract,daemon,http,docs): a worker answers the fleet operations as a fleet of one by @V3RON in #288
- feat(ui,http,cli,docs): the daemon serves a web console at / with operator sign-in by @V3RON in #289
- feat(ui,docs): live data and the workers views in the console by @V3RON in #291
- feat(console,cli,http): waiting requests view and simlock list --requests by @V3RON in #296
- feat(ui,core,daemon,cli): attention view and stalled devices by @V3RON in #295
- feat(ui,http,docs): leases view, lease details and holder labels in the console by @V3RON in #293
- feat(ui,docs): the events view in the console by @V3RON in #294
- feat(ui): the Apex look in the console by @V3RON in #298
- feat(ui,docs,e2e): page every console table and draw only the events in view by @V3RON in #300
- test: close audit gaps — cleanup --rule, per-boot address, one admission check, boundary scans, timeout tests by @V3RON in #303
- refactor: delete production code only tests kept alive (audit step 2) by @V3RON in #304
- refactor(gateway): retire the legacy routing policy only tests ran (audit step 3) by @V3RON in #306
- test: delete tests a stronger keeper already proves (audit step 4) by @V3RON in #308
- fix(core): a daemon that loses the identity race reads the winner's id, not an empty file by @V3RON in #302
- chore(agents): unattended delivery — orchestrator, forked stages, merge gate, mutation testing by @V3RON in #301
- chore(agents): weekly delivery stats, tests-after-red for the spec review, releases from a workflow by @V3RON in #313
- feat(gateway): a request no worker can serve fails at once by @V3RON in #310
- feat(bus): every event carries an id that survives a restart by @V3RON in #322
- feat(gateway): retry a worker's cannot-serve refusal on another worker by @V3RON in #315
- feat(bus): a relayed event keeps the worker's id and timestamp by @V3RON in #323
- feat(gateway): the pick accounts for health, the worker's queue, and its RAM budget by @V3RON in #321
- docs(adr): 0014 — an event has one id, minted where the fact happened by @V3RON in #311
- docs(adr): 0015 — a lease request is a set of constraints, and the catalog says which class each model is by @V3RON in #330
- chore(agents): severity-gated reviews, review inputs script, spec check before ready, assumptions by @V3RON in #331
- chore(agents): pin model and effort for every delivery stage, reviewers as agent definitions by @V3RON in #338
- chore(agents): delivery stats read GitHub through repo-scoped endpoints only by @V3RON in #339
- feat(catalog): the catalog names each model's class by @V3RON in #340
- feat(catalog): the catalog shows the default model per class (#333) by @V3RON in #342
- docs(adr): 0016 — usage figures are derived on read from the event history by @V3RON in #344
- feat(lease): a request names a class or nothing, and is served by a fitting idle device first by @V3RON in #343
- feat(events): events carry the grant facts; capacity and queue depth become events by @V3RON in #351
- feat(events): the event log keeps a window of time, bounded by size by @V3RON in #353
- feat(lease): --os accepts a version range by @V3RON in #352
- chore(agents): faster delivery runs and specs a person can follow by @V3RON in #355
- feat(gateway): warm hits respect the request's mode and the runtime the worker would pick by @V3RON in #325
- feat(gateway): a class or range request is served by a worker that fits by @V3RON in #357
- docs(adr): 0017 — the warm pool is a module beside the lease transaction, not a step in it by @V3RON in #361
- docs(adr): 0017 is accepted, not yet implemented by @V3RON in #367
- docs(adr): 0018–0019 — leasing is one module, and startup ends every lease whose device is not running by @V3RON in #360
- chore(agents): run delivery stages as background custom agents by @V3RON in #376
- chore(agents): implementer audits its diff before reporting by @V3RON in #377
- chore(agents): session titles and status lines show delivery progress by @V3RON in #378
- feat(lint): imports past a module's index into core or gateway fail lint by @V3RON in #374
- chore(agents): agents run only the tests their change reaches; hooks run the other checks by @V3RON in #379
- chore(test): run fast e2e files four at a time by @V3RON in #380
- chore(agents): a session stops itself when it passes a token or time budget by @V3RON in #384
- chore(agents): implementer never runs hook checks by hand, never waits on CI, never stashes by @V3RON in #385
- refactor(core): reclaim is its own coordinator and commits what the driver returns by @V3RON in #375
- feat(core): the warm pool module: one budget, a keep rule that fits, and an off switch by @V3RON in #386
- chore(agents): agents and skills take every command from toolchain.md, and say it in fewer words by @V3RON in #390
- chore(agents): review converges: a claims review, two code-review lenses, later rounds review only the fix by @V3RON in #391
- chore(agents): the spec check plans, runs a pre-mortem and gives every category a status by @V3RON in #392
- refactor(leasing): leasing is its own module, entered through src/leasing/index.ts by @V3RON in #383
- fix(leasing): a grant and its request's result are one write by @V3RON in #397
- feat(core): a reserve of running slots, and a request waits for a device on its way by @V3RON in #394
- feat(contract): status answers only health and host while the daemon is starting by @V3RON in #398
- feat(core): warm targets boot or create devices ahead of demand by @V3RON in #408
- feat(leasing): startup ends every lease whose device is not running by @V3RON in #409
- chore(ci): the console lane runs on a PR only when it changes what the lane exercises, in Chromium only by @V3RON in #413
- chore(agents): review rounds run while they converge, every stage is a new agent, and a spec fix is checked closed by @V3RON in #415
- chore(agents): the gate re-runs CI once for a missing runner or a known flaky test, and the budget guard counts only active time by @V3RON in #416
- feat(core): the warm pool in status, doctor, one event and the console by @V3RON in #411
- docs(adr): a requester may choose its lease id (ADR 0020) by @V3RON in #418
- fix(leasing): wake the queue after a failed boot whose destroy also fails by @V3RON in #426
- fix(daemon): dial the gateway uplink from onSocketClaimed by @V3RON in #427
- feat(leasing): let requesters choose the lease ID by @V3RON in #423
- fix(gateway): a worker that was starting when first read gets its full view once its startup ends by @V3RON in #421
- fix(leasing): free the waiter's running slot when a failed boot's device is claimed before the destroy by @V3RON in #425
- docs(adr): a gateway dispatch is a probe, and the gateway records every fleet request's outcome (ADR 0021) by @V3RON in #432
- feat(leasing): a gateway dispatch is a probe; workers record lease.declined, the gateway records every fleet outcome by @V3RON in #433
- test(e2e): slow lane: a target boots a real simulator and emulator, and off shuts both down by @V3RON in #419
- docs(adr): a physical device is a second device type the core knows (ADR 0022) by @V3RON in #435
- docs(adr): ADR 0022 amendments from the #428 spec check by @V3RON in #443
- chore(agents): comments say why or go; a Haiku comment review; incremental mutation testing by @V3RON in #446
- chore(agents): implementer in phases, restricted tools, raw hand-offs, coding.md by @V3RON in #447
- feat(core): core knows physical devices: the device union, its state machine, and virtual-only paths leave them alone by @V3RON in #444
- chore(agents): CI failures reach fix runs; audit runs the comment review; fewer pushes; Stryker failures say why by @V3RON in #452
- feat(enrollment): simlock device add / remove enroll and unenroll physical devices by @V3RON in #449
- fix(core): doctor and the lease health monitor make their registry writes in the decision section by @V3RON in #454
- test(daemon): wait for leasing's held startup write, not 25 ms of real time by @V3RON in #453
- fix(daemon): a frame for a peer that hung up is dropped, not an unhandled rejection that kills the daemon by @V3RON in #457
- fix(e2e): withDaemon waits for admin.token before handing the daemon over by @V3RON in #455
- feat(leasing): lease --physical grants, queues and reclaims enrolled physical devices by @V3RON in #456
- chore(agents): faster delivery: no Stryker on push, foreground helpers, report and budget guards, reviews sized to the diff by @V3RON in #459
- chore(agents): comment lint, two review rounds, briefs, agent caps and delivery measurement by @V3RON in #460
- feat(leasing): physical devices that go missing become absent, end their lease device-lost, and come back reclaimed by @V3RON in #458
- feat(ios): iOS physical devices through devicectl by @V3RON in #461
- feat(android): physical Android devices through the host's default adb server by @V3RON in #462
- feat(gateway): remote agents lease and reach physical devices on workers by @V3RON in #463
- docs(adr): agent-device edge module and lease-end port (ADRs 0023, 0024) by @V3RON in #467
- feat(leasing): an agent id may hold more than one lease, up to lease.maxPerRequester by @V3RON in #468
- docs(adr): ADR 0023 amendments from the #466 spec check by @V3RON in #478
- docs(events): list lease-engine among device.deleted initiators by @V3RON in #479
- docs(console): show simlock status's real output by @V3RON in #480
- fix(events): list cleanup-reaper and nuke as device.deleted initiators by @V3RON in #482
- docs(adr): 0025 — Simlock ships Android device profiles, and a model pairs only with images that fit it by @V3RON in #486
- docs(adr): 0025 amendments from the #485 spec check by @V3RON in #492
- test(e2e): commit prebuilt Appduct playground apps as fixtures by @V3RON in #493
- feat(leasing): call lease-end participants before reclaiming a device by @V3RON in #494
- feat(agent-device): simlock runs the agent-device daemon by @V3RON in #495
- feat(doctor): simlock doctor says why agent-device is not available by @V3RON in #496
- feat(agent-device): an agent opens and closes a device through simlock by @V3RON in #497
- chore(reviews): calibration brief for the four weeks to 2026-10-13 by @V3RON in #498
- feat(agent-device): heartbeats keep the simlock lease alive by @V3RON in #499
- chore(fallow): remove four stale suppressions and fail on stale ones by @V3RON in #500
- test(e2e): spend less time waiting by @V3RON in #504
- test(e2e): a failed warm-pool boot is held back, checked in 2 s instead of a 60 s wait by @V3RON in #503
- ci: split Quality into parallel static, unit and sharded e2e jobs by @V3RON in #501
- chore(agents): one worktree per task, hook guards, decide-and-tell, stacked feature PRs by @V3RON in #505
- chore(agents): the weekday routines finish in a cloud session by @V3RON in #502
- test(ports): process runner waits are constructor options by @V3RON in #382
- feat(agent-device): simlock ending a simlock lease ends the agent-device session first by @V3RON in #506
- feat(agent-device): the front refuses requests that reach past the agent's device by @V3RON in #507
- test(e2e): agent-device through a simlock worker on real devices by @V3RON in #509
- feat(android): Simlock ships its own Pixel 9 Android profile, read before the SDK by @V3RON in #521
- feat(android): the other 15 library profiles, and Medium Tablet as Android's tablet by @V3RON in #523
- feat(android): an Android lease only uses a system image that fits its model by @V3RON in #526
- feat(android): a devices.xml profile's API range, Play Store and screen size decide its images by @V3RON in #530
- feat(android): doctor reports a devices.xml profile hidden by a library profile by @V3RON in #535
- chore(comments): delete comments that say what, not why, since b2c5b2e by @V3RON in #541
- chore(reviews): calibration brief for the four weeks to 2026-10-14 by @V3RON in #540
- docs(adr): 0026 agent-device through a gateway by @V3RON in #512
- feat(fleet): workers advertise their capabilities in status and worker list by @V3RON in #520
- feat(fleet): a lease request may require a capability by @V3RON in #524
- feat(gateway): relay one HTTP exchange to a module on a worker by @V3RON in #528
- feat(agent-device): open, commands, heartbeats and close through a gateway by @V3RON in #536
- feat(agent-device): devices, uploads, artifacts and diagnostics through a gateway by @V3RON in #537
- feat(agent-device): an unreachable worker answers try again, and a gateway restart keeps the agent's device by @V3RON in #539
- test(e2e): agent-device through a gateway on real devices by @V3RON in #538
- chore(agents): specs cite their facts, and a split ends with tasks ready by @V3RON in #548
- chore(agents): the hardware loop, a slow lane that reports and cleans up, and no dialogs in delivery by @V3RON in #549
- chore(agents): audits probe every test, reviews stop overlapping, searches go to Haiku by @V3RON in #550
- chore(agents): modules hand out capabilities, extension points share one shape, and dependency-cruiser guards every component (ADR 0027) by @V3RON in #555
- fix(cli): daemon start reports the config error instead of a socket timeout by @V3RON in #543
- fix(e2e): a daemon on a free port picks another when the port is taken before it binds by @V3RON in #560
- chore: typechecks reuse a local tsbuildinfo cache between runs by @V3RON in #572
- docs(adr): 0028 the uplink carries byte channels and small messages go first by @V3RON in #554
- feat(agent-device): a download over 2 GB fails, never cut short by @V3RON in #561
- feat(link): the uplink carries byte channels beside its messages, and small messages go first by @V3RON in #562
- feat(gateway): relayed bodies travel on byte channels by @V3RON in #570
- test(e2e): transfers through a gateway keep their promises by @V3RON in #571
- docs(adr): 0027 host load is an optional module whose readings ride on status by @V3RON in #529
- feat(host-load): a worker's simlock status shows its CPU, memory and disk load by @V3RON in #563
- feat(host-load): Linux load is measured against a cgroup v2 limit by @V3RON in #565
- feat(gateway): a gateway carries each worker's load in its view and reports its own by @V3RON in #567
- feat(ui): the console shows each worker's load on its card and detail page by @V3RON in #568
- docs(readme): add the global install step to Getting started by @alcpereira in #167
- chore(comments): delete comments that say what, not why, since b2f9a95 by @V3RON in #578
- refactor(link): the link needs no Node, so it can move to a browser or its own package by @V3RON in #579
- docs(adr): record which accepted ADRs the code now implements by @V3RON in #589
- fix(daemon): the daemon reports the version in package.json by @V3RON in #588
- chore(docs): every module has a manual beside its code by @V3RON in #581
- chore(docs): ARCHITECTURE.md becomes the map by @V3RON in #582
- chore(docs): known gaps move into the manuals; COMPONENTS, KNOWN-PITFALLS, LOOP and drafts go by @V3RON in #583
- chore(testing): fewer, stronger tests — new testing rules, a leasing pilot, and a weekly audit-tests routine by @V3RON in #604
- chore(agent-device): require agent-device 0.21.28 and take its proxy from npm by @V3RON in #603
- fix(agent-device): release the simlock lease when a command reports endedLeases by @V3RON in #608
- docs(adr): 0030 optional modules share one contract and load only when turned on by @V3RON in #592
- feat(doctor): one module-unavailable finding for every optional module by @V3RON in #599
- feat(modules): optional modules load through one host and are turned on under capabilities by @V3RON in #601
- feat(agent-device): agent-device runs as an optional module on workers by @V3RON in #605
- feat(agent-device): the gateway side runs as an optional module by @V3RON in #606
- feat(stream): a leased simulator's or emulator's screen, streamed to whoever is looking at it by @V3RON in #576
- feat(ui): the console draws each worker's load as gauges on its detail page by @V3RON in #575
- feat(ui): the load gauges colour over the console's own thresholds by @V3RON in #586
- chore(comments): delete comments that say what, not why, since df35f28 by @V3RON in #611
- feat(ui): console redesign — sidebar, overview, list and inspector pages, a design system by @V3RON in #610
- fix(agent-device): release the simlock lease when close is streamed without --json by @V3RON in #615
- fix: wait for the iOS app installer before readiness by @V3RON in #614
- fix(http): preserve concurrent token mutations by @V3RON in #616
- chore(agents): one spec session, explored first, tasks written from tables by @V3RON in #621
- fix(http,core): write tokens.json and state.json owner-only (#258) by @V3RON in #640
- fix(contract): retire helper import boundary exemptions by @V3RON in #627
- fix(gateway): refuse to republish a worker-pushed request.dispatched by @V3RON in #641
- fix(gateway): drop a worker's framing headers from a relay head by @V3RON in #643
- test(e2e): wait for reclaim before cleanup preview by @V3RON in #628
- fix(daemon): preserve replacement admin credential during restart by @V3RON in #625
- test: daemon status prints a human view, pinned at unit cost (#422) by @V3RON in #644
- fix(drivers/android): class a listed model by the profile its name resolves to by @V3RON in #646
- fix(leasing): a boot failure whose destroy also fails quarantines the device and frees the slot by @V3RON in #649
- fix(leasing): a ready grant marks its waiter in flight before the write (#402) by @V3RON in #650
- fix(console): show fleet lease and device figures as unknown while a worker is starting by @V3RON in #651
- fix(leasing): a handoff grant whose commit throws defers its waiter by @V3RON in #658
- chore(comments): delete comments that say what, not why, since e25f8de by @V3RON in #652
- fix(core): the warm pool skips devices of a platform whose driver was refused by @V3RON in #661
- fix(core): the cleanup reaper finishes its run when one action fails by @V3RON in #664
- fix(core): the operator reset finishes when one device has no driver by @V3RON in #668
- fix(console): the workers-list lane helpers drop a re-read refused by a stopping gateway (#642) by @V3RON in #667
- fix(leasing): the #armTimeout comment states what its markNew callers do by @V3RON in #670
- fix(leasing): no device work for a waiter the queue has just rejected (#665) by @V3RON in #669
- docs(agents): make exploration selective and evidence-bearing by @V3RON in #655
- feat(agents): make review incremental and risk-routed by @V3RON in #656
- chore(ci): bump actions/setup-node from 7.0.0 to 7.1.0 in the github-actions group by @dependabot[bot] in #638
- fix(core): attribute the recovered interrupted reclaim's device.shutdown to the reclaim coordinator by @V3RON in #679
- fix(cli): wait 20 s for a daemon a command auto-launched (#663) by @V3RON in #674
- fix(cli): the auto-launch startup timeout reports DAEMON_STARTUP_FAILED, not INTERNAL (#672) by @V3RON in #683
- fix(console): the overview's Activity lists the latest events, not the highest seq by @V3RON in #680
- docs(adr): 0031 a physical iPhone streams through CoreDevice's media stream, behind a screen-source seam by @V3RON in #622
- feat(drivers/android): stream a leased physical phone's screen behind a capture target by @V3RON in #662
- test(ios): stream a leased physical iPhone's screen by @V3RON in #645
- fix(gateway): a lone refusal after an aged-out window omits count (#677) by @V3RON in #682
- fix(e2e/console): a failed daemon start reports the daemon's own cause (#673) by @V3RON in #687
- fix(ports,core): write daemon.log, events.jsonl and instance.json owner-only (#685) by @V3RON in #689
- perf(cli): load a command's modules only when that command runs by @V3RON in #671
- Rank an installed Android image by the API level it records, so a preview is never the newest runtime by @V3RON in #681
- chore(agents): spec sessions approve once, source facts while asking, and recheck only the fix by @V3RON in #725
- chore(agents): one home for each procedure, short skill descriptions, AGENTS.md as a router by @V3RON in #726
- docs(internal): DELIVERY.md says what the maintainer does and sees, and links to where each step is defined by @V3RON in #728
- feat(history): history.db, usage projections, simlock stats, GET /v1/stats and console figures (#623) by @V3RON in #626
- docs(adr): 0033 a sign-in proxy is a second way to sign in, and auth is one module by @V3RON in #704
- refactor(auth): auth checks live in one module, src/auth by @V3RON in #732
- feat(identity): identity.get, GET /v1/identity and simlock whoami by @V3RON in #735
- feat(auth): sign in through a sign-in proxy's signed JWT by @V3RON in #736
- feat(http): refuse cross-site changing requests from a proxy sign-in by @V3RON in #737
- feat(console): sign in through the sign-in proxy and show who is signed in by @V3RON in #738
- test(real-proxy): run Simlock behind oauth2-proxy and Dex in CI by @V3RON in #740
- chore(agents): measured review and test strategy — mutation by tool, a self-filling ledger, fewer notes and tests by @V3RON in #739
- fix(agent-device): stop renewing commands answered unreachable by @V3RON in #723
- fix(cli): a daemon launched by daemon start that dies during that start reports DAEMON_STARTUP_FAILED by @V3RON in #710
- docs(daemon): drop manual rows for files moved to src/auth by @V3RON in #742
- fix(android): verify emulator identity before kill or snapshot load after a restart (#284) by @V3RON in #722
- docs(adr): 0035 a gateway sends chosen fleet events to webhook destinations by @V3RON in #718
- feat(alerts): a gateway sends chosen fleet events to generic webhook destinations by @V3RON in #741
- feat(alerts): a gateway sends fleet events to Slack by @V3RON in #744
- feat(alerts): simlock alerts test sends one sample to a destination by @V3RON in #746
- feat(website): a product website on GitHub Pages by @V3RON in #747
- fix(android): stop an orphan's running emulator before deleting its AVD by @V3RON in #751
- docs(adr): 0034 one worker per user, and the folder says what a daemon is by @V3RON in #702
- feat(daemon): the folder says what a daemon is, and --gateway reaches the gateway by @V3RON in #745
- feat(cli): commands find the daemon by folder, with a --gateway hint on a worker refusal by @V3RON in #749
- fix(android): prove running emulator root membership by @V3RON in #733
- fix(core): startup removes dead writers' temporary files by @V3RON in #752
- fix(agent-device): a lease the gateway's list omits is not ended (#750) by @V3RON in #753
- docs(adr): 0036 daemon state is a SQLite database, and each owner keeps its own tables by @V3RON in #755
- feat(state): the worker's registry lives in state.db by @V3RON in #775
- feat(drivers): iOS and Android device-data tables by @V3RON in #783
- feat(auth): tokens live in state.db on both daemon kinds by @V3RON in #784
- feat(cli): the CLI and MCP show why an auto-started daemon did not start by @V3RON in #785
- feat(gateway): the gateway's drained workers live in state.db by @V3RON in #786
- docs(adr): 0038 the warm pool learns its kinds from leases, and boots for every queued request by @V3RON in #772
- feat(warm-pool): the warm pool boots or creates one device per queued request by @V3RON in #788
- feat(warm-pool): a worker with no targets keeps the kinds it has leased ready by @V3RON in #792
- chore(agents): review replay harness, and the 2026-10-21 process review by @V3RON in #794
- chore(agents): the process review's small fixes and counters by @V3RON in #796
- chore(agents): stacks merge forward, the ADR PR is reviewed first, and CI failures are triaged before a fix run by @V3RON in #798
- chore(agents): round 1 reports every site of a defect class, safety candidates are probed, mechanical fix-checks spawn no lens, the audit proves coverage by @V3RON in #799
- chore(agents): AGENTS.md routes by role, the implementer carries its checklist, and briefs and the protocol ride in the prompt by @V3RON in #800
- chore(agents): the feature is checked before its tasks, tests are invoker scenarios from one Behaviours table, and tasks hold about ten by @V3RON in #801
- test(audit): 124 weak tests fixed, 33 fewer tests, since 56b5a49 by @V3RON in #795
- fix(warm-pool): protect devices serving queued requests by @V3RON in #804
- feat(website): the hero plays one machine, then a fleet of them by @V3RON in #763
- docs(website): end-user docs live only on the website, rewritten as guides and lookup tables by @V3RON in #816
- docs(adr): 0037 the console acts through the HTTP routes, on Base UI by @V3RON in #762
- feat(history): events.replay pages back with before and limit by @V3RON in #773
- feat(console): a new frame, and Leases in a drawer by @V3RON in #780
- feat(console): Fleet is a table, and each worker has a page with tabs by @V3RON in #787
- feat(console): Queue and Activity move to the shared frame, and Activity scrolls back through the history by @V3RON in #789
- feat(console): Overview home and Inbox by @V3RON in #793
- feat(console): release, cancel, drain, undrain and remove from the console by @V3RON in #803
- feat(console): search or jump to anything with ⌘K by @V3RON in #834
- test(audit): remove low-value tests across the suite, 140 fewer tests by @V3RON in #849
- docs(adr): joined workers refuse their own HTTP listener by @V3RON in #809
- feat(config): refuse HTTP on joined workers and migrate fixtures by @V3RON in #842
- feat(agent-device): --os and --image-tag reach lease.request by @V3RON in #840
- feat(warm-pool): status, doctor, console and docs show learned kinds with their origin by @V3RON in #844
- fix(startup): reject daemon sockets closed before hello by @V3RON in #805
- docs(adr): 0040 every HTTP route is declared once, and the OpenAPI document is built from the declarations by @V3RON in #815
- feat(contract): move to Zod 4 by @V3RON in #845
- feat(http): declare the System and Devices routes and build the OpenAPI document by @V3RON in #850
- feat(website): publish openapi.json and render the HTTP API reference by @V3RON in #855
- feat(http): declare the lease and lease-request routes by @V3RON in #854
- feat(http): declare the admin routes in the OpenAPI document by @V3RON in #857
- feat(http): the OpenAPI document lists the stream route by @V3RON in #858
- test(agent-device): drop download-cap.test.ts by @V3RON in #862
- docs(adr): 0041 the daemon can run under the user's service manager by @V3RON in #826
- feat(daemon): SIGTERM is a clean stop, and a start beside a running daemon exits 0 by @V3RON in #841
- feat(daemon): macOS service install, uninstall and supervised starts by @V3RON in #856
- feat(daemon): daemon status shows the service state, doctor reports a broken service by @V3RON in #859
- feat(ports): systemd user unit service manager on Linux by @V3RON in #861
- fix(ci): shard the console lane over four jobs by @V3RON in #868
- fix(ui): console e2e Activity:371 and Queue:163 by @V3RON in #869
- test(console): stop the Overview's route stubs before the fleet shuts down by @V3RON in #867
- ci: run console e2e only in Chromium by @V3RON in #880
- test: wait for Console semantic state by @V3RON in #882
- docs(adr): 0043 physical devices reach agent-device through a second daemon by @V3RON in #872
- feat(agent-device): a worker runs a phone daemon beside the simulator daemon by @V3RON in #876
- feat(agent-device): lease a physical phone through agent-device by @V3RON in #879
- test: make E2E resource cleanup await process exit by @V3RON in #884
- ci(release): plan, build on macOS, tag, publish through npm OIDC, release, deploy the site by @V3RON in #833
- test: remove wall-clock waits from usage stats by @V3RON in #883
- docs(adr): 0042 simlock updates itself through a frozen call and a detached updater by @V3RON in #827
- feat(updater): the updater, its npm port and launcher port, and the install check by @V3RON in #878
- feat(daemon): simlock update and POST /v1/update update one daemon after its leases end by @V3RON in #885
- feat(daemon): every daemon knows the latest Simlock version, simlock status says when a newer one exists by @V3RON in #887
- feat(gateway): update one worker from the gateway (#838) by @V3RON in #888
- feat(ui): update a worker from the console (#839) by @V3RON in #896
- fix(ios): stream a physical iPhone on CoreDevice 642 or later, not 642 only by @V3RON in #902
- chore(agents): the test rules ride in the briefs, and the audit proves the spec instead of extending it by @V3RON in #904
- fix(e2e): move the mouse off the menu so a new toast is not hovered (#900) by @V3RON in #903
- test(daemon): relay timing test keeps every transfer sending until its windows close (#688) by @V3RON in #901
- fix(gateway): a stale worker view no longer brings back a released lease (#898) by @V3RON in #899
- fix(agent-device): an allocate with every capable worker drained answers NO_CAPACITY by @V3RON in #935
- fix(e2e): the drain test answers the Fleet page without the host's load (#886) by @V3RON in #938
- docs(adr): 0044 the console reads what its page shows, and events mark it stale (#905) by @V3RON in #907
- feat(http): unchanged JSON answers under /v1 are 304 with an ETag by @V3RON in #920
- feat(gateway): read one lease directly, name the worker's lease id (#913) by @V3RON in #922
- feat(ui): the console reads per page and marks data stale from events by @V3RON in #926
- feat(inbox): the daemon says what needs the operator: GET /v1/inbox by @V3RON in #937
- feat(ui): the console sends ETags back and patches lease renewals in place by @V3RON in #927
- feat(ui): one shared recent-events list per console tab by @V3RON in #939
- test(console): an idle console on a 50-worker fleet stays under 40 requests a minute (#918) by @V3RON in #940
- fix(ports): a worker redials a gateway that vanished without closing the uplink by @V3RON in #942
- docs(adr): 0045 a device's screen streams to operators, not a lease's (#906) by @V3RON in #908
- feat(stream): stream any running device by worker and device id by @V3RON in #923
- fix(ui): console layout fixes from the 2026-10-23 review by @V3RON in #924
- feat(ui): watch a device's screen from the device drawer by @V3RON in #928
- feat(history): the worker's Events tab scrolls back through its history by @V3RON in #943
- fix(http): an Android lease over HTTP names its adb serial as address by @V3RON in #953
- feat(cli): simlock instructions prints the rules an agent must follow by @V3RON in #960
- feat(cli): simlock setup installs the Simlock skill into Claude Code and Codex by @V3RON in #969
- docs(adr): 0046 a standalone worker serves agent-device by default with a private profile by @V3RON in #954
- feat(modules): a standalone worker writes a private agent-device profile for local agents by @V3RON in #963
- feat(core): a standalone worker serves agent-device on localhost by default by @V3RON in #967
- fix(e2e): keyboard console tests wait for the sign-in form before tabbing by @V3RON in #936
- docs(adr): 0047 device.exec fills in the lease's device, and refuses another (#951) by @V3RON in #955
- feat(drivers): device.exec fills in the lease's device and refuses another by @V3RON in #972
- feat(mcp): run_on_device runs a command on the session's lease by @V3RON in #974
- feat(leasing): lease.maxPerRequester per platform by @V3RON in #975
- fix(android): quote a 4 s boot for a device with a matching clean baseline by @V3RON in #978
- fix(capacity): a shut-down device holds no RAM budget by @V3RON in #979
- docs(agent-device): parallel agents need their own session by @V3RON in #980
- fix(e2e): a daemon start that exits 0 but never listened fails with its log tail by @V3RON in #982
- fix(agent-device): sharding names a leased device by agent-device's device list name by @V3RON in #986
- fix(daemon): log the Android driver's diagnostics by @V3RON in #987
- test(agent-device): an over-limit download never delivers more than 2 GiB by @V3RON in #988
- docs(gateway): a starting worker's leases are hidden from their owner by @V3RON in #989
- fix(daemon): daemon start fails when the HTTP listener cannot bind by @V3RON in #990
- fix(gateway): an expired lease on a disconnected worker no longer blocks its requester by @V3RON in #992
- fix(daemon): a stop waits for the cleanup run in flight (#985) by @V3RON in #999
- docs(website): --lease waits for a starting worker (#991) by @V3RON in #1002
- chore(agents): process review 2026-10-25: turbo, bug:new triage, feature auto-close, orchestrator scripts, tool-guard waiting rules by @V3RON in #993
- chore(checks): the test lint and nine repo tests hold the rules agents did not read, and fix the drift they found by @V3RON in #994
- chore(checks): guards and PR checks make the delivery rules mechanical by @V3RON in #995
- chore(checks): the spec lint runs before the checker, and a public-surface change needs its page by @V3RON in #996
- build(deps): Fallow 3.35 with an honest CI gate by @V3RON in #997
- fix(daemon): a stop mid-startup refuses parked requests (#1001) by @V3RON in #1003
- fix(daemon): a stop waits for health ticks and recoveries in flight by @V3RON in #1004
- fix(e2e): the keyboard-scroll test notes the row in view after the end row moves it by @V3RON in #1007
- fix(e2e): the Events tab test reads every /v1/events body before the page closes by @V3RON in #1008
- chore(comments): delete comments that say what, not why, since 4429038 by @V3RON in #1011
- docs(adr): 0048 an iOS worker may keep its simulators in Xcode's device set by @V3RON in #964
- feat(drivers): iOS simulators can live in Xcode's device set (drivers.ios.deviceSet) by @V3RON in #976
- chore(ci): keep the release token out of the push URL; website install without scripts by @V3RON in #889
- chore(deps): update ws, hono and the MCP SDK past their advisories; Dependabot for npm by @V3RON in #890
- fix(daemon): exec children get a minimal environment; docs say what an agent token can do by @V3RON in #891
- fix(daemon): the data directory is created owner-only by @V3RON in #892
- fix(daemon): status.get shows an agent only its own leases and queue entries by @V3RON in #893
- fix(contract): an exact osVersion is bounded like a component version by @V3RON in #895
- feat(gateway): a join token is pinned to the first worker that uses it by @V3RON in #894
- chore(comments): delete comments that say what, not why, in src/contract by @V3RON in #1032
- chore(comments): delete comments that say what, not why, since 1f42ae4 by @V3RON in #1033
- docs(adr): 0049, a lease holder watches and drives its device's screen (#1013) by @V3RON in https://github.com/callstackincubator/simlock/pull/1014
- feat(stream): a lease holder watches its own lease's screen by @V3RON in https://github.com/callstackincubator/simlock/pull/1025
- feat(gateway): a gateway module can hold a two-way byte channel to a worker module by @V3RON in https://github.com/callstackincubator/simlock/pull/1026
- feat(input): a lease's input socket by @V3RON in https://github.com/callstackincubator/simlock/pull/1034
- feat(input): Android input through scrcpy's control channel by @V3RON in https://github.com/callstackincubator/simlock/pull/1036
- feat(input): iOS simulator input through the HID injector by @V3RON in https://github.com/callstackincubator/simlock/pull/1037
- fix(gateway): drop agent-device instance pins when relaying by @V3RON in https://github.com/callstackincubator/simlock/pull/1045
- feat(warm-pool): configured targets come first, and warmPool.learn turns learning off by @V3RON in https://github.com/callstackincubator/simlock/pull/1043
- feat(warm-pool): simlock warm forget forgets a learned kind by @alcpereira in https://github.com/callstackincubator/simlock/pull/1040
- chore(comments): delete comments that say what, not why, since 65df1b6 by @V3RON in https://github.com/callstackincubator/simlock/pull/1038
- chore(deps): bump @readme/openapi-parser from 9.1.0 to 10.0.0 by @dependabot[bot] in https://github.com/callstackincubator/simlock/pull/1023
- feat(cli): simlock --version prints the installed version by @V3RON in https://github.com/callstackincubator/simlock/pull/1059
- feat(cli): simlock setup runs the doctor checks and reports the machine by @V3RON in https://github.com/callstackincubator/simlock/pull/1062
- docs(website): one install recipe, MCP by scope, for-agents box by @V3RON in https://github.com/callstackincubator/simlock/pull/1065
- ci(release): build the package on the xcode-27 image by @V3RON in https://github.com/callstackincubator/simlock/pull/1072
New Contributors
- @alcpereira made their first contribution in #167
Full Changelog: v0.2.0...v0.4.0