Review triage economics: drop the finding quota, redraw patch vs defer, one ledger contract - #2805
Draft
pbean wants to merge 9 commits into
Draft
Review triage economics: drop the finding quota, redraw patch vs defer, one ledger contract#2805pbean wants to merge 9 commits into
pbean wants to merge 9 commits into
Conversation
…eview triage Blind Hunter: keep the what-is-missing second pass, drop the ten-finding floor and the never-stop-empty clause; every finding must name file, line, the input or state that reaches it, and the bad outcome. #2675 credited the question, not the count. step-04 Classify: carry forward logged verdicts on a loopback or follow-up pass; verify from the evidence a finding cites; a finding with no demonstrated outcome is false. Out-of-scope routes on merits, never to defer. patch is a locality test, not a size test; bad_spec is for design defects and doubt resolves to patch; defer is a five-part positive test and maybe-false groups are rejected, not deferred. Deferred items are deduplicated against the spec before append, summary is one clause of at most 100 characters, location and severity are required. Finalize: a follow-up pass recommends another only when it patched a high; step-01 sets followup_pass when it starts one. step-03: a test the change wrote must discriminate and a helper it introduced must be adopted at every touched site before done.
Lockstep with the bmad-build-auto change: both Blind Hunter layers drop
the ten-finding floor and the never-stop-empty clause and demand file,
line, reaching input, and bad outcome per finding.
step-04 Classify carries forward logged verdicts on a loopback or resumed
review, verifies from the cited evidence, treats a finding with no
demonstrated outcome as false, routes out-of-scope findings on their
merits, makes patch a locality test and defer a five-part positive test,
and resolves bad_spec doubt to patch. With a human present: a patch that
crosses a scope line or changes an agent-context rule is confirmed once,
all together, before it is applied, and a declined one becomes a defer
with the human's reason; intent_gap asks before reverting working code.
The ledger write sites read the file before appending and skip an entry
naming the same location and substance.
step-oneshot gains the out-of-scope guard, the spec-edit rejection, the
locality patch test, and the five-part defer test. step-03 adds the
discriminating-test and helper-adoption done bar. step-04 rewrites
{diff_file} after patches so step-05 reads it instead of rebuilding the
diff.
…code review Add references/deferred-work-entry.md — byte-identical in bmad-build and bmad-code-review, pinned by test-template-sync — as the single way to write the deferred-work ledger: read the whole file first; an open match on location and substance gets a seen-again line instead of a new entry; a closed match gets a new entry naming the closed id; entries are native ### DW-<n> blocks with origin, location, source_spec, severity, a two-sentence reason, and status: open; ids are minted from the highest existing and existing lines are never rewritten. The four bmad-build write sites and bmad-code-review's present step point at it; the "## Deferred from: code review" heading shape is gone. bmad-code-review: the Blind Hunter drops its ten-finding floor; step-01 loads the spec's prior review record and open ledger entries as triage input; step-03 carries forward verdicts for unchanged code, verifies from cited evidence, treats undemonstrated findings as false, routes out-of-scope findings on their merits, makes patch a locality test and defer a five-part test, and keeps an ambiguous fix at decision_needed even without a spec — the user is present. Story-file defer bullets carry their DW id. Docs: build-a-change describes the ledger contract, dedupe, and carry-forward and no longer suggests one fresh run per entry; review-a-change describes the five-way verdict instead of the retired dismiss and assign-severity steps. Renderer test asserts the reference is published and referenced from every write site.
…rior recommendation A dry run of the new rules against a real ledger found four places the text under-specified the route. At every lockstep site (build-auto and build step-04, build oneshot, code-review step-03): - the patch blast radius includes the code a test in the diff exercises, so a tests-only story can patch the code under test; - the verification-gap sentence also fires for a test that would pass under the wrong behavior it exists to catch, not only under a revert (step-03's done bar says the same); - a new record of a kind a format already carries is not a new external contract; a new field or file is; - a direct correction outside the diff names its file in the triage row. build-auto step-01 sets followup_pass only when the done spec's followup_review_recommended is true; a plain re-review is a first pass.
Restore the plan's reading of followup_pass: step-01 sets it whenever a done spec re-enters review, so any re-review runs the strict convergence rule — another pass only when this one patched a high. The previous commit gated it on the spec's followup_review_recommended, which let a manual re-review count as a first pass and recommend again on two patched mediums. followup_review_recommended itself is unchanged: it defaults to false.
…er tests only what it edits The first live run of the new step-04 (bmad-automator2, spec-dw-65-66-82) spent 20 of its 38 review minutes inside a fresh "Apply review patches" subagent: five minutes re-reading the tree before its first edit, then ablations, linters and the full suite that the step re-ran anyway. Tool wall time was under three minutes; the rest was generation. Step-04 asked for the step-03 implementer to be "re-engaged with its context intact" but never said what that meant, so the reviewer launched a new subagent with a prompt that opened "You previously implemented". Both step-04 files now say it: re-engagement is continuing the same subagent, addressed by the name or id its launch returned; a fresh launch is not re-engagement and discards the context the implementer holds; apply the patches yourself only when the implementer cannot be continued. The patch message also tells the patcher to run only the tests covering the files it edits and then return - the step owns the full verification. The shared sentence stays byte-identical between bmad-build and bmad-build-auto; the enumerated human-present differences are untouched.
Observed live (bmad-automator2, spec-dw-79-83-85-rearm-transaction-window): the follow-up review pass appended a fresh "## Review Triage Log" section at the end of the file instead of the one the spec already carried between the Spec Change Log and Design Notes. Both sections sat outside the intent contract, so nothing forbade writing to the first - the reviewer just did not look for it. A split log weakens the carried-row comparison on later passes, which reads "the" triage log. Both step-04 files now carry the same sentence at their triage-log write site: append to the section the spec already has - never create a second; if two exist, merge them into the earlier heading first, preserving every row. bmad-build hosts it on its one-row-per-finding bullet, bmad-build-auto on its append-format item; the sentence itself is byte-identical.
This branch took the quota out of the Blind Hunter prompt in three ship skills, four instances across their customize.toml files. references/lens-adversarial.md is a fifth copy of that same prompt and kept both lines, so a review run through the adversarial lens was still told to find at least ten issues and still read an empty list as a signal to keep hunting - the quota the rest of the branch removed, surviving on the one path that reaches it from bmad-review rather than from a ship skill. Upstream #2801 updated this lens directory alongside the other three copies of the edge-case hunter, so the lenses already move in lockstep with the ship prompts by convention. The lens now carries the same evidence bar, adapted rather than pasted: it addresses "the provided content" instead of CONTENT, and asks each finding to name where in the content it lives, the condition that triggers it, and the bad outcome that follows - its own location / trigger_condition / potential_consequence fields, not the file-and-line phrasing the diff-only copies use. The closing line is the shared one: an empty list is a valid result, and you do not fill it by lowering the evidence bar. guard_snippet was defined as "the concrete fix or improvement". Improvement is the exact category the evidence bar excludes, so a lens that no longer reports improvements should not offer a field that invites one; it now means the concrete fix. SKILL.md advertised the old contract in its lens summary and now describes the current one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every review layer in
bmad-build,bmad-build-autoandbmad-code-reviewran a Blind Hunter subagent whose prompt carried a floor: find at least ten issues, and never stop with an empty list. A reviewer that must produce ten items on a clean forty-line diff produces ten items. Triage then paid to verify each one, the spec's triage log recorded each one, and the ones triage could not disprove but did not want landed in the deferred-work ledger — where the next sweep read them back as work.The floor came from #2675, which credited the question — look for what is missing, not only what is wrong — and got implemented as a count. This branch keeps the question and drops the count, then redraws the line between
patchanddeferso that what the change caused gets fixed in the run instead of filed.What changed
Everything here is instruction text. The two step-04 review files stay in lockstep: shared sentences are byte-identical between
bmad-buildandbmad-build-auto, and only the human-present branches differ.1 — The hunter stops counting (
f8ee78e4,b8012952,24bc95c4,81229443)All five copies of the Blind Hunter prompt lose the ten-finding floor and the never-stop-empty clause, and gain an evidence bar: file, line, the input or state that reaches it, the bad outcome. The what-is-missing second pass survives intact. Four copies are the review layers in
bmad-build,bmad-build-autoandbmad-code-review; the fifth isreferences/lens-adversarial.mdinbmad-review, which states the same bar in its own field shape —location,trigger_condition,potential_consequencerather than file-and-line — and drops "or improvement" fromguard_snippet, the exact category the bar excludes. Thebmad-reviewSKILL.md lens summary no longer advertises the old ten-finding contract.2 — Triage verifies cheaper and routes wider (
f8ee78e4,b8012952,606f502d)carried, never re-verified, never patched or deferred twice.false. Triage does not build the claim on the reviewer's behalf.patchbecomes a locality test, not a size test — the blast radius is named explicitly (files in the diff, their tests, code a test in the diff exercises, direct callers of changed symbols, sibling sites of a pattern the diff fixed).deferbecomes a five-part positive test. All-maybe-falsegroups are rejected with what would settle them, not deferred. Out-of-scope routes on merits, never to defer.3 — One ledger contract (
24bc95c4)New
references/deferred-work-entry.md, byte-identical inbmad-buildandbmad-code-reviewand pinned bytest-template-sync, becomes the only way to writedeferred-work.md. Read the whole ledger first; an open match on location and substance gets aseen-again:line instead of a new entry; a closed match gets a new entry naming the closed id. Entries are### DW-<n>blocks; ids mint from the highest existing and nothing is renumbered. Five write sites point at it.4 — The loop stops paying twice (
2bafb3fb,3933e297,14215d54)## Review Triage Logsection per spec, ever — append to the one that exists; if two exist, merge into the earlier heading first, preserving every row.followup_passon every re-dispatch of adonespec; a follow-up recommends another pass only when it patched ahigh, and must name the unverified risk. Patch volume is never grounds.Docs and tests move with the skills:
build-a-changedescribes the ledger contract, dedupe and carry-forward;review-a-changedescribes the five-way verdict;test-template-syncgeneralises to a cross-skill vendored-copy check; the renderer test asserts the reference is published and referenced from every write site.Verification
A/B on the hunter prompt — 20 context-free runs
Old and new prompts against two diffs: a real one, and the same diff with exactly one line changed (a proof-of-work ternary inverted — a defect that turns nine tests red). Five runs per cell, all
claude-opus-5, model confirmed per transcript. Old prompt read fromgit show main:, new from the branch working tree.The planted defect was found in all ten runs that saw it. Under the old prompt it arrived first in a list of 16–22 items; under the new prompt it arrived alone, and four of five runs proved it by running the suite (nine tests red as written, 333 green with the operands swapped). The new prompt's clean-diff findings were real defects, not noise — one was independently rediscovered and landed later on the downstream repo's main. One run returned an empty list and said it had rejected stale-prose near-findings. Contamination screen clean: no reviewer read the planting script's body or cross-compared the diffs.
Finding quality — from the sweep specs' own triage logs
19 review passes under the old skill, 12 under the new, across ten stories.
highverdicts per passdeferVolume barely moved; composition flipped. The new skill surfaces and fixes more verified-real defects per pass while triage spends far less on refutation. Deferrals per story fell from ~7 to 0.5, and the follow-up pass converges — recommended at most once per story, every one resolving to
false.Session cost
Measured from the loop journal's
session-start/session-endpairs across 42 sessions:review-2): 6 sessions → 0 — median 23m01s each, 2.3 h and 3.6 M weighted tokens the new era never spent.3933e297cost 20 of that run's 38 review minutes; after the change, three sessions ran 3m55s, 5m12s and 9m21s, and 3 of 3 continued the live implementer rather than launching a patch agent.The saving is a session that stops being scheduled and a third of the review session's tokens — not a shorter session.
Limits
highrate fell 12 → 3. The counts are too small to separate from the stories, and these commits also changed whathighmeans (a vague "this is messy" with no named harm can no longer be graded at all), so part of that is definitional. When highs were present the new skill caught them — the rearm pass patched three verifiedhighfindings.falseverdict is a refutation by the same step these commits rewrote; nothing here audits those refutations independently.Testing
Full
npm testgreen, including the generalisedtest-template-sync(both vendored copies byte-identical to their sources) and the renderer assertion thatreferences/deferred-work-entry.mdis published into the snapshot and referenced from every ledger write site.