Skip to content

A round that exhausts its admission envelope finishes normally instead of stopping #9

Description

@LucasWaki

Found by the adversarial review of the genesis-loop change set, 11 September 2026.
Open at 492f2a4.

What happens

wb_orchestrator/external_runtime.py:83 classifies a ledger refusal as
infra:weekly_budget when the message mentions "weekly" or "overrun", and
infra:budget otherwise — the per-round admission envelope case.

wb_orchestrator/orchestrator.py:880 stops the run on infra:weekly_budget
only. infra:budget never sets _stop_reason and never aborts. The
cost_ceiling branch above it cannot cover the gap either: it compares
self._spent, a sum of actual row.cost_usd, against the plan ceiling, and a
refused admission spends nothing, so _spent does not grow.

Every remaining attempt therefore records infra:budget, the round is marked
finished, and wb run exits 0.

What this does and does not corrupt

Verified against the merged tree before filing, because the original report was
stronger than what the code does:

  • measures.is_infrastructure matches any infra: prefix, so the cut attempts
    are excluded from the pass denominator, not counted as failures.
  • caveats.for_run emits a sentence naming how many attempts stopped with an
    execution issue.

So the published rates are not contaminated and the exclusion is disclosed. The
defect is the run's own state: a round truncated by admission exhaustion reads as
a completed round rather than a stopped one, and nothing marks it resumable. A
reader comparing two rounds cannot tell that one of them stopped early.

Fix

See the correction in the comments before starting. The obvious one-line
branch on infra:budget is wrong: that kind is also the pinned outcome when a
single attempt exhausts its own scope cap (tests/test_external_customer.py:119),
so stopping the round on it would kill a round on the first per-attempt cap hit.
The root cause is that _budget_failure collapses the ledger's distinct "run
budget exhausted" and "scope budget exhausted" into one kind. Split those first,
then stop the round on the envelope kind only, with its own stop reason so resume
can tell it from the weekly case — the weekly case waits for Monday,
the envelope case does not. A test covering the envelope path is the missing half;
the weekly path already has one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions