Architecture

Lifecycle recovery

Roder records a small durable lifecycle history for each turn. The history tells clients whether a turn finished, was interrupted, failed, or needs recovery after a restart, without exposing provider command lines, PIDs, prompts, or credentials.

Inspect a thread

roder thread lifecycle <thread-id>
roder thread lifecycle <thread-id> --json

App-server clients can call thread/read withincludeTurns: false and inspect the additive lifecyclefield. The TUI shows a durable warning when a resumed thread includesrecovery_needed records or redacted lifecycle-corruption diagnostics.

States and cleanup proof

  • running and interrupt_requested reconcile to recovery_needed after restart when no matching local turn remains.
  • completed, failed, and interrupted are terminal runtime states, but they do not disclose provider internals.
  • cleanup records whether cleanup was not requested, requested, completed, timed out, or unknown.
  • ownership reports the proof level: runtime task only, provider cleanup pending, or provider cleanup confirmed.

This distinction matters because interrupting Roder's async runtime task is not proof that every provider child process or remote job exited. Claude Code uses a supervised SDK cleanup path; local process tasks drain through graceful signal, forced kill, and reap; remote tasks call the selected runner's cancellation API.

Shutdown and metrics

runtime/drain stops admitting new turns, requests interruption for locally owned work, waits within a bounded deadline, and reportsclean, deadline_exceeded, orpersistence_failed. The shared [lifecycle] configuration controls shutdown drain time, process grace and kill windows, session-end cancellation, and bounded process diagnostics.

[lifecycle]
shutdown_drain_timeout_ms = 5000
process_grace_timeout_ms = 250
process_kill_timeout_ms = 1000
cancel_tasks_on_session_end = true
max_completed_process_diagnostics = 64

Native app-server clients can call lifecycle/metrics for redacted process-local counters covering drain outcomes, persistence failures, restart reconciliation, and provider cleanup proof totals. Use a thread's lifecycle record when deciding whether a particular turn needs inspection or retry.