Skip to content

Make the pr-review budget per-problem, not per-run #168

Description

@aaddrick

Depends on #166.

Problem

The PR review cap resets on every relaunch, so it is not a budget. An issue that burned three review rounds and landed in needs_human draws three more on the next run, with less context than the run that spent the first three, and this repeats indefinitely.

processIssue zeroes both halves of the state: settled: [] at :4821 and metrics at :4846. The process_pr path at :4871 then calls reviewAndMerge, whose loop starts at iter = 1 against MAX_PR_REVIEW_ITERATIONS (:4607).

Change

Seed ctx.metrics and ctx.settled from the durable block the dependency issue writes, and enforce the seeded budget: a resume arriving with the budget already spent goes straight to needs_human without running a review round.

Give that its own gate_findings disposition. "Resumed into an exhausted budget" is a different outcome from "spent three rounds here," and collapsing them into carried-unresolved hides the thing worth seeing. Add a Verification Gaps line so the batch PR explains why the issue was left alone rather than appearing to have been skipped for no reason.

Three constraints, each verified

:4609 is an assignment, not an increment. ctx.metrics.pr_review_iters = iter, with iter a fresh local starting at 1, clobbers any seeded value on the resumed run's first pass. The counter has to become a real accumulator before seeding it means anything.

Only adjudicated iterations count. reviewAndMerge bails at :4656 (if (!spec || !code) return fail(...)) before the tally at :4669, so the rule "increment where recordGateOutcome is called" already distinguishes a real adjudicated round from an agent death, with no new judgment required. Without this, a transient outage or API failure permanently consumes budget on a PR that was never oscillating, and resume gets worse at the job it exists for.

Note that this changes the meaning of computeFriction's pr_review_iters numerator (:2437) from rounds-entered to rounds-adjudicated. That is the intended meaning, but it is a behaviour change to an existing metric and belongs in the PR description.

Scope the carry honestly. pr_review_iters carries. approach_iters and plan_iters carry, but note in the PR that this is a no-op on the process_pr path, which jumps straight to reviewAndMerge and never runs those gates: it matters only on a resume_point: 'implement' resume. quality_iters does not carry, because it is a run-wide aggregate rather than a per-scope budget. test_iters does not carry, because the test loop is oracle-grounded and a reset budget there is not the same hazard as a reset judge budget.

Acceptance criteria

  • A second run against the same open PR resumes with the spent count intact and draws only the remaining rounds.
  • A resume arriving with the budget exhausted returns needs_human with zero review stages run, its own disposition recorded, and one Verification Gaps line.
  • An agent death during review does not consume budget. Add a test for this specifically.
  • A dead or failed preflight read does not silently grant a fresh budget; it is logged and distinguishable.
  • ctx.settled is populated on a resume and renders into both review prompts at :4619 and :4639.
  • A first run, with no prior block, is byte-identical to today.
  • node --test stays green. Extend tests/pr-review-gate.test.js, tests/friction.test.js, tests/gate-findings.test.js.

Documentation target

Document in CHANGELOG.md and in docs/architecture/gate-hygiene.md, adding its row to docs/architecture/index.md's file map if not already present.

Do NOT edit docs/architecture/pipeline.md, metrics.md, or failure-semantics.md. Their moved prose is hash-frozen by tests/architecture-provenance.test.js, and since the tech-docs stage runs at :4707, after the last test-loop execution, a frozen-prose edit surfaces only as a red CI check on the batch PR. New pages are authored text and are explicitly allowed; see docs/architecture/CLAUDE.md.

Metadata

Metadata

Assignees

Labels

gate-hygieneGate hygiene: findings, caps, and per-problem budgets (sequenced)

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions