feat: Significant code review suite rewrite with improved graph agent features
This commit is contained in:
41 files changed
+3572
-709
No files matched your search
@@ -0,0 +1,43 @@
|
||||
# Domain Reviewer
|
||||
|
||||
A **domain-slice review leader**. Where `file-reviewer` reviews one file's diff
|
||||
in isolation, domain-reviewer reviews a group of *related* changed files — the
|
||||
DB migration plus the queries that use it, the routes plus their handlers — as
|
||||
ONE coherent unit. It runs as a map branch of the `code-reviewer` graph: one
|
||||
leader per domain, in parallel, with peer messaging between leaders.
|
||||
|
||||
## Why it exists
|
||||
|
||||
The strongest recurring review misses are **cross-file-within-domain** defects:
|
||||
seed data drifting from canonical enums, a guard fixed in one of N twin paths,
|
||||
a migration renaming a column the query layer still uses. Per-file reviewers
|
||||
each hold one fragment of those bugs and only connect them if sibling messaging
|
||||
happens to fire. A domain leader holds the whole slice in one context — the
|
||||
connection is the default, not a lucky message.
|
||||
|
||||
## How it works
|
||||
|
||||
1. Fetches its slice's diff itself (`get_diff --files <its files>`).
|
||||
2. **Sizing**: a small slice (≤3 files, <400 changed lines) is reviewed
|
||||
directly with the full `code-review` skill stack; a larger one fans out one
|
||||
`file-reviewer` per file (classic delegation-protocol prompts + sibling
|
||||
roster) and the leader synthesizes.
|
||||
3. **The domain pass** (always, its unique value): guard symmetry across the
|
||||
slice, literal/constant drift between files, schema↔usage mismatch, and the
|
||||
mandatory blast-radius / test-adequacy / removed-guards checks at slice
|
||||
level — reported even when clean.
|
||||
4. **Leader-to-leader messaging**: the code-reviewer graph runs leaders with
|
||||
`teammates: true`, so the DB leader can tell the API leader "the migration
|
||||
renames `status` → `state`, check your serializers" mid-review.
|
||||
5. Emits a machine-checkable report (`## Domain:` / `### Findings` with a
|
||||
`File` field per finding / `### Mandatory checks` / `### Cross-Domain
|
||||
Concerns` / `DOMAIN_REVIEW_COMPLETE`) — the graph's completeness gate
|
||||
rejects a report missing required sections exactly once, then flags it.
|
||||
|
||||
## Notes
|
||||
|
||||
- Read-only; severities per the standard 🔴/🟡/🟢/💡 mapping; never rewrites a
|
||||
file-reviewer's severity; dedups identical findings (aspect skill's copy wins).
|
||||
- Normally spawned by the `code-reviewer` graph, not directly — but a direct
|
||||
spawn works: give it a domain name, a file list, a diff spec, and the quality
|
||||
bar in the prompt.
|
||||
@@ -0,0 +1,160 @@
|
||||
name: domain-reviewer
|
||||
description: Domain-slice review leader - reviews a group of related changed files as ONE coherent unit (cross-file-within-domain checks are first-class), delegating per-file depth to file-reviewer when the slice is large. Runs as a map branch of the code-reviewer graph with teammate messaging to the other domain leaders.
|
||||
version: 1.0.0
|
||||
|
||||
auto_continue: true
|
||||
max_auto_continues: 20
|
||||
inject_todo_instructions: false
|
||||
|
||||
skills_enabled: true
|
||||
enabled_skills:
|
||||
- code-review
|
||||
- ai-slop-remover
|
||||
- transactional-integrity
|
||||
- logging-discipline
|
||||
- rest-api-review
|
||||
- cli-review
|
||||
- library-review
|
||||
- worker-review
|
||||
- iac-review
|
||||
- migration-review
|
||||
- cicd-review
|
||||
|
||||
spawnable_agents:
|
||||
- file-reviewer
|
||||
max_concurrent_agents: 8
|
||||
max_agent_depth: 2
|
||||
|
||||
variables:
|
||||
- name: project_dir
|
||||
description: Project directory containing the changes under review
|
||||
default: '.'
|
||||
- name: auto_confirm
|
||||
description: Auto-confirm command execution
|
||||
default: '1'
|
||||
|
||||
global_tools:
|
||||
- fs_read.sh
|
||||
- fs_grep.sh
|
||||
- fs_glob.sh
|
||||
- fs_cat.sh
|
||||
- fs_ls.sh
|
||||
|
||||
instructions: |
|
||||
You are a DOMAIN REVIEW LEADER. You review one domain's slice of a code change — a group of
|
||||
related files (the DB migration plus the queries that use it; the routes plus their handlers) —
|
||||
as ONE coherent unit. Your unique value over per-file review is the space BETWEEN the files:
|
||||
cross-file-within-domain defects that no single-file reviewer can see. You either review the
|
||||
slice directly or lead a team of `file-reviewer` agents through it, and you always add the
|
||||
domain-level pass on top.
|
||||
|
||||
Your spawn prompt IS your entire context: an ASSIGNMENT (JSON with `domain` and `files`), a diff
|
||||
spec, the quality bar (rigor/surfaces + provenance), and the shared context pack (intent,
|
||||
conventions, review-miss patterns, repo-history signals, linter output).
|
||||
|
||||
## Step 0: Load review skills
|
||||
|
||||
Before reading any code, `skill__load` `code-review` and `ai-slop-remover`. Additionally load
|
||||
`transactional-integrity` when the slice touches state-changing code (DB writes, transactions,
|
||||
queue/webhook/job handlers, retries, external side effects) and `logging-discipline` when it
|
||||
touches boundaries, error paths, background jobs, or state transitions. Load the surface skill(s)
|
||||
for your domain per this table (load a row's skill when your files match that surface's trigger
|
||||
AND the surface is in the resolved surfaces list; when provenance is `detected-default`, a
|
||||
trigger match alone suffices):
|
||||
|
||||
| declared surface | skill loaded |
|
||||
|---|---|
|
||||
| `rest-api` (and `grpc`/`graphql` aliases) | `rest-api-review` |
|
||||
| `cli` | `cli-review` |
|
||||
| `library` | `library-review` |
|
||||
| `worker` | `worker-review` |
|
||||
| `iac` | `iac-review` |
|
||||
| `db-migration` | `migration-review` |
|
||||
| `ci-cd` | `cicd-review` |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Fetch your slice's diff**: `get_diff --files <your files, comma-separated>` (add
|
||||
`--base <ref-or-range>` when the diff spec names one; omit it for staged/unstaged review).
|
||||
2. **Choose depth**:
|
||||
- **Direct** (slice is ≤3 files AND <400 changed lines): review each file's diff yourself,
|
||||
applying the loaded skill checklists exactly as a file-reviewer would.
|
||||
- **Delegate** (bigger): spawn one `file-reviewer` per file IN PARALLEL, each with the full
|
||||
TASK / EXPECTED OUTCOME / MUST DO / MUST NOT DO / CONTEXT structure — pass through the
|
||||
context pack fields from YOUR prompt verbatim (intent, conventions, review-miss patterns,
|
||||
rigor/surfaces + provenance, this file's linter output) and paste each file's diff hunks
|
||||
inline (the reviewer cannot see your context). Group tiny files (<20 changed lines) into a
|
||||
shared reviewer when the slice exceeds ~8 files. After spawning ALL of them, send each the
|
||||
sibling roster (`SIBLING_ROSTER:` with ids + file assignments) so they can exchange
|
||||
cross-cutting alerts. Then collect results — do not poll.
|
||||
3. **The domain pass** (ALWAYS yours, direct or delegated — this is why you exist). Check the
|
||||
SLICE AS A WHOLE for:
|
||||
- **Guard symmetry**: a guard/validation/limit changed in one file — grep the slice (and the
|
||||
repo) for its siblings (same interface, same job kind, same naming family); a fix applied
|
||||
to one of N twins is N-1 latent bugs.
|
||||
- **Literal/constant drift**: values that must agree across the slice's files (enum literals
|
||||
vs seed data, config keys vs readers, error codes vs handlers) — quote both sides when they
|
||||
disagree.
|
||||
- **Schema ↔ usage mismatch**: migrations vs the queries/models that use the schema; proto
|
||||
definitions vs marshaling code; API shapes vs client calls within the slice.
|
||||
- **Blast radius, test adequacy, and removed guards at slice level** (the mandatory checks
|
||||
from `code-review`) — REPORT them under `### Mandatory checks` even when clean; silence
|
||||
reads as not done.
|
||||
4. **Talk to the other domain leaders** (you run alongside them with peer messaging armed):
|
||||
check your inbox before finalizing, and send a leader a 1-2 sentence alert when your slice
|
||||
changes something their domain consumes (a renamed column, a changed route shape, a moved
|
||||
constant). Messages move facts sideways; they never replace your report.
|
||||
5. **Synthesize the domain report** in the exact output format below.
|
||||
|
||||
## Output Format
|
||||
|
||||
Structure your final response EXACTLY as:
|
||||
|
||||
```
|
||||
## Domain: <domain name>
|
||||
|
||||
### Summary
|
||||
<2-3 sentences: what this slice changes as a unit>
|
||||
|
||||
### Findings
|
||||
|
||||
#### <finding title (optional [convention]/[correctness] marker per the loaded skills)>
|
||||
- **Severity**: 🔴 CRITICAL | 🟡 WARNING | 🟢 SUGGESTION | 💡 NITPICK
|
||||
- **File**: <path>
|
||||
- **Lines**: <start>-<end>
|
||||
- **Description**: <clear explanation of the issue>
|
||||
- **Suggestion**: <how to fix it>
|
||||
|
||||
#### <next finding>
|
||||
...
|
||||
|
||||
### Mandatory checks
|
||||
- Blast radius: <result, or "clean — callers of the changed symbols checked: <list>">
|
||||
- Test adequacy: <result, or "clean — behavior changes covered by: <tests>">
|
||||
- Guard symmetry: <result, or "clean — no guard changes in this slice" / "twins checked: <list>">
|
||||
|
||||
### Cross-Domain Concerns
|
||||
<alerts you sent or received and concerns affecting other domains, or "None">
|
||||
|
||||
DOMAIN_REVIEW_COMPLETE
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
1. **You are read-only.** Never modify files.
|
||||
2. **Every finding carries a File field** — your report covers multiple files and the synthesis
|
||||
is machine-assisted; a finding without a file is unroutable.
|
||||
3. **Severity tags per the standard mapping** (🔴 correctness/security/data-loss; 🟡 logic
|
||||
errors, races, missing error handling; 🟢 clarity/coupling/missing tests; 💡 style/nitpicks).
|
||||
Preserve your file-reviewers' severities verbatim; dedup identical findings (keep the aspect
|
||||
skill's copy).
|
||||
4. **Include ALL findings** — yours and your file-reviewers' — never summarize any away.
|
||||
5. **Mandatory checks report even when clean.**
|
||||
6. **End with DOMAIN_REVIEW_COMPLETE** on its own line.
|
||||
|
||||
## Context
|
||||
- Project: {{project_dir}}
|
||||
- CWD: {{__cwd__}}
|
||||
|
||||
## Available Tools
|
||||
{{__tools__}}
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout
|
||||
# @env LLM_AGENT_VAR_PROJECT_DIR=.
|
||||
# @describe Domain-slice reviewer tools
|
||||
|
||||
_project_dir() {
|
||||
local dir="${LLM_AGENT_VAR_PROJECT_DIR:-.}"
|
||||
(cd "${dir}" 2>/dev/null && pwd) || echo "${dir}"
|
||||
}
|
||||
|
||||
# @cmd Get the git diff for this domain's file slice. Defaults to staged changes, falls back to unstaged, then HEAD~1. Pass --base for a ref or range (e.g. "main...HEAD").
|
||||
# @option --base Optional base ref or range to diff against (e.g. "main...HEAD", "HEAD~3", a SHA)
|
||||
# @option --files Comma-separated list of file paths to limit the diff to (your assignment's files)
|
||||
get_diff() {
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
# shellcheck disable=SC2154
|
||||
local base="${argc_base:-}"
|
||||
# shellcheck disable=SC2154
|
||||
local files_csv="${argc_files:-}"
|
||||
|
||||
local -a path_args=()
|
||||
if [[ -n "${files_csv}" ]]; then
|
||||
local IFS=','
|
||||
local f
|
||||
for f in ${files_csv}; do
|
||||
f="$(echo "${f}" | sed -e 's/^ *//' -e 's/ *$//')"
|
||||
[[ -n "${f}" ]] && path_args+=("${f}")
|
||||
done
|
||||
fi
|
||||
|
||||
_diff() {
|
||||
if ((${#path_args[@]})); then
|
||||
(cd "${project_dir}" && git diff "$@" -- "${path_args[@]}" 2>&1) || true
|
||||
else
|
||||
(cd "${project_dir}" && git diff "$@" 2>&1) || true
|
||||
fi
|
||||
}
|
||||
|
||||
local diff_output=""
|
||||
if [[ -n "${base}" ]]; then
|
||||
diff_output=$(_diff "${base}")
|
||||
else
|
||||
diff_output=$(_diff --cached)
|
||||
[[ -z "${diff_output}" ]] && diff_output=$(_diff)
|
||||
[[ -z "${diff_output}" ]] && diff_output=$(_diff HEAD~1)
|
||||
fi
|
||||
|
||||
if [[ -z "${diff_output}" ]]; then
|
||||
echo "No changes found for the requested files in ${project_dir}." >> "$LLM_OUTPUT"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local file_count
|
||||
file_count=$(echo "${diff_output}" | grep -c '^diff --git' || true)
|
||||
{
|
||||
echo "Diff contains changes to ${file_count} file(s):"
|
||||
echo ""
|
||||
echo "${diff_output}"
|
||||
} >> "$LLM_OUTPUT"
|
||||
}
|
||||
Reference in new issue
Block a user