The panel

Nine reviewers. Nine lenses.

The default roster ships with atcr init as nine editable persona files. Each one reviews the same diff through a different focus and emits findings in the same pipe-delimited format — so the reconciler can cluster them by what they found, not who found it.

The embedded roster, synced from the atcr repo: bruce (generalist correctness), dax (test coverage and error-path), greta (algorithmic correctness), ingrid (idiomatic-style and conventions), kai (architecture and design), mira (production feasibility), otto (style, readability, and idiom), penny (performance and resource), sasha (security and injection).

bruce

Generalist correctness
  • Inverted conditions, off-by-one, wrong operator
  • Ignored returns and swallowed errors
  • Code that does not do what its name promises
Canonical finding
HIGH|store/cache.go:88|Get returns stale entry after Invalidate|delete the key inside the same lock as Invalidate|correctness|20

greta

Algorithmic correctness
  • Boundary conditions: first/last, empty, overflow
  • Loop termination, invariants, accumulators
  • Numeric overflow, float comparison, div-by-zero
Canonical finding
HIGH|merge/cluster.go:51|window comparison uses < so delta-3 lands outside the cluster|use <= for the inclusive ±3 window|correctness|10

kai

Architecture & design
  • Boundary violations and upward imports
  • Hidden coupling and shared mutable state
  • The cost of the next change
Canonical finding
MEDIUM|internal/report/render.go:30|renderer reads reconcile internals directly|consume the exported findings.json schema instead|correctness|25

mira

Production feasibility
  • Missing timeouts, unbounded retries
  • Partial failures and resource exhaustion
  • What the 3am pager sees
Canonical finding
HIGH|client/http.go:61|no timeout on provider call|derive a per-call context with a deadline from config|performance|15

otto

Readability & idiom
  • Names that mislead the next maintainer
  • Structure that hides intent
  • Fighting the language instead of using it
Canonical finding
MEDIUM|util/slug.go:14|sanitize() also truncates and lowercases|split into sanitize/truncate/lower or rename to normalizeSlug|style|10

dax

Tests & error paths
  • Untested failure branches
  • Vacuous assertions that prove nothing
  • Over-mocked fixtures hiding real behavior
Canonical finding
HIGH|parse/stream_test.go:1|no test feeds a malformed header|add a case with an unknown version header expecting a hard error|testing|20

ingrid

Idiomatic style & conventions
  • Swallowed errors and lost error wrapping
  • Leaked goroutines, missing cancellation
  • Interface abuse and stdlib reinvention
Canonical finding
HIGH|parse/num.go:14|error from strconv.Atoi discarded, bad input silently becomes 0|check and return the error instead of ignoring it|error|15

penny

Performance & resource
  • N+1 queries and unbatched calls
  • Unbounded caches and leaked resources
  • Accidental O(n²) and hot-path allocation
Canonical finding
HIGH|store/orders.go:88|query inside range loop issues one DB call per row (N+1)|batch the ids into a single WHERE id IN (...) query|n+1|25

sasha

Security & injection
  • Injection: SQL, command, template
  • Broken auth and predictable tokens
  • Leaked secrets and insecure defaults
Canonical finding
CRITICAL|store/users.go:42|user input concatenated into SQL query enables injection|use a parameterized query with placeholders|injection|20
Community personas

Beyond the built-in nine.

atcr personas install pulls community-contributed personas from the community registry into ~/.config/atcr/personas/ — they join the panel on your next review, no restart. Highlights:

Zero-egress, local-first panel

Three personas tuned for a local endpoint (Ollama / llama.cpp / vLLM), so no code ever leaves your hardware: gerald (secrets & data-egress, gemma3:27b), orson (duplication & repo-wide redundancy, qwen3:30b-a3b), and liam (invariants & state consistency, llama3.3:70b). Discover them with atcr personas search --provider local.

simon — the anti-slop lens

Hunts AI-generated bloat in a diff: comments that restate the code, abstractions wrapping one call site, defensive checks the type system already guarantees, and dead branches nothing can reach — flagged for deletion, not more structure.

Built one worth sharing? Tune a persona locally, run its fixture, and send it back as a pull request with atcr personas submit — it rides your own GitHub CLI session, no bot token.

The roster is yours. Personas are plain markdown files in .atcr/personas/. Edit a focus, change a model binding, drop one, or add your own — a Redis concurrency specialist for one PR, a protobuf reviewer for another. The reconciler does not care how many panelists there are; it only cares which findings overlap.

Why heterogeneous

Different models miss different things.

A panel of one model run nine times still has one model's blind spots. atcr binds personas to different models and providers on purpose: when two independent models — not two prompts — catch the same bug, that agreement is the confidence signal the reconciler scores.