Skip to content

feat(resolve): collapse duplicate cross-reviewer issues via DUPLICATE triage verdict - #307

Open
dean0x wants to merge 6 commits into
mainfrom
feat/resolve-duplicate-verdicts
Open

feat(resolve): collapse duplicate cross-reviewer issues via DUPLICATE triage verdict#307
dean0x wants to merge 6 commits into
mainfrom
feat/resolve-duplicate-verdicts

Conversation

@dean0x

@dean0x dean0x commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Summary

The same underlying defect flagged by 3 Review agents was counted as 3 issues — fixed once, reported as "Total Issues 3 / Fixed 3". This inflated all Statistics rows and skewed the fp_ratio convergence formula in /code-review (which divides false-positive count by fp_count + fixed_count + deferred_count). The fix is a DUPLICATE triage verdict that collapses cross-reviewer duplicates before the disposition matrix runs.

Changes

src/assets/agents/triage.md — duplicate grouping pre-pass added before the blast-radius matrix (not as a matrix row — this is a relation between issues, not a priority). Groups issues by same root cause, selects the most complete report as primary, applies the matrix only to the primary. Non-primary members get DUPLICATE with duplicate_of: <primary-id> (non-chainable). Security gate applies to the whole group. Kept minimal (avoids PF-026).

src/assets/commands/resolve.mds — DUPLICATE added to every verdict-enumeration site per PF-024 (spawn↔op seam):

  • Phase 2: parsed verdict list, completeness assertion (DUPLICATE is valid; missing/chained duplicate_of → Triage failure with retry-then-abort)
  • Phase 3: DUPLICATE issues are never dispatched to Code agents
  • Phase 9 (manage-debt): DUPLICATE issues never create their own debt tickets
  • Phase 9b-1 (THREAD_MAP prep): ext-{N} matched to a DUPLICATE maps to the primary's verdict/verification status
  • Phase 10 (display): | Duplicates Collapsed | {n} | row added to Results table
  • Output artifact: Statistics counts unique issues only; | Duplicates Collapsed | {n} | row added; ## Duplicates section added with | Issue | Duplicate Of | File:Line | table
  • Architecture block and Edge Cases table updated

tests/build-mds.test.ts — §16b guards (RED→GREEN TDD) pin DUPLICATE, duplicate_of, | Duplicates Collapsed | , and ## Duplicates in compiled dist/commands/resolve.md.

Parser-Contract Safety

