review: the re-review mode dial (full | scoped | flip-gated | fast)#246
review: the re-review mode dial (full | scoped | flip-gated | fast)#246jwbron wants to merge 6 commits into
Conversation
🦋 Changeset detectedLatest commit: 64f8115 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
be4202d to
6cee4a1
Compare
8e015ff to
813767c
Compare
|
Heads-up: jwbron/review-dispatch-tax (this PR's base) was rebuilt on the refreshed chain per the topology note on #243; its history was rewritten (old tip 8e015ff, new tip 813767c, content unchanged apart from prettier formatting). Reset or rebase local state onto origin/jwbron/review-dispatch-tax before continuing. The prettier/lint CI failures on the old chain are fixed on the new one. |
…parsing, deterministic depth lib, lifecycle evals The runs-per-PR cost lever. A per-repo 're-review' line in ROUTING (full | scoped | flip-gated | fast, default full) dials how much of the roster a repeat review runs. lib/rereview-mode.ts owns the deterministic half: content-hashed hunk signatures over the generated-stripped diff, the hidden review-body fingerprint stamp (survives cache eviction, dismiss-stale-approvals, and COMMENTED-only histories), the divergence tripwire that re-arms full review at unreviewed share >= 0.4, and the plan/stamp CLI. Adversarial lifecycle cases (rewrite-after-approval, sparse-PR-then-payload) ship as data in eval/lifecycle/ with a deterministic replay harness; counters gain costByRereviewDepth so the live A/B prices scoped against full. The review.md orchestrator wiring lands in a follow-up commit, on top of fold-in batch two's re-review accountability surface.
… accountability renderer The re-review mode dial's flip gate needs 'did the reconciler keep any blocking thread' as a number it can read from rereview.json, not a label judgment re-made at verdict time. Additive: the section rendering is unchanged.
… the orchestrator Step 1 stages the bot's prior reviews (every state, dismissed and comment-only included) for the stamp reader. Step 3 runs the rereview-mode plan CLI after the provenance CLI and maps each depth to its dispatch and staging: scoped overwrites full-stripped.diff with scoped.diff so the full roster reads only unseen hunks; flip-gated dispatches reconcile plus correctness over the scoped diff; fast is reconcile-only. Step 4 gains the flip rule: a reduced-depth run may flip a stamped REQUEST_CHANGES to APPROVE only at keptBlockingCount 0, and in flip-gated depth a validated blocking finding posts and blocks, vetoing the flip. Step 6 appends the hidden fingerprint stamp as the last line of every submitted review body; Steps 7 and 8 skip on reduced depths; Step 9 notes the stamp, not the cache, is the tripwire's authoritative fingerprint. The executed plan is copied into out/ so the run artifact records the depth the counters price.
…es for the newly-linted workflows tree The dispatch-tax trim brought workflows/review into eslint+prettier scope; format the mode-dial files and the two pre-existing violations in disciplines.test.ts and finding-schema.ts so CI lints clean.
b2308dd to
976b925
Compare
Review live A/BBaseline:
Improvements (candidate caught, baseline missed)
Adversarial hard gate: PASSED on the candidate arm. Single-run-stable rows: recall, verdict agreement, regressions, adversarial gate. Judge quality and noise are not: they jitter run-to-run at this corpus size, and a regressed reviewer can score HIGHER on judge quality (fewer, surer comments each read better). Recall against the labeled specs is the load-bearing metric. |
|
Eval pointer: the real (roster-level) evals for the mode dial live in #251, stacked on this PR. This PR carries the mechanism plus its deterministic layer only: the depth/tripwire replays in What actually measures reviewer behavior under each dial setting is in #251:
Reviewers judging whether the dial is measured before any repo flips a mode line: that evidence is #251's; both merge before any consumer can set |
… into jwbron/rereview-mode-dial
… into jwbron/rereview-mode-dial
The re-review mode dial: the runs-per-PR cost lever from the plan of record's "Re-review economics" section. Stacked on the eval stack (#232-#238) and fold-in batch two (#243-#245); the base should track the top of the batch-two stack as it grows.
Why
Two measured lifecycles of the same seeded PR paid the full 11-agent fan-out on every push, with per-run cost rising as threads accumulate (v1.3.1: $7.19 / $8.77 / $9.14; v1.4.0: $8.31 / $9.87 / $11.29, runs 29044383251 / 29045581242 / 29046928431 in Khan/webapp). The approval run is the most expensive while emitting the least. Both lifecycles also caught a fresh seeded defect on a re-review push that a reconcile-only fast path would have missed, which argues for
scopedas the default reduced depth.What
A per-repo mode line in
.github/aw/review/ROUTING:full: today's behavior, and the default. No consumer changes behavior until its repo sets a mode line.scoped: full roster, staged only the hunks new since the last fully-reviewed fingerprint; comments scoped to those hunks.flip-gated: reconcile plus the correctness pass over new hunks; a REQUEST_CHANGES to APPROVE flip is vetoed by that pass's validated blocking findings (the findings gate the flip instead of being discarded).fast: reconcile-only.Three guards, all deterministic (
workflows/review/lib/rereview-mode.ts):Named interactions handled by construction:
state, so a dismissed approval still anchors and still reads as an approval.Eval and measurement
The roster-level evals live in #251 (stacked on this PR): open-PR corpus cases with reconciler dispatch and flip-gate/duplicate scoring, the per-mode pricing sweep (
eval/rereview-sweep.ts), and the ported seeded lifecycle. This PR carries the deterministic layer:eval/lifecycle/):rewrite-after-approvalandsparse-pr-then-payload, each scored as "the tripwire re-armed and the payload got a full review", plus an economy control (fix-push-stays-cheap) scored as "the reduced path actually ran". Replayed deterministically ineval/lifecycle.test.tsunder all three reduced modes.out/rereview-plan.json;lib/counters.tsaggregatescostByRereviewDepth; the review-trial skill gains a ROUTING-override arms pattern (two arms at the same ref differing only in the mode line) and scores adversarial lifecycle pushes.enablelines are.Composition with batch two
Based on the top of the batch-two stack (#243 -> #244 -> #245 -> #247) so the mode dial's re-review paths compose with the re-review accountability rendering (#244) rather than race it: the accountability section stays the visible body surface; the fingerprint stamp is appended last as a hidden comment; and the flip gate reads
keptBlockingCount, a small additive field this PR adds to the accountability renderer'srereview.json, so "did the reconciler keep any blocking thread" is a number read at verdict time, not a label judgment re-made there. The orchestrator wiring (Step 1 prior-review staging, the Step 3 depth plan and per-depth dispatch/staging, the Step 4 flip rule, the Step 6 stamp, reduced-depth skips in Steps 7/8) is the last commit on the branch.Supersedes
Khan/frontend#13420 (frontend's consumer-side re-review stopgap, held on the old pin) is superseded by this: the dial lives in the shared workflow and frontend opts in with a single
re-reviewline in its ROUTING file once priced. Frontend is deliberately not touched here.