pub enum StopCause {
Completed,
MaxTurns,
OutputTokenBudget,
CostBudget,
Interrupted,
Loop,
NoOutput,
}Expand description
Why the loop stopped. Completed is the model deciding it was done;
everything else is the harness cutting it short.
Ord is derived so it can key a map — the declaration order carries no
meaning beyond giving a histogram a stable print order.
Variants§
Completed
MaxTurns
OutputTokenBudget
CostBudget
Interrupted
Someone cancelled it — a user pressing Ctrl-C, a shutdown, a timeout.
Loop
The model repeated an identical tool call, with an identical result,
right after a compaction — the sign that compaction did not carry the
task and the run is stuck re-living it. Distinct from MaxTurns on
purpose: “hit the turn limit” reads as the task being too big, when a
stuck run is a different problem with a different fix.
NoOutput
The model returned turns with no content at all — no text, no tool
calls — and did not recover when asked to answer. A thinking model does
this when the whole per-turn budget goes to reasoning and the answer
never starts; the provider reports max_tokens, or even stop, with an
empty message.
Distinct from Completed for the reason Loop is distinct from
MaxTurns: this used to report success. A run that produced nothing
returned StopCause::Completed with exhausted: false, so it was
indistinguishable from a model that finished and had nothing to say —
which is how it went unnoticed until it accounted for 15 of 28
Terminal-Bench trials, every one of them scored as an ordinary failure.
Implementations§
Source§impl StopCause
impl StopCause
Sourcepub fn is_early(self) -> bool
pub fn is_early(self) -> bool
True when the harness cut the run short, so the answer may be partial.
Sourcepub fn cut_short(self) -> bool
pub fn cut_short(self) -> bool
True when the harness ended the run, as distinct from the model
finishing or a person stopping it. Narrower than Self::is_early.
One definition because there were two, and they disagreed: doctor
excluded Interrupted on the grounds that a person pressing Ctrl-C is
the system working, while the candidate gate’s CutShort metric
counted everything that was not Completed — so a cancelled arm
scored as a loss on the metric it was predicting. NoOutput belongs
on this side: a run that produced nothing and did not recover was
ended by the harness, and it is the failure mode that took 15 of 28
trials in one benchmark, so a check blind to it is blind to the thing
most worth seeing.