What changed
Roder 0.1.13 makes interrupted and restarted work easier to reason about. Each turn now records a small redacted lifecycle history that says whether the turn is running, interrupted, completed, failed, or needs recovery after a restart. The record also reports what cleanup proof Roder has, instead of assuming that cancelling an async runtime task means every provider process or remote job was actually reaped.
The CLI and TUI expose durable recovery state, while app-server clients can read lifecycle state through thread/read, subscribe to lifecycle updates, call runtime/drain during shutdown, and inspect aggregate lifecycle/metrics counters.
This release also broadens reliability defaults for eval-style runs. The eval profile can continue after hitting the consecutive tool-failure limit by nudging the model and can nudge once when a non-interactive turn tries to finalize without using tools. Interactive and plain non-interactive sessions keep the conservative defaults unless you opt in through [reliability].
Two smaller agent-control ergonomics also landed in this release. create_goal can start the next objective after an earlier goal has already completed, blocked, paused, or hit a limit, so resumed sessions do not get stuck behind stale finished goal state. Subagent tools now validate configured roles and lane compatibility before child work starts, which catches misrouted fanout or spawn_agent requests before they consume a teammate turn.
Why it matters
- Restarted sessions no longer have to guess whether an active-looking turn actually survived a process restart. If Roder cannot prove that a turn reached a terminal path, it marks recovery needed.
- Shutdown is more explicit.
runtime/drainstops accepting new work, requests interruption for owned work, waits within a bounded deadline, and reports whether cleanup was clean, timed out, or failed to persist. - Provider cleanup is less hand-wavy. Claude Code uses a supervised SDK cleanup path, local process tasks use graceful signal, forced kill, and reap, and remote tasks call the remote-runner cancellation API.
- Eval runs can be less brittle without changing normal interactive behavior. The eval profile keeps working through recoverable tool-failure loops and premature empty finalization, while hard caps still bound the turn.
- Long compaction events are easier to inspect. The TUI and app-server item stream now include estimated before/after token counts and elapsed time for compaction summaries.
- Multi-agent runs fail earlier when the requested role or lane does not match the installed subagent configuration, making orchestration errors cheaper to correct.
Using it
Inspect lifecycle state from the CLI:
roder thread lifecycle <thread-id>
roder thread lifecycle <thread-id> --json
App-server clients can read the same state without loading a full transcript:
{
"jsonrpc": "2.0",
"id": 1,
"method": "thread/read",
"params": {
"threadId": "THREAD_ID",
"includeTurns": false
}
}
For shutdown-aware clients, call runtime/drain before exiting the process. Operators can tune the drain and process cleanup windows with [lifecycle] config keys such as shutdown_drain_timeout_ms, process_grace_timeout_ms, process_kill_timeout_ms, and cancel_tasks_on_session_end.