Phase 1 of the boris-routines-adoption plan. Implements ADR 0010 — this issue does not re-decide it.
Blocks every other phase. review:fanout is findings producer #1, so the first detector of any kind makes producer #2, and the fix action consumes exactly one file.
Why this is a correctness gate
plugins/review/skills/fanout/context/fix-pass-mode.md:3 — consume "the newest persisted findings file for the CURRENT branch". :7 takes the newest *.md by filename sort and stops. No merge, union, or multi-file handling exists anywhere in the fanout tree.
Two conforming producers on one branch means the later timestamp silently wins and the earlier producer's findings are never applied — no error, no warning, run reports success. A detector running after a full review shadows the entire review. This is the green-with-hidden-findings class docs/conventions/liveness-assertion/README.md:58 exists to prevent, and it fails silently rather than loudly.
Two changes, not one
1. The applied-plan record becomes a consumption ledger. fix-pass-mode.md:76 writes it only under --yes in a non-interactive session — "Interactive and headless-stop paths write no record". Any bound anchored on it is a no-op on the interactive path, so the merge set would grow without limit and re-inject findings that :95's required post-fix re-review already resolved. Write it on every apply path; source-findings: carries the full consumed set.
2. The locator becomes a merge set. All type: review-findings files whose branch: equals the current branch exactly, minus every file named by any source-findings: of a record whose own branch: also matches exactly. The branch filter binds both sides — :7 calls it load-bearing because the directory slug is lossy, and an unfiltered record from a slug-collided branch silently truncates the set.
Work items
Sanity checks
Related
- ADR 0010 (the decision this implements)
- Blocks: the detector-findings convention stub, and every detector phase
Phase 1 of the boris-routines-adoption plan. Implements ADR 0010 — this issue does not re-decide it.
Blocks every other phase.
review:fanoutis findings producer #1, so the first detector of any kind makes producer #2, and the fix action consumes exactly one file.Why this is a correctness gate
plugins/review/skills/fanout/context/fix-pass-mode.md:3— consume "the newest persisted findings file for the CURRENT branch".:7takes the newest*.mdby filename sort and stops. No merge, union, or multi-file handling exists anywhere in the fanout tree.Two conforming producers on one branch means the later timestamp silently wins and the earlier producer's findings are never applied — no error, no warning, run reports success. A detector running after a full review shadows the entire review. This is the green-with-hidden-findings class
docs/conventions/liveness-assertion/README.md:58exists to prevent, and it fails silently rather than loudly.Two changes, not one
1. The applied-plan record becomes a consumption ledger.
fix-pass-mode.md:76writes it only under--yesin a non-interactive session — "Interactive and headless-stop paths write no record". Any bound anchored on it is a no-op on the interactive path, so the merge set would grow without limit and re-inject findings that:95's required post-fix re-review already resolved. Write it on every apply path;source-findings:carries the full consumed set.2. The locator becomes a merge set. All
type: review-findingsfiles whosebranch:equals the current branch exactly, minus every file named by anysource-findings:of a record whose ownbranch:also matches exactly. The branch filter binds both sides —:7calls it load-bearing because the directory slug is lossy, and an unfiltered record from a slug-collided branch silently truncates the set.Work items
grep -rn "review-findings\|fix-pass-record\|source-findings" --include='*.md' --include='*.sh' --include='*.py' .— enumerate every parse path inside and outsideplugins/review/, record them before editing.source-findings:.Locationand identicalFindingtext; everything else stays distinct with its producer named inSurface(s). State in the doc why this is narrower than Stage 3's key —findings-normalization.md:77puts dedup at "Stage 3 Sonnet (semantic merge)" and:66orders "Minimize FALSE-MERGE over FALSE-SPLIT". The fix action runs no LLM stage, and the ±3-line bucket would merge distinct defects atfoo.ts:42andfoo.ts:44, dropping one remediation.## Unparsedby concatenation; union## Surfaceswith each producer named; report each consumed file'stier:rather than picking one.default-mode.md:77declares these required "to keep the report honest about coverage".> DEGRADED:blockquote above## Findings(run-everything-mode.md:163-168).memory_dirresolving outside the worktree serves several worktrees on different branches; the exact-branch:filter on both sides is what keeps that correct.plugins/review/.claude-plugin/plugin.json(0.19.0 to 0.20.0) and the matching CHANGELOG entry in the same PR.Sanity checks
scripts/check-changelog-parity.sh --check-bump origin/mainexits 0. (Bare invocation exits 2 — usage.)scripts/check-changed-skills.sh origin/mainexits 0. Editingcontext/fix-pass-mode.mdmakesfanouta changed skill —check-changed-skills.sh:52-56maps any path underplugins/<p>/skills/<s>/to the skill dir — so the full static gate runs; only--require-evalsis SKILL.md-scoped.grep -c "fix-pass-record" plugins/review/skills/fanout/context/fix-pass-mode.md>= 3.branch:differs from the current branch excludes nothing.foo.ts:42andfoo.ts:44with differentFindingtext both survive (false-merge guard).Related