| description | Language-agnostic code review with adversarial challenge |
|---|
Language-agnostic code review. Takes one or more files, discovers companion artifacts, and runs a structured analysis pipeline. Sub-agents read all code and perform all inspection. The main context orchestrates, filters, and renders the report. Raw code never enters the main context.
Noise philosophy: The tool should go out of its way not to find anything. Every finding must justify its existence. The default posture is: this code is fine until proven otherwise with strong evidence. A clean review with zero findings is a valid and desirable outcome, not a failure of the tool.
\newpage
flowchart TD
Paths --> Inventory
Inventory --> Curate
Curate --> Analyze
Analyze --> Solo
Analyze --> Batch
Solo --> Findings
Batch --> Findings
Analyze --> Challenge
Findings --> Challenge
Challenge --> Tiebreak
Curate --> Synthesize
Analyze --> Synthesize
Tiebreak --> Synthesize
Synthesize --> Report
Tiebreak --> Report
\newpage
Raw source code NEVER enters the main context. All code reading, all inspection, all per-file analysis happens inside sub-agents. The main context receives only structured JSON records. Non-negotiable.
Runs in main context. No LLM. Deterministic.
Input: User-provided paths.
Actions:
- Expand directories (exclude build artifacts, vendor, generated).
- Attach
companion_pathper discovery heuristics (header/impl/test pairs).
Discovery heuristics by extension:
.hpp/.h--> look for.cpp/.cc/.cwith the same stem, same directory orsrc/.cpp/.cc/.c--> look for.hpp/.hwith the same stem, same directory orinclude/.py--> look fortest_{stem}.pyor{stem}_test.pyin the same directory ortests/.ts/.tsx--> look for{stem}.test.ts,{stem}.spec.ts,{stem}.test.tsx.java--> look for{Stem}Test.javain the same package or a parallel test tree.rs--> look formod.rsin the same directory, ortests/{stem}.rs
General fallback: same stem, related extensions or test prefix/suffix patterns. If nothing is found, proceed without a companion.
Output: DiscoveryResult
review_roots: array of stringfile_entries[]: array of{ path, companion_path }
Inform the user: "[N] files under review, [M] companions discovered."
One sub-agent per file. Classify and orient.
For each file_entries[] path, spawn one sub-agent. Inject fixed Step 1 prompt + { path, companion_path }. Sub-agent reads file (and companion if present) from disk.
Return: Step1Record
file_path: stringprimary_kind: string, one ofimplementation,header_or_interface,test_code,test_fixture_or_data,documentation,configuration,generated_or_vendor,unknownreview_as: string, one ofcode_review,documentation_review,fixture_review,configuration_review,skipinclude_in_pipeline: boolean -falsemeans all later steps skip this pathlanguage: string (e.g.cpp,python,typescript,rust,markdown,other)approx_line_count: integer or nullappearance: string, 1-2 sentences - structural impression (e.g. "200-line module with a single class and decorator-heavy factory methods")primary_entrypoints: array of string, at most 5external_touchpoints: array of string, at most 5concurrency_present: boolean
Validation: Reject if JSON invalid; arrays > 5 items; unknown enums; appearance > 600 chars.
Main appends validated records to step1_results[].
One sub-agent per file. Builds the file's story and enumerates its functions in a single read.
When: For each path where include_in_pipeline is true. Adapted per review_as mode.
Input: Step1Record for this file + companion_path from Step 0. Sub-agent reads file + companion from disk.
Return: FileAnalysis
file_path: stringbrutal_one_line: string, one sentence - what this file is for / what it must not breakinvariants: array of string, at most 5 - key invariants or contracts the file maintainsrisk_flags: array of string, at most 3file_level_findings[]: array of objects (from file-level rules F1-F3), each:rule_id: string (F1,F2, orF3)confidence: string, one ofhigh,medium,lowpriority: string, one ofmust_fix,should_fix,nice_to_havelocation: string - file path + line or range or "file-wide"action: string, one sentencerationale: string, one sentence
functions[]: array of objects - populated forcode_reviewandtest_codefiles; empty array for docs/fixtures/config. Each:qualified_name: stringkind: string (function, method, static_method, constructor, destructor, lambda, macro, etc.)visibility: string (public,internal,private)role_in_file: string, one line aligned tobrutal_one_linestart_line: integersolo_review: boolean -trueif the function needs its own dedicated sub-agent;falseif it can be batched. Marktruefor functions with complex control flow, significant state management, concurrency, or central responsibility. Short accessors, simple constructors, trivial wrappers, and straightforward utilities should befalse.
Main stores one FileAnalysis per file. Function inventory is not printed in the final report.
Fresh sub-agents. 8-rule checklist. Default posture: this function is fine.
Batching strategy: Main partitions each file's functions[] using solo_review:
- Solo (
solo_review: true): one fresh sub-agent per function. - Batch (
solo_review: false): grouped into batches of at most 8, one fresh sub-agent per batch.
-
Spawn a new sub-agent (no carryover).
-
Inject function context packet (assembled by main):
file_pathandcompanion_path(Step 0)brutal_one_line,invariants,risk_flags(Step 2)concurrency_present(Step 1)role_in_file,function_qualified_name,kind,visibility,start_line(Step 2 function row)
-
Sub-agent reads file and companion (if present) from disk. The companion is needed for A2 contract fidelity.
-
Run 8-rule scan, fill verdict slots.
-
Self-challenge (mandatory): After filling all 8 verdicts, execute a final pass:
"Re-read each non-clean verdict. For each, ask: would a skeptical senior engineer who knows this codebase accept this finding, or would they say 'that is not a real problem'? If you cannot state in one sentence what breaks or degrades because of this issue, change the verdict to clean. Style preferences that do not affect correctness, maintainability, or safety must be clean, not advisory."
Revise verdicts in place before returning JSON.
-
Return
PerFunctionReview:file_path: stringfunction_qualified_name: stringstart_line: integerverdicts[]: array of 8 objects (one per rule A1-A8), each:rule_id: stringverdict: string, one ofclean,advisory,flag,naconfidence: string, one ofhigh,medium,lowline: integer or null (required foradvisoryandflag)action: string or null - for non-clean: one sentence; else nullrationale: string or null - for non-clean: one sentence (what breaks or degrades); forclean: one sentence confirming; forna: one sentence whypriority: string or null - foradvisory: one ofshould_fix,nice_to_have; forflag: null (main assignsmust_fix); forclean/na: null
- Spawn a new sub-agent (no carryover).
- Inject batch context packet:
file_pathandcompanion_path(Step 0)brutal_one_line,invariants,risk_flags(Step 2)concurrency_present(Step 1)functions[]: array of{ function_qualified_name, kind, visibility, role_in_file, start_line }for all functions in this batch
- Sub-agent reads file and companion from disk.
- Run 8-rule scan for each function in the batch.
- Self-challenge (same prompt as solo).
- Return
BatchReview:file_path: stringreviews[]: array of objects, one per function in the batch (same order as input), each:function_qualified_name: stringstart_line: integerverdicts[]: array of 8 objects (same schema as solo)
After all Step 3 sub-agents return, main verifies:
expected = { f.qualified_name for f in FileAnalysis.functions }
reviewed = { r.function_qualified_name for r in all solo + batch outputs }
missing = expected - reviewed
If missing is non-empty, re-run for the missing functions (solo). Deterministic set comparison.
Main normalizes all outputs: unpack BatchReview.reviews[] into individual PerFunctionReview records. Downstream steps see a flat PerFunctionReview[] per file.
- Full
Step1Record(onlyconcurrency_presentforwarded) - Full
FileAnalysis(only breadcrumb fields + target function rows) - Any other file's data
One fresh sub-agent per file. Adversarial pass - tries to disqualify every non-clean finding from Steps 2 and 3.
When: For each file with at least one non-clean finding. If all-clean, skip.
Input:
file_pathandcompanion_path(sub-agent reads from disk)brutal_one_line(Step 2)invariants(Step 2, at most 5 strings)- Only the non-clean findings for this file: array of
{ rule_id, function_qualified_name, line, action, rationale, confidence, priority } - Not the full Step 1/2 records
Challenger prompt:
"You are a skeptical senior engineer. Your job is to defend this code against the findings below. For each finding, read the code at the cited location and determine:
- Is the finding factually correct? Does the code actually do what the finding claims? If the finding cites the wrong line, misreads the logic, or describes behavior that does not exist, disqualify it.
- Is it actually a problem? Even if factually correct, does it matter? If the pattern is idiomatic, intentional, or has no realistic negative consequence, disqualify it.
- Is the severity right? If the finding survives but the severity is too high, downgrade it.
You may NOT add new findings. You may only disqualify or downgrade existing ones. If every finding is valid, say so - do not invent objections to seem useful."
Return: ChallengeResult
file_path: stringchallenges[]: array of objects, one per input finding (same order), each:rule_id: stringfunction_qualified_name: string or nullline: integersurvived: booleanrevised_priority: string or null - if survived but downgraded: new priority; null if unchanged or disqualifiedchallenge_reason: string, one sentence
Main merges results. Disqualified findings dropped. Downgraded findings get priority updated.
Applied in main after Step 4. Uniform across all surviving findings from Steps 2 and 3:
priority: must_fix+confidence: low--> downgrade toshould_fixpriority: should_fix+confidence: low--> droppriority: nice_to_have+confidence: low--> dropconfidence: highormedium--> no change
Findings list only contains items that survived all three filters (self-challenge, challenger, tiebreaker).
One sub-agent. Cross-file analysis from the full pipeline output. Runs after the challenge pass; only sees surviving findings. This is where the pipeline's investment pays off. Small codebase = concise output. Large library = deep output. Do not compress to fit a template.
Input:
- All
Step1Records (classification, entrypoints, touchpoints, appearance) - All
FileAnalysisrecords (brutal one-liners, invariants, risk flags, function inventories) - All surviving
PerFunctionReviewfindings (post-challenge) - All surviving
FileAnalysis.file_level_findings[](post-challenge) - File paths + companion paths (Step 0)
Do not pre-summarize. Let the sub-agent do the compression.
Return: SynthesisResult
verdict_one_line: string - brutal one-line verdictexecutive_summary: string - 1-2 paragraphsfile_groups[]: array of objects - files clustered by responsibility or subsystem, each:group_name: string (e.g. "Parsing layer", "HTTP handlers", "Test suite")group_description: string, 1-3 sentencesfile_paths[]: array of string
file_profiles[]: array of objects, one per reviewed file, each:file_path: stringprofile: string, 1 sentence to 1 paragraph - scaled to how much there is to say. Short for clean files, longer for files with significant findings or complex responsibilities.
cross_cutting_analysis: string - unbounded prose covering module boundaries, cross-file duplication, naming coherence, responsibility leakage. Scales with the codebase.cross_file_findings[]: array of objects (global rules G1-G4), each:rule_id: stringconfidence: string, one ofhigh,medium,lowpriority: string, one ofmust_fix,should_fix,nice_to_havelocations[]: array of string - file:line referencesaction: string, one sentencerationale: string, one sentence
Cross-file findings intentionally skip the adversarial challenge. The synthesis sub-agent already works from filtered data. The confidence tiebreaker in Step 6 still applies.
Main context renders user-visible markdown. Apply confidence tiebreaker to Step 5 cross-file findings (same rules as Step 4 tiebreaker).
Output path: User-specified, or code-review-{scope-slug}.md where {scope-slug} is derived from the review roots (directory name or primary file stem). The report is output. If a report with this name already exists, increment the version suffix: -v2, -v3, etc.
# Code Review: [name]
- **Date:** [date]
- **Model:** [model]
- **Scope:** [review_roots from Step 0]
[Brutal one-line verdict from Step 5]
## Executive Summary
[1-2 paragraphs from SynthesisResult.executive_summary.
What the code is, what the review found, what deserves attention.
Read this if you read nothing else.]
## Codebase Profile
### [Group Name]
[group_description. List of files in this group.]
(Skip file groups if codebase is 2-3 files and grouping adds nothing.)
### [filename]
[Per-file profile from SynthesisResult.file_profiles[].
One sentence for clean utility files.
Full paragraph for complex modules with findings.]
...
## Cross-cutting Analysis
[Unbounded prose from SynthesisResult.cross_cutting_analysis.
Module boundaries, duplication, naming, responsibility leakage.
Let it grow to match the codebase.]
## Findings
### Must fix
1. `src/parse.cpp:142` - add bounds check before array access
(unchecked index into user-supplied vector)
2. `lib/auth.py:87` - validate token expiry before granting session
(expired tokens currently accepted)
### Should fix
3. `src/render.py:55` - extract DB query from pure formatting function
(mixed IO and presentation)
### Nice to have
4. `src/render.py:112` - reduce nesting depth
(currently 5 levels deep in conditional chain)
N files / M functions reviewed clean.
Each item: numbered, file:line - action (rationale). One line per finding, blank line between findings.
flagverdict --> must fixadvisorywithshould_fixpriority --> should fixadvisorywithnice_to_havepriority --> nice to havecleanverdicts omitted
Multi-location findings (cross-file, rules G1-G4): comma-separate locations.
5. `src/parse.cpp:42`, `lib/util.py:88` - extract shared validation
into one module (same bounds-check logic duplicated)
If zero findings survive: "No findings. The reviewed code is clean."
Triple duty - each finding line serves as:
- Report finding - reader sees what's wrong, where, and why
- Human to-do - developer works down the list
- Machine to-do - LLM gets file, line, instruction, and reasoning
Injected into every Step 3 sub-agent. 8 rules, each with Scan, Clean bar, and Flag vs Advisory.
Scan:
- Trace every branch - right thing, right type, boundary handled?
- Enumerate loop bounds - correct at 0, 1, N-1, N, MAX?
- List every nullable/optional value - guarded before use?
- Check operator precedence in compound expressions.
- Enumerate return paths - same type/shape? Any path that forgets to return?
Clean bar: No plausible logic error in control flow, boundaries, or null handling. Flag: Likely wrong behavior at runtime. Advisory: Fragile pattern that works today but breaks on plausible input change.
Scan:
- Read name, doc comment,
role_in_file- what should this function do? - Read body - does it actually do that, and only that?
- Preconditions validated or asserted at entry?
- Does it mutate arguments the caller would not expect?
- Side effects not visible from signature?
Clean bar: Behavior matches name, docs, stated role; no hidden mutations or effects. Flag: Function contradicts its name/docs, or silently mutates caller state. Advisory: Preconditions not enforced but documented; minor name drift.
Scan:
- Describe what it does in one sentence without "and" - if you cannot, it does too much.
- Count parameters - more than 4 is a smell.
- Boolean "mode" parameter creating two functions in one body?
- Does the name match what the code does?
Clean bar: One job; name matches behavior; tight parameter list. Flag: Two unrelated jobs, or name actively misleads. Advisory: High parameter count, or mild name drift.
Scan:
- List every acquired resource.
- Release on every exit path (early returns, exceptions, error branches)?
- RAII /
with/deferin use, or manual? - Resource escapes without documented ownership transfer?
Clean bar: Every resource has guaranteed release on all exit branches. Flag: Leak on a reachable path. Advisory: Manual cleanup works but guard pattern would be safer.
Scan:
- List every fallible call.
- Error checked? Propagated? Or silently ignored?
- Empty catch /
except: pass/ ignored return code? - Error types appropriate granularity?
Clean bar: Every fallible call has an explicit error path; no silent swallowing. Flag: Error silently swallowed on a path affecting correctness or data integrity. Advisory: Error handled but with context loss.
Scan:
- Nesting depth > 3?
- Function length > ~40 lines?
- Local names convey intent?
- Unnecessary indirection?
Clean bar: Readable top-to-bottom; names convey intent; nesting shallow. Flag: N/A (readability alone is never "likely bug"). Advisory: Specific improvement with location.
Skip when concurrency_present is false.
Scan:
- Shared mutable state without synchronization?
- Lock ordering consistent?
- Atomic operation assumes stronger ordering than documented?
- Captured mutable reference across await point?
Clean bar: No unprotected shared state; consistent lock ordering. Flag: Race condition or deadlock on reachable path. Advisory: Synchronization present but coarser than necessary.
Scan:
- Testable with just parameters and return value, or requires mocking globals/DB/network/filesystem/clock?
- Mixes I/O with pure computation in same body?
- Hidden dependency (global, singleton, env var,
Date.now(),random())? - Would a unit test require building a mini production environment?
Clean bar: Testable by supplying inputs and checking outputs; dependencies explicit. Flag: N/A (testability alone is never "likely bug" - if an untestable path is also wrong, A1 or A5 catches the bug). Advisory: Mixed I/O and logic; hidden dependency; complex mock setup required.
Run inside Step 2 sub-agent. Emit into FileAnalysis.file_level_findings[].
Scan:
- List public functions/classes/types - does each have a doc comment?
- If some have doc comments and others don't, that's inconsistent.
- For existing doc comments - do they describe current behavior or stale behavior?
- Parameter names in docs match actual parameter names?
Clean bar: Public surface is uniformly documented (all or none); existing docs match current code. Flag: Doc comment describes behavior opposite to what the code does (misleads callers). Advisory: Partial coverage (some public APIs documented, others not); minor parameter name drift.
Scan:
- Indentation style consistent within file?
- If companion exists, same conventions (brace placement, line length, import ordering)?
- Trailing whitespace, mixed tabs/spaces, inconsistent blank line patterns?
Clean bar: Consistent internal style; no jarring divergence from companion. Flag: N/A (formatting alone is never "likely bug"). Advisory: Inconsistent indentation, mixed conventions, or divergence from companion style.
Scan:
- Any two functions with near-identical logic (same structure, same operations, different names/parameters)?
- Repeated boilerplate that could be a shared helper or macro?
- Copy-paste patterns with minor variations?
Clean bar: No repeated logic blocks that could be a single helper. Flag: N/A (duplication alone is never "likely bug"). Advisory: Specific duplicated pattern with locations; suggest extraction target.
Run during synthesis. Emit into SynthesisResult.cross_file_findings[].
Scan:
- Same logic, algorithm, or validation repeated in multiple files?
- Shared constants defined independently in separate files?
- Utility functions reimplemented instead of imported from a common module?
Clean bar: No logic or constant duplicated across file boundaries. Flag: Duplicated validation or business logic where a bug fix in one copy would need to be applied to all copies. Advisory: Duplicated utility logic or constants that could be consolidated.
Scan:
- Same concept called different names in different files (e.g.
user_idvsuserIdvsuid)? - Same name used for different concepts across files?
- Public API naming conventions consistent across modules?
Clean bar: Same concept, same name everywhere; no naming collisions. Flag: Same name means different things in different modules (collision that misleads). Advisory: Inconsistent casing or abbreviation conventions across boundaries.
Scan:
- Are internal types or implementation details exposed across module boundaries?
- Interface width - do callers need to know more than they should?
- Coupling to concrete types where an interface/abstraction would be appropriate?
- Easy to use correctly, hard to use incorrectly?
Clean bar: Clean boundaries; callers depend on contracts not implementations. Flag: Internal mutation exposed without documented ownership transfer; API that silently does the wrong thing on plausible inputs. Advisory: Overly wide interface; unnecessary coupling to internals; API that works but requires caller to know implementation details.
Scan:
- Invariant maintained partly in module A and partly in module B?
- File doing work that belongs in a different file's stated responsibility?
- Mixed abstraction levels at module boundaries (high-level orchestration mixed with low-level I/O)?
Clean bar: Each module owns its invariants completely; responsibilities don't split across boundaries. Flag: Split invariant where a change in one module silently breaks the other. Advisory: Mild responsibility overlap; work that would be cleaner in a different module.
Save output after each complete section. Always save output BEFORE marking plan items done. On resumption: read the plan and the last section of the output file. Continue from where output ends. Never rewrite prior sections.
All content in this file is dedicated to the public domain under CC0 1.0 Universal.