All existing Statistics row labels (Fixed, False Positive, Deferred) and section headings (## Fixed Issues, ## False Positives) are byte-stable — labels unchanged, column layouts unchanged. The Duplicates Collapsed row is strictly additive and the /code-review convergence parser ignores it. All parser-read rows now count unique (non-DUPLICATE) issues, which de-skews fp_ratio without any change to the formula or the parser.

Reviewer Focus Areas

  • Completeness: every verdict-enumeration site in resolve.mds should name DUPLICATE (grepped for FIX_NOW/FALSE_POSITIVE/BY_DESIGN/FIX_SEPARATE/TECH_DEBT/ESCALATED as anchor points)
  • Non-chainability: duplicate_of must reference a non-DUPLICATE id — enforced in the completeness assertion and in triage.md pre-pass rule 4
  • Security gate group semantics: triage.md pre-pass rule 3 — if ANY group member is a security finding, the primary goes through the Security Gate
  • Parser safety: ## Duplicates is additive; existing ## Fixed Issues / ## False Positives column layouts are unchanged
  • PF-024: caller (resolve.mds) maps ext-{N} to primary's verdict client-side; git.md operation contracts untouched

dean0x and others added 6 commits August 28, 2026 01:41
… triage verdict

Add a DUPLICATE verdict to the /resolve pipeline so the same underlying defect
flagged by multiple Review agents counts as one issue in resolution-summary.md,
de-skewing fp_ratio convergence math in code-review without any parser change.

Changes:
- triage.md: duplicate grouping pre-pass before the disposition matrix; DUPLICATE
  verdict section in output; duplicate_of attribute (non-chainable); security gate
  applies to the whole group (applies ADR-006, avoids PF-026)
- resolve.mds: DUPLICATE added to every verdict-enumeration site — Phase 2 parse
  list, completeness assertion, Phase 3 batch exclusion, Phase 9 manage-debt note,
  Phase 9b-1 THREAD_MAP mapping, Phase 10 Results table, Output artifact Statistics
  (Duplicates Collapsed row + ## Duplicates section), Architecture block, Edge Cases
  (avoids PF-024 spawn↔op seam; additive-only per ADR-006)
- tests/build-mds.test.ts: §16b guards pin DUPLICATE, duplicate_of,
  "| Duplicates Collapsed | ", and "## Duplicates" in compiled resolve.md (PF-018)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove filler word ("immediately") from triage.md pre-pass rule.
In resolve.mds: simplify the completeness-invariant sentence for DUPLICATE
entries, drop the redundant "excluded from all batches" clause (implied by
"never dispatched"), and condense the PF-024 parenthetical in Phase 9b-1.
No behaviour or contract change — all §16b parser-contract literals preserved.
Self-review fixes on the DUPLICATE triage verdict:

- triage.md: responsibility 3 said "apply the matrix" to every issue,
  contradicting the pre-pass ("matrix applies to primaries only") and
  omitting DUPLICATE from ledger completeness. Reworded in place.
- triage.md: a group mixing security and non-security findings could
  elect the non-security report as primary (it may be the "most specific
  and complete"), handing the Code agent a style description for a
  security defect. Security member is now always the primary; the
  whole-group Security Gate remains the backstop.
- resolve.mds: Phase 5 never stated that DUPLICATE rows are exclusive to
  ## Duplicates. Without it, a duplicate of a FALSE_POSITIVE primary
  could be listed in ## False Positives while the unique-only Statistics
  row counted just the primary -- section and row disagreeing, and
  git.md manage-debt reading duplicates out of ## Fix Separately.
- resolve.mds: the Statistics note swept `Total Issues` into the
  unique-only rule, so Total would have excluded collapsed duplicates
  and stopped equalling the sum of its rows. Total now counts every
  triaged issue; all other rows stay unique-only.
- resolve.mds: completeness assertion demanded a `duplicate_of` field
  while the ledger emits a `Duplicate Of` column -- an enum/field-name
  mismatch across the spawn/op seam whose failure mode is a hard abort
  (avoids PF-024). Assertion now names the ledger surface.
- resolve.mds: Triage spawn directive named only the matrix; now names
  the collapse-then-matrix order it parses a DUPLICATE bucket from.
- tests: new tests/resolve/duplicate-verdict.test.ts pins the producer
  side of the seam (build-mds §16b pinned only the caller side, so the
  agent could stop emitting the bucket with every guard green).

Byte-stable parser contract untouched: Fixed / False Positive /
Deferred row labels and ## Fixed Issues / ## False Positives column
layouts are unchanged (applies ADR-006, additive-only).
…ambiguate statistics note

- docs/commands.md: append DUPLICATE to the disposition enumeration (step 1)
  and note in step 7 that duplicate cross-reviewer reports are collapsed so
  Statistics counts reflect unique issues
- CHANGELOG.md: add ### Changed entry under [Unreleased] describing the new
  DUPLICATE verdict and its effect on resolution-summary counts
- resolve.mds: reword the ambiguous Statistics note — "every other row above
  Duplicates Collapsed" → "every row between Total Issues and Duplicates
  Collapsed" to make clear that Total Issues itself is not a unique-only count

Co-Authored-By: Claude <noreply@anthropic.com>
…TE edge case

In triage.md Duplicate Grouping Pre-Pass step 2, add a parenthetical
tying 'security member' to the Security Gate so the term is grounded on
first use in the pre-pass.

In resolve.mds Edge Cases table, extend the DUPLICATE-without-duplicate_of
row label to also name the chained-to-another-DUPLICATE case, matching the
Phase 2 completeness-assertion prose at ~line 189.

Co-Authored-By: Claude <noreply@anthropic.com>
…t-name guard

'cross-reviewer' contains 'reviewer' which trips the case-insensitive retired-name
scan for the pre-PR-#253 'Reviewer' agent name. Reword to 'multiple Review agents'
which carries the same meaning and passes the guard.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant