Found during #1381's live ADR 0016 validation (required live iOS/Android runs). Pre-existing — reproduced byte-identically at merge base 00ef28734 — not introduced by #1349.
Repro (live Android emulator, real daemon over CLI)
printf 'context platform=android device="Pixel 9 Pro XL API 37" kind=emulator theme=unknown\nopen "com.android.settings" --relaunch\n' > /tmp/open-only.ad
AGENT_DEVICE_STATE_DIR=/tmp/ad-state node bin/agent-device.mjs replay /tmp/open-only.ad --json
# => success, data.session = "cwd:<hash>:default"
AGENT_DEVICE_STATE_DIR=/tmp/ad-state node bin/agent-device.mjs session list --json
# => { "sessions": [] }
The script has no close, yet the session is gone ~120ms after the replay response. The session's events.ndjson shows request.finished (replay, ok) followed by the empty session_list with no close/teardown event in between; the daemon process (same pid) stays alive throughout, so it is an in-process store removal, not a daemon restart.
Why it matters
ADR 0016's consumption contract: "a script without close … the named session stays active and the successful ReplayCommandResult returns its session id. The caller binds subsequent commands to that returned id." The provider-scenario test (active-session-script-publication.test.ts) passes because the in-process daemon store keeps the session across callCommand calls — the live CLI path is where it breaks, which is exactly the gap the ADR's live-run validation bullet exists to catch.
Two adjacent observations from the same sessions (may share a root cause; can split out if not):
- After a
close of the recording session, the immediate next replay can fail step 1 with DEVICE_IN_USE ("Device is already in use by session "default"") until a second explicit close --session default — a lingering claim/lease after teardown (cf. the daemon-shutdown releaseSessionLease gap noted in the device-claim design).
- One interleaved sequence of closes across a stale replay session + a PUBLISHED recording session left the published
.ad rewritten with post-publication actions and two trailing close lines (PUBLISHED close-time saving is supposed to be disarmed; the clean publish→get→close flow is hash-stable, verified). Timeline available on request.
Live session/event logs from the runs are available in the #1381 validation notes.
Found during #1381's live ADR 0016 validation (required live iOS/Android runs). Pre-existing — reproduced byte-identically at merge base
00ef28734— not introduced by #1349.Repro (live Android emulator, real daemon over CLI)
The script has no
close, yet the session is gone ~120ms after the replay response. The session'sevents.ndjsonshowsrequest.finished (replay, ok)followed by the emptysession_listwith no close/teardown event in between; the daemon process (same pid) stays alive throughout, so it is an in-process store removal, not a daemon restart.Why it matters
ADR 0016's consumption contract: "a script without
close… the named session stays active and the successfulReplayCommandResultreturns its session id. The caller binds subsequent commands to that returned id." The provider-scenario test (active-session-script-publication.test.ts) passes because the in-process daemon store keeps the session acrosscallCommandcalls — the live CLI path is where it breaks, which is exactly the gap the ADR's live-run validation bullet exists to catch.Two adjacent observations from the same sessions (may share a root cause; can split out if not):
closeof the recording session, the immediate nextreplaycan fail step 1 withDEVICE_IN_USE("Device is already in use by session "default"") until a second explicitclose --session default— a lingering claim/lease after teardown (cf. the daemon-shutdownreleaseSessionLeasegap noted in the device-claim design)..adrewritten with post-publication actions and two trailingcloselines (PUBLISHED close-time saving is supposed to be disarmed; the clean publish→get→close flow is hash-stable, verified). Timeline available on request.Live session/event logs from the runs are available in the #1381 validation notes.