Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions skills/review-pr-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ Same scope as `review-pr`: **web/frontend projects** (React, TypeScript, Next.js
## Arguments

```
/review-pr-workflow <pr-url-or-number> [verify-agent=claude|codex] [tier=auto|full|light|skip]
/review-pr-workflow <pr-url-or-number> [verify-agent=claude|codex] [tier=auto|full|light|skip] [run-checks=true|false]
```

| Arg | Default | Meaning |
|-----|---------|---------|
| `verify-agent` | `claude` | Which agent verifies findings in Phase 2. `claude` uses the session model. `codex` shells out to the `codex` CLI. |
| `tier` | `auto` | How much horsepower to spend. `auto` detects from the diff (see Tier Detection). Anything else overrides detection. |
| `run-checks` | `true` | Phase 0 lint and tests. Omitted or `true` runs them. Only explicit `false` skips — then neither the main loop nor any workflow agent runs lint, tests, or typecheck. |

Example: `/review-pr-workflow https://github.com/yearn/kong/pull/412 verify-agent=codex tier=full`

Expand Down Expand Up @@ -52,7 +53,7 @@ Do all of this yourself. Subagents share one working directory; if they check ou
2. **Read the PR body for instructions** — author's review notes, linked issues (`Closes #123`, `Fixes #456`, URLs).
3. **Fetch linked issues** — read each issue body for the original spec. The review is graded against this, not against the PR description.
4. **Checkout the PR branch locally.** Do this once, here. Every workflow agent is read-only from this point.
5. **Run project linters** — `bun run lint`, `npm run lint`, whatever the project defines. Capture the output; it goes into the workflow as context so five agents don't each re-run it.
5. **Run project linters and tests** unless the user passed `run-checks=false`. Omitted means run. Lint: `bun run lint`, `npm run lint`. Tests: `bun test`, `npm test`, whatever the project defines. Capture both; they go into the workflow as `lintOutput` and `testOutput` so agents don't each re-run them. Pass `runChecks` as a real boolean (`true`/`false`). If skipped, do not run lint, tests, or typecheck; set both outputs to `(skipped — run-checks=false)` — never leave them empty; empty is interpolated as `(clean)`.
6. **Detect new dependencies** — if `package.json` changed, list newly added packages. These feed the dependency lens.
7. **Detect the tier** (below) and **state it out loud with its reason** before spawning anything.

Expand Down Expand Up @@ -127,10 +128,12 @@ Pass these as real JSON values, never a JSON-encoded string.
| `baseRef` | no | Base to diff against, e.g. `origin/main`. Defaults to `origin/HEAD`; pass it explicitly when the PR targets anything else. |
| `diffStat` | no | Output of `gh pr diff --stat` |
| `changedFiles` | no | Array of paths |
| `lintOutput` | no | Phase 0's lint result, so five agents don't each re-run it |
| `lintOutput` | no | Phase 0's lint result, so five agents don't each re-run it. On `run-checks=false`, the skip sentinel — not empty. |
| `testOutput` | no | Phase 0's test result. Same skip-sentinel rule as `lintOutput`. |
| `newDeps` | no | Newly added package names |
| `tier` | no | `full` or `light`. `skip` throws — run `review-pr` inline instead. |
| `verifyAgent` | no | `claude` (default) or `codex` |
| `runChecks` | no | Real boolean. Default `true`. `false` forbids lint/test/typecheck in every agent prompt. |

### returns

Expand Down Expand Up @@ -186,7 +189,7 @@ Agent count scales with findings, not diff size. A PR yielding 2 blockers and 5

4. **Preview the review for the user.** Output the full review as plain markdown text in the conversation. Do not skip this. Do not substitute a tool-call preview.

Then, in **no more than four lines** outside the review body, report counts only: tier and why, `verify-agent`, `stats.refuted`, `stats.discarded`, `stats.advisories`, any duplicate collapse from step 2, and `stats.unverified`. Counts, not contents — do not summarise a refuted claim. Two exceptions to the line budget — if `gaps` is non-empty, list each gap in one line so the user can decide whether to re-run a lens; and if `stats.unverified` is non-zero, list those findings explicitly and say plainly that the review is not exhaustive; raising `MAX_VERIFY_PER_LENS` or re-running that lens is the fix.
Then, in **no more than four lines** outside the review body, report counts only: tier and why, `verify-agent`, `run-checks`, `stats.refuted`, `stats.discarded`, `stats.advisories`, any duplicate collapse from step 2, and `stats.unverified`. Counts, not contents — do not summarise a refuted claim. Two exceptions to the line budget — if `gaps` is non-empty, list each gap in one line so the user can decide whether to re-run a lens; and if `stats.unverified` is non-zero, list those findings explicitly and say plainly that the review is not exhaustive; raising `MAX_VERIFY_PER_LENS` or re-running that lens is the fix.

5. **Post only after explicit approval.** Do not call any GitHub write tool before the user approves this specific review. A prior approval, a plan that mentioned posting, or this skill's own existence does not count.

Expand Down
19 changes: 19 additions & 0 deletions skills/review-pr-workflow/scripts/check-workflow.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ const FAKE = {
const isAdv = f => Boolean(f.advisory)
let agentCalls = 0
let labels = []
let prompts = []

function makeEnv({ refuteAll = false } = {}) {
agentCalls = 0
labels = []
prompts = []

async function agent(prompt, o = {}) {
agentCalls++
labels.push(o.label)
prompts.push({ label: o.label, prompt })
if (o.label?.startsWith('review:')) return { findings: FAKE[o.label.split(':')[1]] ?? [] }
if (o.label?.includes('verify:')) {
const refuted = refuteAll || o.label.includes('bugs3')
Expand Down Expand Up @@ -170,5 +173,21 @@ threw = null
try { await run({}) } catch (e) { threw = e.message }
check('[edge] missing args.pr is rejected', /args\.pr is required/.test(threw || ''), threw)

const specPrompt = (runArgs) => run(runArgs).then(() =>
prompts.find(p => p.label === 'review:spec')?.prompt || '')

const defaultPrompt = await specPrompt({ ...BASE, tier: 'light' })
check('[checks] omitted runChecks still forbids re-running lint/test',
/already run — do not re-run lint or tests/.test(defaultPrompt) &&
/Test output, already run/.test(defaultPrompt),
defaultPrompt.slice(0, 400))

const skippedPrompt = await specPrompt({ ...BASE, tier: 'light', runChecks: false })
check('[checks] runChecks=false forbids lint/test/typecheck and does not claim they ran',
/run-checks=false/.test(skippedPrompt) &&
/Do not run lint, tests, typecheck/.test(skippedPrompt) &&
!/already run/.test(skippedPrompt),
skippedPrompt.slice(0, 400))

console.log(fails ? `\n${fails} failing` : '\nall checks passed')
process.exit(fails ? 1 : 0)
13 changes: 11 additions & 2 deletions skills/review-pr-workflow/workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,21 @@ const {
diffStat = '',
changedFiles = [],
lintOutput = '',
testOutput = '',
newDeps = [],
tier = 'full',
verifyAgent = 'claude',
runChecks = true,
} = input

const CHECKS = runChecks
? `Lint output, already run — do not re-run lint or tests:
${lintOutput || '(clean)'}

Test output, already run — do not re-run it:
${testOutput || '(clean)'}`
: `run-checks=false. Do not run lint, tests, typecheck, or any project script. Review the diff only.`

// Verify at most this many findings per lens, highest severity first. Bounds the
// agent count; the selection is deterministic so resumes hit cache.
const MAX_VERIFY_PER_LENS = 4
Expand Down Expand Up @@ -72,8 +82,7 @@ ${changedFiles.join('\n')}
Diffstat:
${diffStat}

Lint output, already run — do not re-run it:
${lintOutput || '(clean)'}
${CHECKS}

The PR branch is already checked out. You are READ-ONLY: do not checkout, commit,
stash, start a dev server, or modify any file.
Expand Down