pub enum LoopFailure {
EngineUnavailable,
Cancelled,
Infrastructure,
Configuration,
NeedsAuth,
Execution,
Verification,
BudgetExhausted,
}Expand description
Why a loop run ended without green checks.
One axis: “what stopped this from passing”. Descriptive, not
prescriptive — each variant records what happened, never what to do next.
See LoopOutcome::failure for why, and do not read a retry instruction
out of any variant here.
Produced by four modules (external_loop, native_loop, foreman_loop,
rpc), so “the worker” below means whatever ran the work — an external CLI,
the native inference loop, or a foreman farm-out.
The first two are knowable before the contract can say anything: no work
was attempted, so there is nothing to evaluate. The rest describe a run that
produced work. Where a loop can evaluate the contract it does so before
classifying — a transport that dies mid-run must not pronounce a session
failed while the contract might already be green, because the worktree is
the state, not the process. (rpc’s agent-build path is the exception: it
has no shell contract to evaluate, only scenario results.)
Variants§
The worker could not be started, or never received the task — missing binary, unready CLI, pipes or prompt delivery that failed before handoff. Nothing was attempted, so the caller is free to try a different engine.
Cancelled
The user cancelled. Terminal, and explicitly NOT a fallback trigger: substituting another engine would run work the human just stopped.
Infrastructure
The machinery failed rather than the work: an invocation that died mid-run, or a backbone that stopped answering. Edits may be partially applied.
Configuration
The configured routing constraints leave no model eligible. No provider was invoked and no work was attempted, so this belongs to daemon configuration rather than the item being healed.
NeedsAuth
The run needs the human to sign in, and nobody did within the window.
Split out of Infrastructure because the two call for opposite
responses: an outage is not worth waiting on, whereas this resolves in
seconds if someone is asked. Folding them together is what made an
expired 15-minute token discard a 29-minute session — the run did not
need to end, it needed to ask. Edits survive in the worktree; re-running
after car auth login resumes from there.
Execution
The worker ran, reported its own error, and the checks are still red.
Verification
The worker ran clean and the checks are still red — the implementation was wrong, not the machinery.
BudgetExhausted
A loop hit its wall-clock ceiling and the next iteration was not admitted.
Distinct from Verification because a harness-imposed cut is not a task
loss, and a scorer needs to tell them apart: ab::ArmOutcome::scorable
exists precisely to keep “the harness stopped it” out of the scored
denominator, and the alternative to a typed cause is another compare
against error prose — which this enum was introduced to end.
It does NOT protect the recurrence/skill machinery, despite the obvious
guess: record_failure and record_recurrence run at the END of a red
iteration, while admission is denied at the START of the next one, so a
cut-off approach has already been written to skill memory as a failure
before this variant exists. Fixing that is a separate change.
Trait Implementations§
Source§impl Clone for LoopFailure
impl Clone for LoopFailure
impl Copy for LoopFailure
Source§impl Debug for LoopFailure
impl Debug for LoopFailure
impl Eq for LoopFailure
Source§impl PartialEq for LoopFailure
impl PartialEq for LoopFailure
impl StructuralPartialEq for LoopFailure
Auto Trait Implementations§
impl Freeze for LoopFailure
impl RefUnwindSafe for LoopFailure
impl Send for LoopFailure
impl Sync for LoopFailure
impl Unpin for LoopFailure
impl UnsafeUnpin for LoopFailure
impl UnwindSafe for LoopFailure
Blanket Implementations§
impl<T> Boilerplate for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more