diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index 96dda15..7708203 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -16,15 +16,57 @@ permissions: id-token: write jobs: + # ---------- Gate: run CI checks first so Claude doesn't waste tokens ---------- + # Skips gracefully if package.json doesn't exist yet (spec-only PRs). + ci: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + + - name: Check if project has been scaffolded + id: check + run: | + if [ -f package.json ]; then + echo "has_project=true" >> "$GITHUB_OUTPUT" + else + echo "has_project=false" >> "$GITHUB_OUTPUT" + echo "No package.json found — skipping CI (spec-only PR)" + fi + + - uses: actions/setup-node@v4 + if: steps.check.outputs.has_project == 'true' + with: + node-version: 22 + + - run: npm ci + if: steps.check.outputs.has_project == 'true' + + - run: npm run lint + if: steps.check.outputs.has_project == 'true' + + - run: npm run typecheck + if: steps.check.outputs.has_project == 'true' + + - run: npm test -- --run + if: steps.check.outputs.has_project == 'true' + env: + CI: true + + - run: npm run build + if: steps.check.outputs.has_project == 'true' + + # ---------- Claude review: only runs if CI passes ---------- review: - # Skip drafts; review when marked ready. + needs: ci if: github.event.pull_request.draft == false runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 15 steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 # full history so Claude can diff against base + fetch-depth: 0 - uses: anthropics/claude-code-action@v1 with: @@ -42,32 +84,29 @@ jobs: judging the diff — PRs here are usually either spec documents or implementations of a spec. - Review standards for this repo, in priority order: + CI (tests, lint, typecheck, build) has ALREADY PASSED in a prior + job. Do NOT re-run npm ci, npm test, npm run lint, npm run + typecheck, or npm run build. Focus exclusively on code review. - 1. VERIFY, don't trust. If the PR contains code, run the actual - acceptance toolchain from a clean state: npm ci (a lockfile out - of sync with package.json is an automatic blocker), then - npm test, npm run typecheck, npm run lint, npm run build. - Report exact failures. A fresh clone must work — missing - postinstall/prepare steps are blockers, not nits. + Review standards for this repo, in priority order: - 2. Spec traceability. If the PR implements a numbered task, check + 1. Spec traceability. If the PR implements a numbered task, check the implementation against that spec's acceptance criteria and flag criteria that are unmet or silently reinterpreted. - 3. Consistency across sources of truth. Flag contradictions + 2. Consistency across sources of truth. Flag contradictions between the diff, .kiro/steering/AI-MAP.md, .kiro/specs/, and "MD Instructions/" — including stale version pins and paths. - 4. Registry purity rule: nothing imported by /compiler, its CLI, + 3. Registry purity rule: nothing imported by /compiler, its CLI, or /server may transitively import .vue files. Check imports. - 5. Standard review: correctness, types (no `any`), security, + 4. Standard review: correctness, types (no `any`), security, and whether tests actually assert what they claim. Do not restate the diff or praise padding. Credit genuinely good decisions in one or two lines. Be specific enough that a follow-up commit can address every point without asking questions. claude_args: | - --max-turns 30 - --allowedTools "Bash(npm ci),Bash(npm install),Bash(npm test),Bash(npm run typecheck),Bash(npm run lint),Bash(npm run build),Bash(npx nuxt prepare),Bash(git diff:*),Bash(git log:*)" + --max-turns 20 + --allowedTools "Read,Grep,Glob,MultiGrep,Bash(git diff:*),Bash(git log:*),Bash(cat:*),Bash(find:*),Bash(ls:*),Bash(head:*),Bash(tail:*),Bash(wc:*)" diff --git a/CLAUDE.md b/CLAUDE.md index 9cabaa2..0136231 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,5 +25,7 @@ reviewer, Claude Code sessions) must follow the same project conventions. - Component tests mounting Nuxt UI components use `mountSuspended` from `@nuxt/test-utils/runtime` (Vitest environment `nuxt`); pure unit tests opt into node via a `// @vitest-environment node` docblock. -- A fresh clone must pass: `npm ci && npm test && npm run typecheck && - npm run lint && npm run build`. +- A fresh clone must pass: `npm ci && npm run lint && npm run typecheck && + npm test && npm run build`. +- CI runs these checks as a gate before the Claude review job. Claude does + not re-run them — it focuses on code review only.