| name | github-review-twin |
| description | Reviews pull requests in the user's own GitHub review voice, as a deterministic pipeline of blocks (blocks.yaml) — ownership detection, nine mandatory gates, a judgement pass, then voice + ASD-STE100 Simplified Technical English wording and short-post compression. Use when the user asks to review a PR, review code like them, draft or post PR comments, self-review their own PR, mine past GitHub review feedback, tune the review rules, sync AGENTS into the twin, add or skip a review block, or make reviews sound less AI-generated and more like their own style. |
GitHub Review Twin
Deterministic pipeline. Every step is a block in blocks.yaml. This file is the runner and the invariants; the blocks hold the work.
SKILL_DIR="${SKILL_DIR:-$HOME/.claude/skills/github-review-twin}"
cat "${SKILL_DIR}/blocks.yaml"
Run contract
cat blocks.yaml. Announce the resolved run: block ids in order, each marked run or skip: <reason>.
- Execute blocks in manifest order. Read a block's
file at the moment you run it — not up front.
- A block whose
when is false is skipped and reported. Never dropped silently, never re-ordered, never "does not apply" by judgement from reading the diff.
- Each block appends to the findings pile with its
id attached. Findings keep their block id until the rank block.
- Stop after the
deliver-* block for the current mode. The other one does not run.
Adding a block. Append an entry to blocks.yaml and write its blocks/<id>.md. Position in the list = position in the run. A block that wraps another skill sets skill: <name> and its file says how to feed it. blocks/debate.md is the worked example.
Thorough mode. Large or multi-domain PR: read blocks/thorough.md — same blocks, dispatched to parallel sub-agents, Tier 0 in the main thread first.
Skipping a block. The user may say skip=g4-convention or only=g0-existence,g1-provenance. Honour it and say which blocks were skipped in the output.
Block file shape
Every blocks/*.md file has, in this order:
# <id> — <one-line purpose>
**When:** <condition, same as blocks.yaml>
**Scan:** <the greps / reads that produce candidates>
**Verdict:** <how a candidate becomes a finding, or gets dropped>
**Emits:** <what lands on the pile>
Candidates are not findings. A grep result is where you start looking; an empty scan means "nothing matched", not "this gate passed".
Invariants (hold in every block, every mode)
- Ownership decides everything. Own PR → fix the code, stage, self-review. Someone else's PR → comment only, never edit their branch. Getting this backwards is the worst failure mode.
- Never commit, never push. Stage only. Every mode.
- Tier 0 wins. When
g0-existence, g0b-scope, or g0c-rendering fires, drop every later finding whose subject lives inside the path that should be deleted, split out, or restructured — from the chat draft too. A finding about code that should not exist is deleted, not demoted.
- Never review how feature-flag branches are organized. No finding may propose to split, extract, deduplicate, parameterize, rename, or tidy them, in any file, under any wording — including "the cleanup after rollout is one delete instead of seven edits". Advice that plans the flag's future has accepted the flag instead of questioning it.
- Inline only. Every posted finding attaches to a code line (
path + line, side: RIGHT). No PR-wide body, no summary table, no gh pr comment for findings.
- No verdict without the scan.
g1-provenance has three outcomes needing three different fixes; g2-reuse needs a named replacement. Guessing gets them wrong.
- Never assert scarcity you did not measure. "used nowhere else", "the only caller" — run the grep and quote the count, or cut the claim and keep the finding.
- Collapse before you rank. One rule broken across six files is one finding.
- Substance precedence (AuraSell/aurasell web PRs): live
web/AGENTS.md + matching web/.agents/skills/ > root AGENTS.md > review-rules.md.
- Wording stack: openers and severity from
review-voice-profile.md → body from review-ste.md → ADHD + caveman compression on simple posts. If compression would strip a signature opener (nit:, can we, lets, why, FYI -), keep the opener and cut the rest.
- Never say "as an AI", never disclose internal analysis, never name STE / ASD-STE100 / ADHD / caveman in a comment, never add "[Comment made with Cursor]".
- Only correctness bugs, regressions, and security issues are blockers. Everything else is non-blocking — trust the author to weigh it.
Reference files (read when a block calls for them)
| File | Holds | Read when |
|---|
review-voice-profile.md | openers, severity markers, priorities, comment shape | voice block |
review-ste.md | Simplified Technical English rules for comment bodies | voice block, every draft |
review-rules.md | substance checklist behind the gates | the gate that cites it |
review-knowledge-drop.md | mined recurring patterns, source coverage, sync metadata | judge block, or when tuning |
VALIDATION-PR-14415.md | regression fixture: 13 missed findings + the gate that must catch each | before changing any gate |
maintenance.md | voice re-mine, AGENTS sync, learning from PR comments, evals | user asks to update/sync/tune the twin |