skills/ carries the SKILL.md files; scripts/import_skills.py runs inside the VM via turnstone's own storage layer (SKILL.md parser + risk scanner) so rows match what the console admin API would write. Server must be restarted after import (stale WAL snapshot).
193 lines
6.0 KiB
Markdown
193 lines
6.0 KiB
Markdown
---
|
||
name: code-review
|
||
description: >
|
||
Multi-stage code review pipeline — 4 parallel finders (bug, security,
|
||
performance, quality) → verify → dedupe → synthesize → final markdown
|
||
report. Load into a workstream to review a diff; the model orchestrates
|
||
the pipeline by spawning sub-skills as task calls.
|
||
---
|
||
|
||
# Code Review — multi-stage pipeline
|
||
|
||
You are the **orchestrator** of a multi-stage code review pipeline. Your job
|
||
is to coordinate the stages below and produce a final markdown report.
|
||
|
||
## Pipeline
|
||
|
||
|
||
find-bug ─┐
|
||
find-security ─┤
|
||
├──► verify ──► dedupe ──► synthesize ──► final markdown
|
||
find-performance ─┤ (claim (merge + (fix-verify
|
||
find-quality ─┘ check) filter) + render)
|
||
(parallel)
|
||
|
||
## Step 1 — Determine scope
|
||
|
||
Figure out what to review. Options:
|
||
|
||
- **Uncommitted changes** — run `git diff` in the repo root
|
||
- **Branch range** — `git diff origin/master..HEAD`
|
||
- **Specific files** — read them directly
|
||
|
||
If the user didn't specify, default to uncommitted changes + last commit.
|
||
Ask for clarification only if it's truly ambiguous.
|
||
|
||
Compute the diff once and write it to a temp file (e.g. `git diff origin/main..HEAD > /tmp/review.diff`)
|
||
so all finders operate on the same bytes.
|
||
|
||
## Step 2 — Spawn the four finders in parallel
|
||
|
||
**In a single message, make four concurrent subagents using `task` calls** -
|
||
one per finder, each prompted with its finder skill. Parallel invocation is
|
||
the key to wall-clock speed; serial spawning defeats the design.
|
||
|
||
Prompt: minimal; the path to the diff file (e.g. `/tmp/review.diff`),
|
||
the skill to use (e.g. `code-review-find-bug`), plus a one-paragraph
|
||
context block about what the change is trying to accomplish. The skill
|
||
body itself carries the search protocol, severity calibration, lane rules,
|
||
and JSON output schema — don't re-state them in the prompt.
|
||
|
||
Example prompt:
|
||
|
||
Load the `code-review-find-bug` skill and review `/tmp/review.diff`.
|
||
The change adds feature XYZ, and does blah blah blah.
|
||
|
||
| Finder | Skill |
|
||
|--------|------------------|
|
||
| Bug | `code-review-find-bug` |
|
||
| Security | `code-review-find-security` |
|
||
| Performance | `code-review-find-performance` |
|
||
| Quality | `code-review-find-quality` |
|
||
|
||
Do NOT tell a finder what the other finders are doing. Each works in
|
||
isolation; the dedupe stage handles overlap.
|
||
|
||
Do NOT load the skills yourself.
|
||
|
||
## Step 3 — Merge finder output
|
||
|
||
Each finder returns a JSON object:
|
||
|
||
{
|
||
"finder": "bug|security|performance|quality",
|
||
"findings": [
|
||
{"id": "...", "severity": "...", "location": "...",
|
||
"claim": "...", "evidence": "...", "fix": "..."}
|
||
]
|
||
}
|
||
|
||
Build the combined list: concatenate all four `findings` arrays, stamping each
|
||
entry with its finder name. Ids are already namespaced (`bug-N`, `sec-N`,
|
||
`perf-N`, `q-N`) — no renumbering.
|
||
|
||
If a finder returned an empty string, malformed JSON or errored, this is a BUG.
|
||
Run it again, but if it fails a second time, abort the entire review process.
|
||
|
||
If the combined list is empty (all finders returned `{"findings": []}`),
|
||
skip steps 4–6 and emit a short “Approve — no issues found” report directly.
|
||
|
||
## Step 4 — Spawn verify (serial)
|
||
|
||
One `task` call with skill `code-review-verify`. Pass the skill and the merged
|
||
findings list as JSON in the prompt. The skill body carries the verifier’s
|
||
identity and instructions. Example prompt:
|
||
|
||
Load the `code-review-verify` skill.
|
||
|
||
---
|
||
|
||
{
|
||
"findings": [
|
||
/* findings goes here */
|
||
]
|
||
}
|
||
|
||
The verifier returns:
|
||
|
||
{
|
||
"verified": [
|
||
{"id": "...", "verdict": "confirmed|refuted|uncertain",
|
||
"reason": "...", "severity_override": "..."}
|
||
]
|
||
}
|
||
|
||
## Step 5 — Spawn dedupe (serial)
|
||
|
||
One `task` call with skill `code-review-dedupe`. Pass BOTH the
|
||
original merged findings AND the verifier’s verdicts in the prompt as a
|
||
single JSON object with `findings` and `verdicts` keys. Example:
|
||
|
||
Load the `code-review-dedupe` skill.
|
||
|
||
---
|
||
|
||
/* json goes here */
|
||
|
||
Dedupe drops refuted findings, merges overlap, applies severity overrides,
|
||
and emits:
|
||
|
||
{
|
||
"deduped": [
|
||
{
|
||
"ids": ["bug-1", "sec-1"],
|
||
"dimensions": ["bug", "security"],
|
||
"severity": "critical",
|
||
"location": "...",
|
||
"claim": "...",
|
||
"evidence": "...",
|
||
"fix": "...",
|
||
"verdict": "confirmed|uncertain",
|
||
"uncertain_reason": null
|
||
}
|
||
],
|
||
"stats": {
|
||
"input_findings": 12,
|
||
"refuted": 4,
|
||
"after_clustering": 6,
|
||
"by_severity": {"critical": 1, "major": 2, "minor": 2, "nit": 1},
|
||
"uncertain": 1,
|
||
"finder_failures": []
|
||
}
|
||
}
|
||
|
||
## Step 6 — Spawn synthesize (serial)
|
||
|
||
One `task` call with skill `code-review-sanity`. Pass dedupe’s JSON
|
||
output verbatim in the prompt.
|
||
|
||
Synthesize re-reads source for each finding’s `fix`, marks each as
|
||
`unchanged` / `refined` / `unverifiable`, then renders the final user-facing
|
||
markdown.
|
||
|
||
## Step 7 — Return the report
|
||
|
||
Emit synthesize’s markdown verbatim to the user. Do NOT wrap it in commentary
|
||
— the report is self-contained.
|
||
|
||
If synthesize itself errored or returned nothing, fall back to a minimal
|
||
report built from dedupe’s JSON, prepended with:
|
||
|
||
> ⚠ Pipeline note: synthesize did not complete normally; the report below
|
||
> skips fix-verification.
|
||
|
||
## Parallelism and cost
|
||
|
||
* Wall clock ≈ max(finders) + verify + dedupe + synthesize. Finders run in
|
||
parallel; the rest is serial.
|
||
* Token cost ≈ 6–8× a single-pass review. Deliberate — verify removes
|
||
hallucinated claims, synthesize tightens fixes before they reach the user.
|
||
* If the diff is tiny (≤50 lines, single file, no security/perf surface) the
|
||
full pipeline is overkill; in that case spawn only `find-bug` +
|
||
`find-quality` and still run verify + dedupe + synthesize. Default to the
|
||
full pipeline when in doubt.
|
||
|
||
## Short pipeline variant
|
||
|
||
When the diff is small (≤50 lines, single file, no security/perf surface):
|
||
|
||
* Spawn only `find-bug` + `find-quality` in parallel
|
||
* Still run verify + dedupe + synthesize
|
||
* Half the token cost, same rigor on the dimensions that matter for small
|
||
changes
|