`src/engine/core/outcome.rs` — outcome → error
One small file with one load-bearing job: the canonical mapping from a terminal MachineOutcome to the LoopError a caller sees.
Key items
MachineOutcome::to_loop_error(max_turns) -> Option<LoopError>:Completed { .. }→None(a clean completion is not an error)MaxTurnsExceeded→MaxTurnsExceeded { max }Cancelled→CancelledFailed { error }→ the error itself
Behavior notes
- Single source of truth: both the driver’s
Donearm andLoop::stop_reason()go through it — the two can never disagree. - The
Donearm additionally guards the future: a non-Completedoutcome that maps to no error becomesLoopError::Internal("unmapped terminal outcome: ...")rather than committing as success — adding aMachineOutcomevariant without mapping it is a loud bug, not a silent one.
Deep dive: Termination.