Skip to content

Named baselines: a lease starts from a device the operator prepared #327

Open
0 of 6 issues completed
Open

Description

@V3RON

Request: #1049

Problem

Every lease starts from a factory-fresh device, and every agent does the same setup on it before the real work starts: install the app under test, trust a certificate, sign into a test account, set a locale, grant permissions, seed data. That takes minutes per lease, is repeated by every agent on every lease, and is done slightly differently each time. Reclaim wipes the device back to factory, so the work is thrown away on release. Teams report reinstalling Firefox's split APKs on every Android lease, and being stuck with the system image's old Chrome (113 on an API 34 image), which could not load their game's 3D models (#327, leonardoxr).

Operators have no way to prepare a device once and hand copies of it out.

The factory start is also slow and fragile on its own (#1049, points 1 and 4). A new or erased simulator pays a full first boot (36.4 s for a new one and 39.9 s for an erase plus boot, measured on an M3 Pro with iOS 27.0), while a copy of one that booted once boots in 7.2 s. An Android reset loads a snapshot into the running emulator: one load hung for 18 minutes (#1047), a failed load wipes the disk, and creating another emulator once invalidated every other emulator's snapshot (#1048). In #1049's words: "There is also no way to prepare an emulator once (switch apps and animations off, skip a browser's first run) and keep that state across leases."

Who it is for

A team running many agents against one project, where every run needs the same prepared state. The operator who would rather set a device up once than write setup instructions for every agent. An agent that wants to start at step one of its test, not at step zero.

Every agent on a busy Mac, baseline or not, that waits for a first boot after each release.

Outcome

  • An operator prepares a device on a lease they hold, by hand or with their own scripts, and saves it under a name as a baseline. Saving ends that lease. A baseline is tied to the platform, model, OS, mode and image tag of the device it was saved from.
  • A lease request can name a baseline. The granted device is a copy of the baseline: its apps, data, settings, certificates and accounts are in place when the grant arrives.
  • When a baseline lease is released, its device is thrown away, and the next lease naming the baseline gets a new copy: nothing from the previous lease carries over.
  • Baselines can be listed with their note, spec, version, size, when they were saved and whether they are stale. Saving under an existing name replaces the baseline: leases already granted keep what they have, new leases get the new version, and the old version is deleted once nothing uses it. A baseline can be removed when no lease uses it.
  • A device made from one baseline is never handed to a request for another baseline, or for none. A request with no baseline gets a plain device as today.
  • A request naming a baseline that does not exist, that is stale, or that does not match the requested platform, model, OS, mode or image tag fails at once with a clear error. It never silently gets a plain device.
  • Plain leases get faster too: every new or reset simulator or emulator is a copy of a device that already booted once, so no lease waits for a factory first boot after the first one of its kind, and no Android reset loads a snapshot into a running emulator.
  • Through a gateway, a request naming a baseline goes only to a worker that has it, and the operator sees which workers hold which baselines.
  • The console lists each worker's baselines and shows which baseline a device came from.

How it works for the user

sequenceDiagram
  actor Op as Operator
  actor Ag as Agent
  participant S as Simlock worker
  Op->>S: simlock lease --platform android
  S-->>Op: lease L1 (device D1)
  Op->>Op: install the app, sign in, turn animations off
  Op->>S: simlock baseline save checkout --lease L1 --note "app 4.2, test user"
  S-->>Op: saved checkout v1, lease L1 ended
  Ag->>S: simlock lease --platform android --baseline checkout
  S-->>Ag: lease L2: a copy of checkout v1
  Ag->>S: simlock release L2
  S->>S: destroy that copy; the next lease gets a new one
  Ag->>S: simlock lease --platform android --baseline chekout
  S-->>Ag: UNKNOWN_BASELINE, at once
  Ag->>S: simlock lease --platform android --baseline checkout --os 35
  S-->>Ag: BASELINE_MISMATCH, at once
Loading

Before:

$ simlock lease --platform android --baseline checkout
{"error":{"code":"USAGE","message":"Unknown option '--baseline'. …"}}

After:

$ simlock lease --platform android --detach
{"device":{…,"model":"Pixel 9","osVersion":"36"},"lease":{"id":"L1",…}}
$ SIMLOCK_TOKEN=<operator token> simlock baseline save checkout --lease L1 --note "app 4.2, test user"
Saved baseline checkout v1: android Pixel 9, Android 36 (google_apis), full, 4.8 GB. Lease L1 ended.
$ simlock baseline list
NAME      VERSION  PLATFORM  MODEL    OS  MODE  IMAGE        SIZE    SAVED             NOTE
checkout  1        android   Pixel 9  36  full  google_apis  4.8 GB  2026-11-02 13:10  app 4.2, test user
$ simlock lease --platform android --baseline checkout --detach
{"device":{…,"baseline":{"name":"checkout","version":1}},"lease":{"id":"L2",…}}
$ simlock lease --platform android --baseline chekout
{"error":{"code":"UNKNOWN_BASELINE","message":"no baseline named \"chekout\" on this worker"}}
$ simlock lease --platform android --baseline checkout --os 35
{"error":{"code":"BASELINE_MISMATCH","message":"baseline checkout is Android 36, the request asks for 35"}}
$ SIMLOCK_TOKEN=<agent token> simlock baseline save mine --lease L2
{"error":{"code":"FORBIDDEN","message":"Operation baseline.save requires role admin, session is agent"}}
$ SIMLOCK_TOKEN=<operator token> simlock baseline remove checkout --yes
{"error":{"code":"BASELINE_IN_USE","message":"baseline checkout is in use by lease L2"}}

Examples

A baseline name:

Input Today After
checkout no such option accepted
checkout-v2.1_ios no such option accepted
Checkout no such option refused: BAD_REQUEST, lower case only
-checkout no such option refused: must start with a letter or digit
65 characters no such option refused: at most 64
empty --baseline "" no such option refused: at least 1 character
SIMLOCK_BASELINE=checkout and --baseline other no effect other (the flag wins)

Which device serves which request, with baseline checkout saved from a full Pixel 9 on Android 36:

Request Today After
--platform android plain device plain device, never a checkout copy
--platform android --baseline checkout no such option a checkout copy
--platform android --baseline checkout --device "Pixel 9" no such option a checkout copy
--platform android --baseline checkout --os 35 no such option BASELINE_MISMATCH, at once
--baseline checkout --platform ios no such option BASELINE_MISMATCH, at once
--platform android --baseline checkout --physical no such option BAD_REQUEST, at once
--platform android --baseline nothere no such option UNKNOWN_BASELINE, at once
--platform android --baseline checkout after the Android 36 image was removed no such option BASELINE_STALE, at once

What could go wrong

  • A lease named a baseline but got a device without the operator's apps. Unlikely: a baseline device is only ever a copy of that baseline.
  • Two agents leasing the same baseline at once share the test account saved in it and log each other out. Likely when a team saves a signed-in account; the docs say so.
  • A Mac's disk fills up because baselines are never cleaned up on their own. Possible on small disks: an Android baseline is about 5 GB.
  • After an Xcode or emulator update, leases naming a baseline fail until the operator saves it again. Expected; the error and baseline list say why.

Words used

  • source: a device that booted once and was shut down cleanly, kept only to be copied, never leased. Example: the device Simlock copies each time a lease asks for a plain iPhone 17 on iOS 27.0.
  • seed: a source Simlock makes by itself for plain leases, one per platform, model, OS and image tag. Users never name or see it, except in doctor and disk figures.
  • baseline: a source an operator saved from a lease under a name, e.g. checkout.
  • version: a baseline's number, 1 at the first save and one more at each save under the same name.
  • stale: a baseline whose runtime, system image or emulator changed after it was saved, so it can no longer be copied. Example: checkout after the Android 36 image was removed.
  • copy: making a device from a source (iOS simctl clone; Android a copy of the AVD folder). Every lease gets a new copy; a released copy is thrown away.
  • boot snapshot: the one Android memory snapshot stored with a source, so a copy boots in seconds. Replaces the per-device "clean baseline" snapshot of today.

Non-goals

  • Simlock performing the setup. There is no provisioning script and no program run before a device's first boot (Lighter, faster-to-reset devices for a pool of coding agents on one Mac #1049 asks for one; it is its own request). The operator prepares the device; Simlock copies it.
  • An agent saving a device back to a baseline. Only the operator saves.
  • Guaranteeing that in-app state such as a signed-in session survives a boot. That is up to the app.
  • Rolling a baseline back to an older version.
  • Moving a baseline between workers (export and import), or keeping baselines in step across workers.
  • Baselines on physical devices.
  • Removing a baseline because it is old or unused. Only the operator or nuke removes one.
  • Emulator RAM, cores and metrics in the config (Lighter, faster-to-reset devices for a pool of coding agents on one Mac #1049 point 3).
  • Naming a baseline through agent-device. The pinned agent-device cannot send one; that is a follow-up on both sides.
  • Keeping a device between leases. Every simulator and emulator now serves one lease and is thrown away; lease.identity no longer changes anything for them.

Completion conditions

  • An operator leases a device, installs an app on it, and saves it as a baseline. The lease ends. simlock baseline list shows it with its platform, model, OS, mode, version and size.
  • simlock lease --platform <platform> --baseline <name> is granted a device with that app installed. The agent installs nothing.
  • After that lease is released, the next lease naming the baseline gets a device with the app installed and without any file or setting the previous lease changed.
  • A lease with no baseline never receives a device made from one, and a lease naming one never receives a plain device or another baseline's device, even while one sits idle.
  • A --baseline with a model, OS, mode or image tag the baseline was not made for fails at once, naming the mismatch. An unknown name fails at once. A stale baseline fails at once, naming why.
  • Saving under an existing name leaves running leases untouched, and the next lease gets the new version.
  • Removing a baseline that a lease is using is refused. Removing an unused one frees its disk and the idle devices made from it.
  • On a Mac, a plain iOS lease of a kind that was leased before is granted without a factory first boot, and a plain Android reset loads no snapshot into a running emulator and never wipes.
  • Through a gateway, a request naming a baseline only one worker holds is granted by that worker. One that no worker holds fails at once. simlock worker list shows each worker's baselines.
  • simlock status and simlock list --devices show which baseline and version a device came from. The console lists each worker's baselines.
  • simlock nuke removes baselines and seeds with every other managed device, and simlock doctor lists them with their size.
  • The same request field works over the unix socket, the HTTP API, MCP and the client, and through SIMLOCK_BASELINE; the website describes it with the baseline commands.

Open questions

none

Decisions

Shared values

Value or state Rule Written by Read by Source
Baseline name 1–64 characters of a-z, 0-9, ., _, -, starting with a letter or digit; anything else is BAD_REQUEST at the wire edge #1206 (schema) #1206, #1207, #1208, #1209 src/contract/schemas.ts:86-90 (imageTagSchema, the model)
Source records each driver's own table (ios_source_data, android_source_data) keyed by source id: kind, state (making written first, ready at the end), spec key, model, OS, image tag, the platform's fields, size in bytes (absent when it could not be counted), stale reason; no JSON text; sources sit where a lease holder cannot reach them (iOS: their own device set) #1204 (iOS), #1205 (Android) #1206 ADR 0036 §2
Baseline records baselines table, owner baselines, one row per name and version (kept until no device of that version remains): name, version, platform, model, OS, mode, image tag, note, saved at, source id, stale reason #1206 #1207, #1208, #1209 ADR 0036 §2
Baseline list entry name, version, platform, model, OS, mode, image tag, note, size in bytes (absent when it could not be counted; the CLI prints -), saved at (ISO time), stale reason or none; on a gateway also the worker id #1206 #1208 (worker view, gateway list), #1209 ADR 0061 §4
copyTree one filesystem port verb copyTree(from, to, { timeoutMs }), 600 s for every caller; its one adapter runs cp -c -p -R on macOS, cp -a --reflink=auto on Linux, a recursive copy keeping modification times elsewhere #1205 #1206 src/ports/filesystem.ts:52
Device's baseline a virtual device record carries the baseline name and version it was copied from, or none (devices.baseline_name, devices.baseline_version) #1206 (columns), #1207 (values) #1206, #1207, #1208, #1209 src/core/registry-schema.ts:4-35
One lease per virtual device every virtual device is destroyed after its one lease (core's spent path, today taken by lease.identity: fresh); quarantine destroys a virtual device and never reclaims it; a driver's reclaim is for physical devices only #1204 #1205, #1206, #1207 src/core/domain.ts:290-292
BASELINE_IN_USE baseline <name> is in use by lease <id> #1206 #1208, #1209 ADR 0061 §4
BASELINE_SAVE_FAILED a save that failed after its lease ended: the lease stays ended, the device is quarantined, no baseline row is written #1206 #1208 ADR 0061 §4
Baseline routes GET /v1/baselines answers { baselines: [<list entry>] }; POST /v1/baselines saves; DELETE /v1/baselines/{name} removes, with ?workerId=<id> required on a gateway #1206 #1208, #1209 src/http/AGENTS.md
Stale reasons free text that reads after is stale:, at most 300 characters, e.g. runtime com.apple.CoreSimulator.SimRuntime.iOS-27-0 is not installed; each driver lists its own word for word; re-checked on start, after a component removal, before each provision of a baseline, and on list and doctor; a reason clears when the source fits again #1204, #1205 #1206, #1207, #1208, #1209 ADR 0061 §3
provision(spec, { source? }), listSources, destroySource the driver verbs ADR 0061 §1 names; saveSource is added by #1206 #1204 #1205, #1206, #1207 ADR 0061 §1
UNKNOWN_BASELINE no baseline named "<name>" on this worker; on a gateway, when no worker holds it, no worker holds a baseline named "<name>" #1206 #1207, #1208 ADR 0061 §5, §6
BASELINE_MISMATCH baseline <name> is <field value>, the request asks for <value>, naming the first differing field in the order platform, model, OS, mode, image tag; decided by one function both the worker and the gateway call; on a gateway, when every holder differs. Checks run unknown, mismatch, stale #1207 #1208 ADR 0061 §5, §6
BASELINE_STALE baseline <name> is stale: <reason>; on a gateway, when every holder's is stale, the first holder's reason in worker order #1206 (marks), #1207 (refuses) #1208, #1209 ADR 0061 §3, §6
Events baseline.saved (name, version, platform, model, OS, mode, image tag, size, lease id, requester id), baseline.removed (name, version, reason operator or nuke or replaced, requester id when an operator removed it), baseline.stale (name, version, reason); device.deleted gains initiator baseline-save; lease.granted gains baseline {name, version} when the device has one #1206, #1207 #1208, #1209 docs/internal/EVENTS.md
SIMLOCK_BASELINE read by the CLI for lease when --baseline is absent; empty means unset #1207 — ADR 0061 §5
Protocol version each of #1204 to #1209 that changes a contract shape bumps it by one #1204–#1209 — src/contract/AGENTS.md "Protocol version"

Behaviours

Behaviour (invoker, action, what it sees) Seam Cases Task
An agent leases a plain iOS device: Simlock copies the kind's seed, making it first if there is none, and grants the copy; the seed is never granted iOS driver provision and makeReady, src/drivers/ios/index.test.ts no seed yet; seed present; seed stale (its runtime changed) is remade; a named source #1204
A plain iOS lease is released: the simulator is destroyed, and the next lease gets a new copy that boots with the seed's disabled.plist daemon dispatcher, release then lease seed has a disabled.plist; it has none; the clone fails #1204
An operator runs doctor and nuke: seeds are listed with their size, and nuke deletes them daemon dispatcher, src/daemon/dispatcher.test.ts doctor; nuke; removing a runtime deletes its seeds #1204
Any virtual device is released: it is destroyed, whatever lease.identity says, and a device made before this feature goes the same way daemon dispatcher, release reusable; fresh; device made before this feature #1204
An agent leases a plain Android device: Simlock copies the kind's seed into the device's own folder, making it first if there is none, and boots it from the boot snapshot Android driver provision and makeReady, src/drivers/android/index.test.ts no seed yet; seed present; the snapshot does not load (cold boot of the same disk, no wipe); seed stale; two provisions at once; seeds listed and destroyed; the system image removed #1205
A plain Android device is destroyed: the ownership check passes, the emulator is killed and its folder deleted Android driver destroy check passes; check fails (nothing sent, refused) #1205
Two running copies of one seed are told apart: listing, locks and the ownership check go by each device's own AVD folder Android driver listManaged two copies running; old-layout AVD; seed folder is not a device #1205
A source is copied through the filesystem port copyTree adapter, src/ports/filesystem.test.ts macOS; Linux; other; cp fails #1205
An operator saves a held lease as a baseline: the lease ends, and the baseline is version 1, or one more than before under the same name daemon dispatcher baseline.save iOS; Android; existing name; agent token (FORBIDDEN); physical lease; unknown lease #1206
An operator lists baselines: each shows name, version, spec, note, size, saved time and stale reason daemon dispatcher baseline.list and CLI simlock baseline list none; one; stale #1206
An operator removes a baseline: an unused one and its idle devices go; one in use is refused daemon dispatcher baseline.remove unused; in use (BASELINE_IN_USE); unknown (UNKNOWN_BASELINE) #1206
Saving, removing and a baseline going stale each record one event daemon dispatcher, event bus saved; removed by operator; removed by nuke; removed as replaced; stale #1206
An agent leases naming a baseline: it gets a copy of the baseline, and the grant and lease.granted carry its name and version daemon dispatcher lease.request platform and name; with matching model and OS; --os ">=35" fits 36; --device "pixel 9"; CLI flag; SIMLOCK_BASELINE; HTTP; MCP #1207
A request naming a baseline that cannot serve it fails at once daemon dispatcher lease.request unknown name; different platform; different model; different OS; different mode; different image tag; stale; with --physical (BAD_REQUEST); with --class (BAD_REQUEST) #1207
Devices never cross pools: a plain request never gets a baseline device, a named one never gets a plain or other baseline's device, and a device of an older version is never granted leasing planner through the dispatcher idle baseline device and plain request; idle plain device and named request; idle device of another baseline; idle device of an older version #1207
A baseline lease is released: the next lease naming it sees none of the previous lease's changes daemon dispatcher, release then lease iOS; Android #1207
An operator replaces a baseline: running leases keep their device, the next lease gets the new version, and the old version is deleted when its last device goes daemon dispatcher lease running during replace; no lease running; idle copy of the old version (destroyed); a request waiting during the replace (gets the new version) #1207
The warm pool learns a baseline kind from a lease and keeps a copy warm warm pool, src/core/warm-pool/learned.test.ts baseline kind; plain kind beside it #1207
simlock status and simlock list --devices show a device's baseline and version CLI baseline device; plain device #1207
Through a gateway, a request naming a baseline goes only to a worker that holds it, fresh gateway dispatcher, src/gateway/dispatcher.test.ts one worker holds it; none holds it (UNKNOWN_BASELINE); only stale copies (BASELINE_STALE); every holder differs (BASELINE_MISMATCH); a holder answers UNKNOWN_BASELINE and is left out; a warm hit needs the current version; the only holder disconnected (NO_CAPACITY); the only holder busy (waits, with its reason) #1208
An operator runs simlock worker list on a gateway: each worker shows its baselines gateway dispatcher worker with baselines; worker with none #1208
An operator saves, lists and removes baselines through a gateway gateway dispatcher save goes to the lease's worker; list of every worker; remove with --worker; remove without --worker #1208
An operator opens the console: a Baselines page lists each worker's baselines, and a device's drawer shows its baseline console, browser test baselines present; none; stale #1209

Tasks

flowchart LR
  T1[#1204 iOS seeds] --> T2[#1205 Android seeds]
  T2 --> T3[#1206 save, list, remove]
  T3 --> T4[#1207 lease names a baseline]
  T4 --> T5[#1208 gateway]
  T5 --> T6[#1209 console]
Loading

Completion conditions by task: the first, saving, listing and removal — #1206; leasing by name, reset to the baseline, pools, fast failures, replace, status and list, every surface — #1207; plain iOS and Android leases — #1204 and #1205; nuke and doctor — #1204, #1205 and #1206; gateway — #1208; console — #1209.

Open work in the same area:

Written by an agent.

Activity

  1. added
    feature:specSpec in progress, business and technical together.
    on Oct 4, 2026
  2. ericlitman commented on Oct 30, 2026

    @ericlitman

    A data point for the iOS half, from Simlock 0.4.0 on Xcode 27.2. A simctl clone of a shut-down iPhone 17 / iOS 27.0 template that had been slimmed with simslim and booted once came up in 2.4 s and used 136 CPU-seconds over its first minute (median of 3). Today's reclaim (erase, then boot) used 804 on the same machine, and 168 when the device had already been slimmed by simslim. The full table is in #1049.

    One edge case we hit: simctl clone does not copy launchd overrides written by launchctl disable inside the simulator (which is what simslim and Simlock's own slim pass write), because CoreSimulator keeps them outside the device folder, in /private/var/tmp/com.apple.CoreSimulator.SimDevice.<udid>/disabled.plist. A clone of a slim template comes up stock unless that file is copied to the clone's UDID before its first boot. simslim clone copies it; a baseline reclaim would need to as well.

    We'd use baselines for our own pool and would be glad to send a PR for the iOS half (save a shut-down device as a named baseline, lease by name, reclaim by delete plus clone with the override file carried over), in whatever shape you want the spec to take. Say if that would help.

  3. TUNA-NOPE commented on Oct 30, 2026

    @TUNA-NOPE
    Contributor

    Use case for a variant of this: named state that one agent saves and another resumes on a different device, not only a template. We built it outside Simlock and hit three facts that may help the spec.

    • iOS, data folder copied to another UDID: apps fail to launch (SBMainWorkspace denial) until the old UDID is rewritten in var/db/lsd, var/run, Library/FrontBoard and Library/Preferences. simctl clone avoids this but changes the UDID.
    • iOS, saving from a lease: the health monitor reads a stopped device as a crash after two probes, so a shutdown under 30 s with the default settings is safe, and the swap can stay in that window.
    • Android, full /data copy: system apps crash-loop on another device. Per-app copy works, but an app whose key is in Keystore signs out unless its keystore2 rows are merged with the uid remapped.

    Would save-back to the same name, with one holder at a time, fit this issue?

    Written by an agent.

  4. leonardoxr commented on Oct 30, 2026

    @leonardoxr
    Contributor

    One more case for this, from a team testing a browser game on leased devices.

    • Every Firefox test on an Android lease reinstalls Firefox's split APKs, because each lease starts from a wiped device. A baseline with Firefox installed would remove that step from every run.
    • The Android emulator's built-in Chrome is the one in its system image (Chrome 113 on our API 34 image), and it never loaded our game's 3D models. Leasing a newer API level gets a newer Chrome. A baseline with Chrome updated from the Play Store would let us test the Chrome our users run on a given Android version.

    Written by an agent.

  5. V3RON commented on Nov 2, 2026

    @V3RON
    ContributorAuthor

    Spec updated: every section rewritten from the 2026-11-02 spec session, with the open questions answered; Request is now #1049 (points 1 and 4 folded in); the old Platform findings and Also needed moved into ADR 0061 (PR #1201) with new measurements; Decisions, Shared values, Behaviours and Tasks added.

    Written by an agent.

  6. V3RON commented on Nov 2, 2026

    @V3RON
    ContributorAuthor

    Spec updated: round-0 check answers folded in (a new device per lease, --platform stays required, agent-device out and filed as a follow-up, gateway stale answer, copy behind a filesystem port, Android keyed by AVD folder); Shared values and Behaviours updated; ADR 0061 updated on PR #1201.

    Written by an agent.

  7. V3RON commented on Nov 2, 2026

    @V3RON
    ContributorAuthor

    Spec updated: tasks #1204–#1209 added as sub-issues; Shared values gained the baseline routes, stale reasons, driver verbs and BASELINE_SAVE_FAILED rows; the example session now shows the CLI's JSON output; Behaviours cases synced with the tasks.

    Written by an agent.

  8. V3RON commented on Nov 2, 2026

    @V3RON
    ContributorAuthor

    Spec updated: round-1 check findings fixed in #327 and #1204–#1209 (sources out of agents' reach, making rows, one doctor list, nuke split, replace and waiting requests, one mismatch function, gateway order and HTTP workerId, JSON CLI examples); ADR 0061 updated on PR #1201.

    Written by an agent.

  9. added
    feature:plannedSplit into tasks. Never picked up itself.
    and removed
    feature:specSpec in progress, business and technical together.
    on Nov 2, 2026
  10. V3RON commented on Nov 2, 2026

    @V3RON
    ContributorAuthor

    Spec approved by the maintainer on 2026-11-02: ADR 0061 (PR #1201) is Accepted — not yet implemented; tasks #1204 → #1205 → #1206 → #1207 → #1208 → #1209 are task:ready; this feature is feature:planned. Follow-ups filed: #1202 (operator program before first boot), #1203 (agent-device names a baseline).

    Written by an agent.

  11. che1404 commented on Nov 2, 2026

    @che1404

    Use case from our fleet, in support of named baselines: testing Google Play Billing purchases on emulators.

    A purchase needs a Play Store image (google_apis_playstore) and a Google account that is a Play license tester signed in to Play Store. Today every lease starts wiped, so a person has to type the Google password (often with a 2-step prompt on their phone) on each lease, while an agent drives the rest. If the person is not at the screen when the agent reaches the sign-in step, the lease goes idle and is reclaimed, and the sign-in is lost.

    A baseline prepared once by an operator (Play Store image + license-tester account signed in + screen lock if the account is Google Workspace) would make these purchase tests agent-runnable. The android_id caveat in #1205 matters here: we would need to know whether Google keeps the session valid across copies that share it.

  12. V3RON commented on Nov 3, 2026

    @V3RON
    ContributorAuthor

    Handoff

    Done: all six tasks reviewed and ready in stack #1201 > #1210 > #1222 > #1235 > #1236 > #1241 > #1245; ADR 0061 flipped to Accepted on task/1209. Hardware loop on task/1209: the Android release hang fixed (72dbb66, 4301591, b4bcd22), the Android baseline copy fixed (0d38b33). Lane run 2 at 4301591: 6 of 7 files pass.

    Not done: e2e/slow-baseline.test.ts Android fails in its home teardown, ENOTEMPTY in the copy's simlock.avd/modem_simulator (log simlock-slow-e2e-20261103-235223.log). Next: hardware-fix from 4301591 (see the Handoff on #1209), the whole lane again, then one fix-check from 519e2c0. Merge waits for the maintainer.

    Findings: this session was stopped by the 120M-token budget guard.

    Blocked on: a fresh deliver #327 session. After #327 merges, deliver #1118 and #1237 in separate sessions once each is verified unblocked.

    Written by an agent.

  13. V3RON commented on Nov 4, 2026

    @V3RON
    ContributorAuthor

    Delivery run

    Merged: none (the stack #1201 → #1210 → #1222 → #1235 → #1236 → #1241 → #1245 stays open)
    Parked: #1209 — fix-check finding R4 is open after the review cap: Android provisioning from a baseline source skips the stale check (ADR 0061 §3)
    Waiting: none
    Decided: none this run (earlier decisions on #1222 and #1236 still wait on the maintainer)

    The final hardware run passed on 4e6d4656a: 7 slow-lane files, 53/53, on iOS and Android.

    Written by an agent.

  14. V3RON commented on Nov 4, 2026

    @V3RON
    ContributorAuthor

    Delivery run

    Merged: none. The stack #1201 → #1210 → #1222 → #1235 → #1236 → #1241 → #1245 is ready and waits for the maintainer to merge.
    Parked: none. #1209's R4 was fixed at ca0154d91 with the maintainer's approval past the review cap; its fix-check found nothing.
    Waiting: none
    Decided: none this run (earlier decisions on #1222 and #1236 still wait on the maintainer)

    Hardware: full lane passed on 4e6d4656a (7 files, 53/53); slow-baseline passed again on ca0154d91 (iOS and Android, both lease from the saved baseline).

    Written by an agent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature:plannedSplit into tasks. Never picked up itself.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions