status, doctor: finalize sessions whose agent has exited
Commit

Extract endSessionNow — the markSessionEnded + eager-condense sequence the SessionStop hook already runs — and share it with a new finalizeExitedSessions sweep, so the hook and the sweep stay in lockstep. markSessionEnded gains an optional guard so the sweep re-checks OwnerExited on the freshly-loaded state under the session-state lock, closing a TOCTOU race where a turn could revive a session between the list snapshot and the finalize.
entire status and entire doctor run the sweep up front, finalizing any ACTIVE session whose owner process is gone (PhaseEnded + condense) instead of leaving it "active" until the 1h StuckActiveThreshold. Both surfaces also label such sessions "exited" (human output, status --json, and doctor's stuck-session reason) as a fallback when finalization can't run.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Entire-Checkpoint: 1fcfee56345b