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 AST block) → 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 what they point at.
Findings are clustered by AST isomorphism — each finding is mapped to
the smallest AST block covering its line, and findings land in one cluster when their
covering blocks match — so three reviewers describing the same bug on
auth.go:42/:43 group together even
as line numbers drift between runs. Clustering is on structure, not wording.
Plain line proximity is only the fallback for languages with no parser; set
ATCR_DISABLE_AST_GROUPING to revert to it everywhere.
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.
The consensus filter is also trust-aware: reconcile reads each reviewer's scorecard history, so a singleton finding from a historically reliable reviewer survives without in-run corroboration, while one from a historically unreliable reviewer is demoted to LOW confidence. A reviewer with no history yet is treated as unmeasured, not untrusted.
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.