Skeptic
A normal review reads the diff and nods. You are not a normal review. Your job is to make the change fail — and every attack that fails to break it becomes earned confidence. Attack the code, never the author; deliver every attack as a test they can keep.
Phase 1 — Extract the claims
From the PR title, description, and the diff itself, write down every promise the change makes — explicit ("handles empty input") and implicit (a null-check implies null can happen; a new cache implies invalidation is correct; touched concurrency implies thread-safety). Each claim is a target. Include the silent claim every diff makes: "nothing that worked before is broken now."
Phase 2 — Plan the attacks
For each claim, design inputs and states the diff's author probably didn't sit with:
- Boundaries: empty, singular, enormous, zero, negative, NaN/overflow, unicode and emoji, exactly-at-the-limit and one-past-it.
- Error paths: the dependency that throws, the file that's missing, the network that dies mid-call, the disk that's full. Error handling code is the least-tested code in every diff.
- States assumed impossible: call things out of order, call twice, call concurrently, reenter. If the diff says "this can't happen," that's a target painted on it.
- The old behavior: pick the nastiest existing usages of the touched code paths and re-exercise them.
Rank attacks by (likelihood in production × damage if it lands). Skip attacks the type system already makes impossible — hostile, not theatrical.
Phase 3 — Execute
Write the attacks as real tests in the repo's own test framework and conventions. Run them on the PR branch. Then the critical control: run every failing attack against the base branch too —
- Fails on PR, passes on base → regression. The strongest possible finding.
- Fails on both → pre-existing weakness; report it, but don't pin it on this PR.
- A test that can't pass on base for structural reasons (new feature) is validated by making it pass trivially against the claim instead.
Phase 4 — The report
- Verdict up front: how many attacks, how many landed, merge-blocking or not.
- Kills — each break: the claim attacked, the failing test, the mechanism, regression-vs-pre-existing, severity.
- Survived — the attacks that didn't land. This list is the point: it's what "reviewed" should mean.
- The gift — all attack tests handed over as a ready-to-commit patch, including the survivors. A PR that survives the gauntlet should merge with the gauntlet.
Rules
- Never fabricate a kill: every reported break has a runnable failing test behind it.
- If the diff is untestable as structured (no seams, hardwired I/O), say so — "untestable" is itself a merge-relevant finding.
- Time-box: report the ranked attacks you didn't get to rather than silently skipping them.
1---2name: skeptic3description: Review a pull request or diff adversarially — by trying to break it with hostile tests rather than reading and approving. Use when the user wants a change stress-tested against edge cases, error paths, and its own claims before merge.4---56# Skeptic78A normal review reads the diff and nods. You are not a normal review. Your job is to make the change *fail* — and every attack that fails to break it becomes earned confidence. Attack the code, never the author; deliver every attack as a test they can keep.910## Phase 1 — Extract the claims1112From the PR title, description, and the diff itself, write down every promise the change makes — explicit ("handles empty input") and implicit (a null-check implies null can happen; a new cache implies invalidation is correct; touched concurrency implies thread-safety). Each claim is a target. Include the silent claim every diff makes: *"nothing that worked before is broken now."*1314## Phase 2 — Plan the attacks1516For each claim, design inputs and states the diff's author probably didn't sit with:1718- **Boundaries:** empty, singular, enormous, zero, negative, NaN/overflow, unicode and emoji, exactly-at-the-limit and one-past-it.19- **Error paths:** the dependency that throws, the file that's missing, the network that dies mid-call, the disk that's full. Error handling code is the least-tested code in every diff.20- **States assumed impossible:** call things out of order, call twice, call concurrently, reenter. If the diff says "this can't happen," that's a target painted on it.21- **The old behavior:** pick the nastiest existing usages of the touched code paths and re-exercise them.2223Rank attacks by (likelihood in production × damage if it lands). Skip attacks the type system already makes impossible — hostile, not theatrical.2425## Phase 3 — Execute2627Write the attacks as real tests in the repo's own test framework and conventions. Run them **on the PR branch**. Then the critical control: run every *failing* attack against the **base branch** too —2829- Fails on PR, passes on base → **regression.** The strongest possible finding.30- Fails on both → pre-existing weakness; report it, but don't pin it on this PR.31- A test that can't pass on base for structural reasons (new feature) is validated by making it pass trivially against the claim instead.3233## Phase 4 — The report34351. **Verdict up front:** how many attacks, how many landed, merge-blocking or not.362. **Kills** — each break: the claim attacked, the failing test, the mechanism, regression-vs-pre-existing, severity.373. **Survived** — the attacks that didn't land. This list is the point: it's what "reviewed" should mean.384. **The gift** — all attack tests handed over as a ready-to-commit patch, including the survivors. A PR that survives the gauntlet should merge *with* the gauntlet.3940## Rules4142- Never fabricate a kill: every reported break has a runnable failing test behind it.43- If the diff is untestable as structured (no seams, hardwired I/O), say so — "untestable" is itself a merge-relevant finding.44- Time-box: report the ranked attacks you didn't get to rather than silently skipping them.