fix(daemon): keep a session closable while close withholds its device claim
Summary
Refs #4237, close path only. The issue stays open for the open/relaunch follow-up.
close kept the device claim after a failed cleanup or platform close, but retired the session. A retried close got SESSION_NOT_FOUND; only a daemon restart freed the device.
Now a close that withholds the claim keeps the session and its lease, so a plain close retry releases it. Claimless sessions are still retired. A kept session doesn't block daemon idle reap until a successful reopen: an idle detached daemon shuts down, retries the cleanup, and leaves an unconfirmed claim stale. Embedded runtimes and AGENT_DEVICE_DAEMON_IDLE_TIMEOUT_MS=0 need a manual close. Help, docs, ADR 0036 updated.
Design: internal closes (bounded batch/replay, test cleanup) keep the session too. On main they left a claim nothing could free.
Validation
session-close-claim-retry.test.ts, 12 cases:- a retried
closereleases the claim; a leased session keeps its lease; --save-script: the same-flag retry is refused, and a plainclosereleases the claim;- claimless: the session is retired;
- lease-release and platform-close failures are reported correctly;
- idle reap: fires for every kept session (incl. a failed lease release), not once reopened.
- a retried
- Bounded batch/replay IME tests: idle reap unblocked.
- Each fix's cases fail on the code before that fix.
pnpm check:affected --run --head 899fee29b8: passed,exactCommit: true, receiptrun-hNnhV9.- Live Android run at 899fee29b8 (emulator-5556): see the evidence comment.
Known gap: retrying after a committed repair dispatches the platform close again.
š¤ Generated with Claude Code