Skip to main content

Work

Struct Work 

Source
pub struct Work {
    pub calls: u32,
    pub failed: u32,
    pub refused: u32,
    pub verify_like: u32,
    pub shell_calls: u32,
    pub last: Option<Outcome>,
    pub in_flight: u32,
    pub denied: u32,
    pub run: u64,
}
Expand description

The run’s work so far, as of one tool call.

Cumulative, and only ever read as a difference between two points — the turn a step went in_progress and the turn it was marked done. That is why it is a handful of integers rather than a list: the span is arithmetic, and keeping the calls themselves would make this a second copy of the trace.

Stamped on ToolCtx by the loop, which does not know which tool cares — the taint and call_id precedent.

Fields§

§calls: u32

Every attempt, refusals included. A step that tried three times and was refused three times is blocked, not empty, and counting only what ran would report it as having done nothing.

§failed: u32§refused: u32§verify_like: u32

Successful calls that look like they verified something — a shell call whose command matches a small test-runner-shaped keyword list. See [looks_like_verification]. Folded here rather than kept as a raw trace for the same reason calls/failed/refused are: the span is arithmetic, and a tool asking “was there a check in this span” needs a count, not the calls themselves.

§shell_calls: u32

Every successful shell call, matched or not — the denominator verify_like needs to mean anything, so it has to count the same population verify_like draws from (Outcome::Ok only). A refused or failed shell call never ran, and counting it here would reopen exactly the false positive this field exists to close: on a read-only run (shell denied) or a surface where shell is not registered at all, that is precisely the shape a step’s one attempt takes. looks_like_verification can only recognise a check shaped as shell, so verify_like == 0 is ambiguous on its own: it is true both when a step’s checks used some other tool (an MCP test runner, cargo check-via-a-non-shell wrapper) and on any surface where shell is not even registered (a mail-only trigger, a tools:-narrowed skill, a read-only run) — cases where nothing could have set the counter regardless of what actually happened. See escalation_candidate’s UnverifiedClaim branch, which reads this alongside verify_like for exactly that reason.

§last: Option<Outcome>

How the most recent attempt ended. None before the run makes one.

§in_flight: u32

Calls approved in this turn whose results are not back yet — the siblings of the call reading this.

mecha executes a turn’s calls concurrently, so a model that does the work and ticks the box in one batch has that work invisible to the fold below. Without this the commonest efficient shape in the corpus would report as the null step, which is the false positive that would teach people to ignore the reading.

§denied: u32

Calls settled this turn without becoming approved work, whose target step is unknown to the harness. Named for the commonest case (the approver, a hook, the interlock) but not only that: an unknown or withheld tool name and a failed staging attempt settle the same way, without ever being denied by anyone.

Any of these is settled the instant it happens — unlike in_flight it is already in the trace — but the batch it happened in is exactly the shape in_flight exists for: a model ticking a step and reaching for the next one’s tool in the same turn. trace.push for one of these runs ahead of the calls it approved, so Work::of folds it in as the raw trace’s last entry regardless of which call it sat beside — blaming this step for an outcome that belongs to the next one. Carried alongside in_flight for the same reason: a batch holding either supports no finding at all.

§run: u64

Which run these counters belong to.

The trace is per run and a conversation is many runs. In chat and the TUI one submission is one run, so the counters restart at zero while the plan carries on — and a step started before the user last spoke would difference against a larger number, saturate to zero and report as the null step. That is the loudest reading this module has, firing on the commonest shape there is, which is how a check gets switched off. So a mark from another run is unmeasurable rather than empty, and Work::since says so by returning nothing.

Only inequality is ever read, which is what makes a process-local counter enough: two runs in one process must differ, and nothing compares this across processes or across a restart.

Implementations§

Source§

impl Work

Source

pub fn of(trace: &[ToolCallTrace]) -> Self

Fold the run’s trace so far.

Called once per turn, not once per call: the numbers are the same for every call in a batch, and the walk is over every call the run has made.

Source

pub fn with_in_flight(self, n: u32) -> Self

Source

pub fn with_denied(self, n: u32) -> Self

Source

pub fn in_run(self, run: u64) -> Self

Source

pub fn since( &self, start: Work, bookkeeping: u32, last: Option<Outcome>, ) -> Option<Span>

Work done since start, less bookkeeping calls the caller knows were its own.

The adjustment exists because the only caller is a tool that appears in its own count. A model that revises its plan three times mid-step would otherwise show three calls of “work” for a step where nothing happened — the null step masked by the bookkeeping that announced it. The argument for putting the subtraction here rather than in the loop is the loop’s own invariant: it stamps run state without learning which tool reads it, so “the plan tool is not work” is a judgement only the plan tool can make, and this is where the arithmetic it needs lives.

last is the caller’s to supply, and self.last is the wrong answer. self.last is the raw trace’s most recent entry, which is this same bookkeeping tool’s own call whenever one lands last — a successful revision masks an earlier failure (EndedOnFailure never fires), and a rejected one, which never reaches this method’s caller at all, reads as the step’s own failure (EndedOnFailure fires on work that landed). bookkeeping is a count and cannot say which position it occupied, so only a caller tracking its own calls as they happen — [crate::tool::todo::Tracked] does, incrementally — can name the outcome that actually belongs to the span.

None when start was taken in another run — see Work::run. An unmeasurable span supports no finding, which is doctor’s dash one mechanism over: could-not-look and nothing-happened are opposite answers.

Trait Implementations§

Source§

impl Clone for Work

Source§

fn clone(&self) -> Work

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Work

Source§

impl Debug for Work

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Work

Source§

fn default() -> Work

Returns the “default value” for a type. Read more
Source§

impl Eq for Work

Source§

impl PartialEq for Work

Source§

fn eq(&self, other: &Work) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Work

Auto Trait Implementations§

§

impl Freeze for Work

§

impl RefUnwindSafe for Work

§

impl Send for Work

§

impl Sync for Work

§

impl Unpin for Work

§

impl UnsafeUnpin for Work

§

impl UnwindSafe for Work

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more