Great question, Kartik.
Foreman is a daemon, but the Claude session isn't something it watches from outside, the daemon process contains both, with the Claude run executing in-process through the Agent SDK. So foreman never infers that a run ended; it's holding the return value, and that value is always one of a short list: success, timeout, max turns, max budget, paused for a human (ask_human or the plan gate), cancelled, or error. As long as the process runs to completion, a decision is guaranteed. Whether the work was any good is a separate question, answered outside the transcript by the test exit code and the PR's CI status; a "success" with no commits and no PR is treated as a failure, not a delivery.
If it doesn't run to completion, note that "Claude crashed" and "foreman crashed" are the same event; there's no orphan to detect. Job state lives in MongoDB, so on restart foreman picks up anything that was mid-run, marks it failed and retries it; the worktree survives, so the retry just runs again in place. Retries are capped, and when they're exhausted the job goes dead and reports the failure on the ticket and in Slack. Then it's the human's call.