Skip to content

session list omits cwd-scoped sessions opened via replay's internal open dispatch #1394

Description

@thymikee

Found during live iOS/Android validation of #1390's #1384 fix.

Repro (real backends, both platforms)

printf 'context platform=android device="Pixel 9 Pro XL" 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", data.sessionActive = true
AGENT_DEVICE_STATE_DIR=/tmp/ad-state node bin/agent-device.mjs session list --json
# => { "sessions": [] }        <-- empty, but the session is NOT gone
AGENT_DEVICE_STATE_DIR=/tmp/ad-state node bin/agent-device.mjs snapshot --json --session "cwd:<hash>:default"
# => succeeds, real snapshot of the still-open app

Reproduced identically on a booted iOS simulator (open "com.apple.Preferences").

Root cause (traced, not yet fixed)

session_list (src/daemon/handlers/session-inventory.ts:33-40) filters sessionStore.toArray() by sessionMatchesScope(session, resolveImplicitSessionScope(req)) (src/daemon/session-routing.ts) — comparing the CURRENT request's freshly-computed cwd scope against a session.sessionScope field stored on the session at creation time (src/daemon/handlers/session-open.ts:433,520: sessionScope: existingSession?.sessionScope ?? resolveImplicitSessionScope(req)).

The session's storage key (cwd:<hash>:default) is computed correctly at the top-level replay request's own dispatch (resolveEffectiveSessionName), using the CLI's real meta.cwd. But the session's sessionScope field gets set by whatever req reaches session-open.ts when the script's open action is dispatched internally during replay (invokeReplayAction → the real open handler) — and that internally-constructed request apparently doesn't carry the same meta.cwd a top-level CLI request does, so resolveImplicitSessionScope returns undefined for it, leaving session.sessionScope unset.

Later, session_list's own top-level request computes a proper (non-undefined) scope from the CLI's real cwd, compares it to the session's undefined sessionScope, and filters it out — even though the session is fully alive and reachable by its exact name.

Impact

Cosmetic/discovery only — the session is never actually lost, and every command that names the session explicitly (--session <name> or --state-dir <dir>, matching #1390's new address-hint contract) works. But session list (the common no-argument way to discover what's running) silently omits every cwd-scoped session created via a replay script's internal open, which will read as "nothing is running" to an agent or human relying on it.

Scope

Distinct from #1384/#1391 — this is a sessionScope propagation gap in the replay-internal open-dispatch path, not the client/daemon-lifecycle teardown #1390 fixes. Worth its own fix: either propagate the outer replay request's meta.cwd into the internally-dispatched open request, or have session-open.ts fall back to computing scope from a scope already resolved by the enclosing replay dispatch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions