Orphaned escrow sessions are currently bounded only by a 1-hour TTL (shipped in #237). A faster reconciliation was built and dropped in #238 review: sending "drop unclaimed sessions" 120s after app launch destroys sessions that programa snapshot restore can legitimately reattach at ANY later time (v2SnapshotRestore -> createMainWindow -> attemptSessionReattach). Clock-based dropping is fundamentally incompatible with manual snapshot recovery.
Design requirement: the holder may only drop a draining session when every snapshot that references it has been deleted or superseded - i.e. explicit claims, not elapsed time.
Sketch (from the dropped branch, reusable): fixed-size frame 0x05 exists in worktree-agent-a08ed6016d01a4bec history (commit 44108c099a) with correct drain/close coordination. What must change: instead of one unconditional reconcile-done, the app sends per-session claims derived from the union of {current snapshot, session-history/*.json} panel IDs; the holder drops only draining sessions with no claim. Claims refresh when history rotates (10-snapshot cap naturally expires old claims).
Old-holder compatibility is already safe: unknown frame types are logged and skipped (serve() decode guard), degrading to the TTL.
Verify: kill -9 the app mid-session, relaunch, wait past the reconcile window, then programa snapshot restore latest - the restored panes must reattach live processes, not scrollback corpses.
Orphaned escrow sessions are currently bounded only by a 1-hour TTL (shipped in #237). A faster reconciliation was built and dropped in #238 review: sending "drop unclaimed sessions" 120s after app launch destroys sessions that
programa snapshot restorecan legitimately reattach at ANY later time (v2SnapshotRestore->createMainWindow->attemptSessionReattach). Clock-based dropping is fundamentally incompatible with manual snapshot recovery.Design requirement: the holder may only drop a draining session when every snapshot that references it has been deleted or superseded - i.e. explicit claims, not elapsed time.
Sketch (from the dropped branch, reusable): fixed-size frame 0x05 exists in
worktree-agent-a08ed6016d01a4bechistory (commit 44108c099a) with correct drain/close coordination. What must change: instead of one unconditional reconcile-done, the app sends per-session claims derived from the union of {current snapshot, session-history/*.json} panel IDs; the holder drops only draining sessions with no claim. Claims refresh when history rotates (10-snapshot cap naturally expires old claims).Old-holder compatibility is already safe: unknown frame types are logged and skipped (
serve()decode guard), degrading to the TTL.Verify: kill -9 the app mid-session, relaunch, wait past the reconcile window, then
programa snapshot restore latest- the restored panes must reattach live processes, not scrollback corpses.