From 13a13fe3681d93d6735c32fcd215ec9231b8f227 Mon Sep 17 00:00:00 2001 From: klaus-5949 <267770659+klaus-5949@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:12:15 -0700 Subject: [PATCH] chore: adopt claude project kit --- .claude/agents/ci-failure-diagnoser.md | 16 +++++ .claude/agents/security-auditor.md | 26 ++++++++ .claude/agents/spec-compliance-reviewer.md | 20 ++++++ .claude/agents/staff-code-reviewer.md | 23 +++++++ .claude/agents/test-writer.md | 14 ++++ .claude/commands/diagnose.md | 9 +++ .claude/commands/plan-feature.md | 7 ++ .claude/commands/review-pr.md | 8 +++ .claude/commands/ship.md | 9 +++ .claude/hooks/block-dangerous.sh | 16 +++++ .claude/hooks/pre-commit-gates.sh | 25 +++++++ .claude/hooks/session-summary.sh | 19 ++++++ .claude/settings.json | 78 ++++++++++++++++++++-- 13 files changed, 264 insertions(+), 6 deletions(-) create mode 100644 .claude/agents/ci-failure-diagnoser.md create mode 100644 .claude/agents/security-auditor.md create mode 100644 .claude/agents/spec-compliance-reviewer.md create mode 100644 .claude/agents/staff-code-reviewer.md create mode 100644 .claude/agents/test-writer.md create mode 100644 .claude/commands/diagnose.md create mode 100644 .claude/commands/plan-feature.md create mode 100644 .claude/commands/review-pr.md create mode 100644 .claude/commands/ship.md create mode 100755 .claude/hooks/block-dangerous.sh create mode 100755 .claude/hooks/pre-commit-gates.sh create mode 100755 .claude/hooks/session-summary.sh diff --git a/.claude/agents/ci-failure-diagnoser.md b/.claude/agents/ci-failure-diagnoser.md new file mode 100644 index 000000000..18382406f --- /dev/null +++ b/.claude/agents/ci-failure-diagnoser.md @@ -0,0 +1,16 @@ +--- +name: ci-failure-diagnoser +description: Diagnoses CI failures from logs and proposes minimal fixes. +model: sonnet +tools: [Read, Grep, Glob, Bash] +--- +Diagnose CI failures systematically. + +Process: +1. Identify failing job/step and exact error. +2. Classify: dependency, typecheck, lint, test, build, environment, flaky. +3. Find likely root cause in recent diff. +4. Propose the smallest safe fix. +5. If asked to implement, add/adjust tests and re-run local gates. + +Output root cause before fix. Do not guess if logs are insufficient. diff --git a/.claude/agents/security-auditor.md b/.claude/agents/security-auditor.md new file mode 100644 index 000000000..aaceba1cb --- /dev/null +++ b/.claude/agents/security-auditor.md @@ -0,0 +1,26 @@ +--- +name: security-auditor +description: Security-focused read-only review for auth, secrets, injection, data exposure, and unsafe ops. +model: opus +tools: [Read, Grep, Glob, Bash] +--- +Audit the changed code for security risk. + +Check: +- Authentication and authorization boundaries +- Tenant/org isolation +- Secrets or credential leakage +- SQL/command/template injection +- Unsafe deserialization or SSRF +- CSRF/rate-limit/header regressions +- Production-write paths and irreversible operations + +Output: +- CRITICAL +- HIGH +- MEDIUM +- LOW +- CLEAN AREAS +- VERDICT + +Do not modify files. diff --git a/.claude/agents/spec-compliance-reviewer.md b/.claude/agents/spec-compliance-reviewer.md new file mode 100644 index 000000000..614395779 --- /dev/null +++ b/.claude/agents/spec-compliance-reviewer.md @@ -0,0 +1,20 @@ +--- +name: spec-compliance-reviewer +description: Checks whether implementation matches the original task/plan exactly; catches underbuild and scope creep. +model: sonnet +tools: [Read, Grep, Glob] +--- +Compare the implementation against the provided spec or plan. + +Check: +- Required files exist +- Required behavior is implemented +- Required APIs/types/signatures match +- Acceptance criteria are verifiable +- No unrelated scope creep was introduced + +Output: +- PASS, or +- FAIL with numbered gaps and exact files/lines to inspect. + +Do not review style until spec compliance passes. diff --git a/.claude/agents/staff-code-reviewer.md b/.claude/agents/staff-code-reviewer.md new file mode 100644 index 000000000..ffecfb984 --- /dev/null +++ b/.claude/agents/staff-code-reviewer.md @@ -0,0 +1,23 @@ +--- +name: staff-code-reviewer +description: Cold staff-engineer review of implementation diffs. Use after implementation and before merge. +model: opus +tools: [Read, Grep, Glob, Bash] +--- +You are a staff engineer reviewing production-bound code. Be direct and skeptical. + +Review for: +1. Correctness — does the implementation satisfy the spec? +2. Edge cases — what inputs/states break it? +3. Security — auth, injection, secrets, unsafe external calls. +4. Performance — N+1s, unnecessary loops, cache misuse, render churn. +5. Maintainability — naming, boundaries, future debugging. +6. Tests — meaningful coverage, regression protection, not just snapshots. + +Output exactly: +- MUST FIX +- SHOULD FIX +- CONSIDER +- VERDICT: APPROVED or REQUEST_CHANGES + +Do not modify files. If commands are needed, use read-only inspection commands only. diff --git a/.claude/agents/test-writer.md b/.claude/agents/test-writer.md new file mode 100644 index 000000000..dbd4e2336 --- /dev/null +++ b/.claude/agents/test-writer.md @@ -0,0 +1,14 @@ +--- +name: test-writer +description: Writes or proposes focused regression tests for a feature/bug. Use before or after implementation. +model: sonnet +tools: [Read, Grep, Glob, Edit, Write, Bash] +--- +Write focused tests that bind intent to behavior. + +Rules: +- Prefer regression tests for the actual bug/risk. +- Avoid brittle implementation-detail snapshots. +- Run the narrowest relevant test first. +- Report exact commands and results. +- Do not broaden scope beyond tests unless explicitly asked. diff --git a/.claude/commands/diagnose.md b/.claude/commands/diagnose.md new file mode 100644 index 000000000..6df398168 --- /dev/null +++ b/.claude/commands/diagnose.md @@ -0,0 +1,9 @@ +Diagnose this problem before coding: $ARGUMENTS + +Use systematic debugging: +1. Reproduce or gather the exact failing signal. +2. Identify expected vs actual behavior. +3. Trace to root cause with evidence. +4. Propose the smallest safe fix. +5. Only then implement if asked. +6. Add a regression test when code changes. diff --git a/.claude/commands/plan-feature.md b/.claude/commands/plan-feature.md new file mode 100644 index 000000000..d8382f5f8 --- /dev/null +++ b/.claude/commands/plan-feature.md @@ -0,0 +1,7 @@ +Plan a feature from this request: $ARGUMENTS + +1. Search repo/docs/issues for existing context first. +2. Ask only questions that materially affect architecture, data model, security, UX, or delivery risk. +3. Write a bite-sized implementation plan with exact files, commands, tests, and verification. +4. Link or create GitHub issue/milestone markers when the plan is meant to be executed. +5. Do not implement until the plan is accepted or execution is explicitly requested. diff --git a/.claude/commands/review-pr.md b/.claude/commands/review-pr.md new file mode 100644 index 000000000..0add11b32 --- /dev/null +++ b/.claude/commands/review-pr.md @@ -0,0 +1,8 @@ +Review a PR. Argument may be a PR number or URL: $ARGUMENTS + +1. Fetch PR metadata and changed files. +2. Inspect CI status and failing jobs. +3. Review diff for correctness, security, tests, performance, and maintainability. +4. Use staff-code-reviewer for a cold review when useful. +5. Output MUST FIX / SHOULD FIX / CONSIDER / VERDICT. +6. Do not approve or request changes externally unless explicitly instructed. diff --git a/.claude/commands/ship.md b/.claude/commands/ship.md new file mode 100644 index 000000000..228654f20 --- /dev/null +++ b/.claude/commands/ship.md @@ -0,0 +1,9 @@ +Ship the current branch safely. + +1. Read git status and current branch. Stop if on main/master. +2. Summarize changed files and intent from diff. +3. Run project gates: typecheck, build, tests, lint/format where available. +4. Invoke staff-code-reviewer and security-auditor on the diff. +5. Fix MUST/CRITICAL/HIGH items only after explaining them. +6. Ensure PR exists or create one with summary, tests, risks, and linked issues. +7. Final output: branch, PR URL, commits, gate results, unresolved risks. diff --git a/.claude/hooks/block-dangerous.sh b/.claude/hooks/block-dangerous.sh new file mode 100755 index 000000000..acfc5d563 --- /dev/null +++ b/.claude/hooks/block-dangerous.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail +payload="$(cat || true)" +cmd="$(printf '%s' "$payload" | python3 -c 'import json,sys +try: + data=json.load(sys.stdin) + print((data.get("tool_input") or {}).get("command", "")) +except Exception: + print("")')" +if printf '%s' "$cmd" | grep -Eiq '(^|[;&|[:space:]])(sudo|rm[[:space:]]+-rf[[:space:]]+/|chmod[[:space:]]+777|git[[:space:]]+push[[:space:]].*--force|git[[:space:]]+reset[[:space:]]+--hard|npm[[:space:]]+publish|curl[^ +]*\|[[:space:]]*(sh|bash)|wget[^ +]*\|[[:space:]]*(sh|bash))'; then + echo "Blocked dangerous command: $cmd" + exit 2 +fi +exit 0 diff --git a/.claude/hooks/pre-commit-gates.sh b/.claude/hooks/pre-commit-gates.sh new file mode 100755 index 000000000..ff0da883c --- /dev/null +++ b/.claude/hooks/pre-commit-gates.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail +root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +cd "$root" + +# Hyperframes uses bun + oxlint/oxfmt. Do not introduce pnpm/npm workspace commands. +commands=( + "bun run build" + "bun run lint" + "bun run test" +) + +failures=0 +for c in "${commands[@]}"; do + echo "▶ $c" + if ! bash -lc "$c"; then + failures=$((failures+1)) + fi +done + +if [ "$failures" -gt 0 ]; then + echo "Hyperframes pre-commit gates failed ($failures). Fix before committing." + exit 2 +fi +exit 0 diff --git a/.claude/hooks/session-summary.sh b/.claude/hooks/session-summary.sh new file mode 100755 index 000000000..aaaf40e5a --- /dev/null +++ b/.claude/hooks/session-summary.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail +root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +mkdir -p "$root/.claude/session-summaries" +ts="$(date +%Y%m%dT%H%M%S%z)" +out="$root/.claude/session-summaries/$ts.md" +{ + echo "# Claude Session Summary — $ts" + echo + echo "## Git status" + git -C "$root" status --short || true + echo + echo "## Recent commits" + git -C "$root" log --oneline -5 || true + echo + echo "## Reminder" + echo "Before compaction or handoff, preserve modified files, test status, unresolved issues, decisions, PR/issue links, and next command." +} > "$out" +echo "Session summary written: $out" diff --git a/.claude/settings.json b/.claude/settings.json index fa4bc827c..40035ba58 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,15 +1,81 @@ { + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "permissions": { + "allow": [ + "Read(.)", + "Read(./**)", + "Edit(./**)", + "Write(./**)", + "Bash(git status*)", + "Bash(git diff*)", + "Bash(git log*)", + "Bash(git branch*)", + "Bash(git checkout*)", + "Bash(git add*)", + "Bash(git commit*)", + "Bash(gh pr *)", + "Bash(gh issue *)", + "Bash(bun *)", + "Bash(bunx oxlint*)", + "Bash(bunx oxfmt*)", + "Bash(npx hyperframes lint*)", + "Bash(npx hyperframes validate*)", + "Bash(node *)", + "Bash(python3 *)" + ], + "ask": [ + "Bash(git push*)", + "Bash(gh pr merge*)", + "Bash(gh issue close*)", + "Bash(npm publish*)" + ], + "deny": [ + "Read(.env*)", + "Read(**/.env*)", + "Read(**/*secret*)", + "Read(**/*.pem)", + "Read(**/*.key)", + "Edit(.env*)", + "Edit(**/.env*)", + "Edit(**/*secret*)", + "Edit(**/*.pem)", + "Edit(**/*.key)", + "Bash(rm -rf /)", + "Bash(rm -rf ~)", + "Bash(rm -rf /*)", + "Bash(sudo *)", + "Bash(chmod 777 *)", + "Bash(curl * | sh)", + "Bash(curl * | bash)", + "Bash(wget * | sh)", + "Bash(eval *)", + "Bash(git push --force*)", + "Bash(git push -f *)", + "Bash(git reset --hard*)", + "Bash(npm publish*)" + ], + "defaultMode": "acceptEdits" + }, + "enableAllProjectMcpServers": false, "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ - { - "type": "command", - "timeout": 180, - "statusMessage": "Running build + lint + typecheck before commit…", - "command": "node -e \"\nconst chunks = [];\nprocess.stdin.on('data', d => chunks.push(d));\nprocess.stdin.on('end', () => {\n const input = JSON.parse(Buffer.concat(chunks).toString());\n const cmd = input.tool_input?.command || '';\n if (!/git\\\\s+commit\\\\b/.test(cmd)) process.exit(0);\n const { execSync } = require('child_process');\n const cwd = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n const steps = [\n ['bun run build', 'Build'],\n ['bun run lint', 'Lint'],\n ['bun run --filter \\'*\\' typecheck 2>&1 | grep -v \\'vitest\\\\|test\\\\.ts\\' || true', 'Typecheck'],\n ];\n const failures = [];\n for (const [script, label] of steps) {\n try { execSync(script, { cwd, stdio: 'pipe' }); }\n catch (e) {\n failures.push(label + ':\\\\n' + (e.stdout?.toString() || e.message).slice(0, 400));\n }\n }\n if (failures.length > 0) {\n process.stdout.write(JSON.stringify({\n continue: false,\n stopReason: '\\u274c Pre-commit checks failed:\\\\n\\\\n' + failures.join('\\\\n\\\\n') + '\\\\n\\\\nFix the issues above before committing.',\n }));\n }\n});\"" - } + { "type": "command", "command": "bash .claude/hooks/block-dangerous.sh" } + ] + }, + { + "matcher": "Bash(git commit*)", + "hooks": [ + { "type": "command", "timeout": 180, "statusMessage": "Running Hyperframes build/test before commit…", "command": "bash .claude/hooks/pre-commit-gates.sh" } + ] + } + ], + "Stop": [ + { + "hooks": [ + { "type": "command", "command": "bash .claude/hooks/session-summary.sh" } ] } ]