From five opinions to one report.
Anyone can fan a diff out to five models and get five walls of prose. The hard part — and the product — is the merge. The reconciler is deterministic Go: same inputs, same output. Every stage writes a machine-parseable file you can diff and audit.
# the whole pipeline, one command $ atcr reconcile → discover 5 sources, 9 raw findings → cluster 9 findings → 4 clusters (by location) → dedupe 4 clusters → 3 canonical findings → score confidence by reviewer agreement ✓ wrote reconciled/{findings.txt, findings.json, report.md}
Start with the raw findings.
Each persona wrote its own findings.txt during
atcr review — pipe-delimited, one finding per line, no
coordination. Two reviewers independently flagged auth.go; one
flagged a SQL injection a second one disputes. The reconciler reads them all as plain
files on disk.
HIGH|auth.go:42|nil deref on empty session|guard session before .User|correctness|10 LOW|legacy.go:9|naming nit: tmp|rename to scratchBuf|style|5
HIGH|auth.go:43|nil pointer when session is nil|nil-check session|correctness|10
HIGH|auth.go:42|missing nil guard before .User|add guard|reliability|10 HIGH|users.go:88|possible SQL injection|parameterize the query|security|15
+ sources/kai, sources/otto — 9 raw findings across 5 sources. Illustrative data.
Group by where they point.
Findings are clustered by location — same file, line numbers within a small window — so
three reviewers describing the same bug on auth.go:42/:43
land in one cluster instead of three separate rows. Clustering is on position,
not wording.
greta HIGH auth.go:42 nil deref on empty session bruce HIGH auth.go:43 nil pointer when session is nil mira HIGH auth.go:42 missing nil guard before .User
Disagreement survives clustering. When a reviewer objects to a finding
instead of seconding it — bruce thinks users.go:88 is already
escaped upstream — the objection is recorded on the cluster, not silently dropped. It
becomes the difference between confirmed and
disputed later.
Collapse to one canonical finding.
Within a cluster, near-identical findings are merged by similarity into a single canonical row — the clearest problem statement and fix win, the contributing sources are remembered. Three lines become one, without losing who said what.
3 raw lines greta auth.go:42 nil deref... bruce auth.go:43 nil pointer... mira auth.go:42 missing guard...
session before accessing
.User
Confidence is how many independent models agreed.
The canonical findings are scored by reviewer agreement: a finding three independent models caught outranks one a single model raised. Objections pull a finding down to disputed. This is the signal a human reads first.
session before accessing
.User
One report, three formats.
The reconciled findings are written to disk in the three shapes downstream tools need —
a human-readable report.md, a parseable
findings.json, and the raw
findings.txt. The high-confidence items rose to the top
because more than one model independently caught them.
# Reconciled review — PR #402 5 sources · 9 raw → 4 clusters → 3 surfaced · suite v1.4.2 ## Confirmed HIGH auth.go:42 nil-pointer deref on empty session ●●●○○ 3/5 · 94% MED store.go:15 view layer reaches into db ●●○○○ 2/5 · 88% ## Disputed HIGH users.go:88 possible SQL injection (bruce objected) ●●⊘○○ 2/5 · 71%
Why deterministic matters. The models are not reproducible; the reconciler is. Clustering, dedupe, and scoring are pure Go — run them twice on the same sources and you get byte-identical output. The prompts orchestrate; the binary does everything that must be auditable. That is what makes a confidence score you can gate a merge on.