qualia-framework 2.6.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +64 -0
- package/README.md +103 -30
- package/agents/builder.md +110 -0
- package/agents/planner.md +134 -0
- package/agents/qa-browser.md +186 -0
- package/agents/verifier.md +221 -0
- package/bin/cli.js +336 -531
- package/bin/install.js +570 -0
- package/bin/qualia-ui.js +299 -0
- package/bin/state.js +630 -0
- package/bin/statusline.js +252 -0
- package/guide.md +63 -0
- package/hooks/auto-update.js +139 -0
- package/hooks/branch-guard.js +47 -0
- package/hooks/migration-guard.js +60 -0
- package/hooks/pre-compact.js +32 -0
- package/hooks/pre-deploy-gate.js +110 -0
- package/hooks/pre-push.js +33 -0
- package/hooks/session-start.js +170 -0
- package/package.json +29 -20
- package/rules/design-reference.md +179 -0
- package/rules/frontend.md +126 -0
- package/skills/qualia/SKILL.md +87 -0
- package/skills/qualia-build/SKILL.md +97 -0
- package/skills/qualia-debug/SKILL.md +87 -0
- package/skills/qualia-design/SKILL.md +93 -0
- package/skills/qualia-handoff/SKILL.md +66 -0
- package/skills/qualia-idk/SKILL.md +8 -0
- package/skills/qualia-learn/SKILL.md +88 -0
- package/skills/qualia-new/SKILL.md +323 -0
- package/{framework/skills → skills}/qualia-optimize/SKILL.md +1 -1
- package/skills/qualia-pause/SKILL.md +63 -0
- package/skills/qualia-plan/SKILL.md +101 -0
- package/skills/qualia-polish/SKILL.md +157 -0
- package/skills/qualia-quick/SKILL.md +37 -0
- package/skills/qualia-report/SKILL.md +105 -0
- package/skills/qualia-resume/SKILL.md +49 -0
- package/skills/qualia-review/SKILL.md +76 -0
- package/skills/qualia-ship/SKILL.md +90 -0
- package/skills/qualia-skill-new/SKILL.md +167 -0
- package/skills/qualia-task/SKILL.md +91 -0
- package/skills/qualia-verify/SKILL.md +113 -0
- package/templates/DESIGN.md +137 -0
- package/templates/plan.md +28 -0
- package/templates/project.md +22 -0
- package/templates/state.md +27 -0
- package/templates/tracking.json +20 -0
- package/tests/bin.test.sh +673 -0
- package/tests/hooks.test.sh +315 -0
- package/tests/state.test.sh +535 -0
- package/tests/statusline.test.sh +243 -0
- package/bin/collect-metrics.sh +0 -62
- package/framework/.claudeignore +0 -51
- package/framework/CLAUDE.md +0 -51
- package/framework/MCP_SETUP.md +0 -229
- package/framework/agents/architecture-strategist.md +0 -53
- package/framework/agents/backend-agent.md +0 -150
- package/framework/agents/code-simplicity-reviewer.md +0 -86
- package/framework/agents/frontend-agent.md +0 -111
- package/framework/agents/kieran-typescript-reviewer.md +0 -96
- package/framework/agents/performance-oracle.md +0 -111
- package/framework/agents/qualia-codebase-mapper.md +0 -761
- package/framework/agents/qualia-debugger.md +0 -1204
- package/framework/agents/qualia-executor.md +0 -882
- package/framework/agents/qualia-integration-checker.md +0 -424
- package/framework/agents/qualia-phase-researcher.md +0 -457
- package/framework/agents/qualia-plan-checker.md +0 -700
- package/framework/agents/qualia-planner.md +0 -1245
- package/framework/agents/qualia-project-researcher.md +0 -603
- package/framework/agents/qualia-research-synthesizer.md +0 -200
- package/framework/agents/qualia-roadmapper.md +0 -606
- package/framework/agents/qualia-verifier.md +0 -686
- package/framework/agents/red-team-qa.md +0 -130
- package/framework/agents/security-auditor.md +0 -72
- package/framework/agents/team-orchestrator.md +0 -229
- package/framework/agents/teams/framework-audit-team.md +0 -66
- package/framework/agents/teams/full-stack-team.md +0 -48
- package/framework/agents/teams/optimize-team.md +0 -53
- package/framework/agents/teams/review-team.md +0 -70
- package/framework/agents/teams/ship-team.md +0 -86
- package/framework/agents/test-agent.md +0 -182
- package/framework/hooks/auto-format.sh +0 -54
- package/framework/hooks/block-env-edit.sh +0 -42
- package/framework/hooks/branch-guard.sh +0 -43
- package/framework/hooks/confirm-delete.sh +0 -59
- package/framework/hooks/migration-validate.sh +0 -77
- package/framework/hooks/notification-speak.sh +0 -16
- package/framework/hooks/pre-commit.sh +0 -100
- package/framework/hooks/pre-compact.sh +0 -56
- package/framework/hooks/pre-deploy-gate.sh +0 -160
- package/framework/hooks/qualia-colors.sh +0 -32
- package/framework/hooks/retention-cleanup.sh +0 -62
- package/framework/hooks/save-session-state.sh +0 -185
- package/framework/hooks/session-context-loader.sh +0 -96
- package/framework/hooks/session-learn.sh +0 -32
- package/framework/hooks/skill-announce.sh +0 -123
- package/framework/hooks/tool-error-announce.sh +0 -27
- package/framework/install.ps1 +0 -323
- package/framework/install.sh +0 -313
- package/framework/qualia-framework/VERSION +0 -1
- package/framework/qualia-framework/assets/qualia-logo.png +0 -0
- package/framework/qualia-framework/bin/collect-metrics.sh +0 -67
- package/framework/qualia-framework/bin/generate-report-docx.py +0 -429
- package/framework/qualia-framework/bin/qualia-tools.js +0 -2201
- package/framework/qualia-framework/bin/qualia-tools.test.js +0 -1054
- package/framework/qualia-framework/references/checkpoints.md +0 -775
- package/framework/qualia-framework/references/completion-checklists.md +0 -359
- package/framework/qualia-framework/references/continuation-format.md +0 -249
- package/framework/qualia-framework/references/continuation-prompt.md +0 -97
- package/framework/qualia-framework/references/decimal-phase-calculation.md +0 -65
- package/framework/qualia-framework/references/design-quality.md +0 -56
- package/framework/qualia-framework/references/employee-guide.md +0 -167
- package/framework/qualia-framework/references/git-integration.md +0 -254
- package/framework/qualia-framework/references/git-planning-commit.md +0 -50
- package/framework/qualia-framework/references/model-profile-resolution.md +0 -32
- package/framework/qualia-framework/references/model-profiles.md +0 -73
- package/framework/qualia-framework/references/phase-argument-parsing.md +0 -61
- package/framework/qualia-framework/references/planning-config.md +0 -195
- package/framework/qualia-framework/references/questioning.md +0 -141
- package/framework/qualia-framework/references/tdd.md +0 -263
- package/framework/qualia-framework/references/ui-brand.md +0 -160
- package/framework/qualia-framework/references/verification-patterns.md +0 -612
- package/framework/qualia-framework/templates/DEBUG.md +0 -159
- package/framework/qualia-framework/templates/DESIGN.md +0 -81
- package/framework/qualia-framework/templates/UAT.md +0 -247
- package/framework/qualia-framework/templates/codebase/architecture.md +0 -255
- package/framework/qualia-framework/templates/codebase/concerns.md +0 -310
- package/framework/qualia-framework/templates/codebase/conventions.md +0 -307
- package/framework/qualia-framework/templates/codebase/integrations.md +0 -280
- package/framework/qualia-framework/templates/codebase/stack.md +0 -186
- package/framework/qualia-framework/templates/codebase/structure.md +0 -285
- package/framework/qualia-framework/templates/codebase/testing.md +0 -480
- package/framework/qualia-framework/templates/config.json +0 -35
- package/framework/qualia-framework/templates/context.md +0 -283
- package/framework/qualia-framework/templates/continue-here.md +0 -78
- package/framework/qualia-framework/templates/debug-subagent-prompt.md +0 -91
- package/framework/qualia-framework/templates/discovery.md +0 -146
- package/framework/qualia-framework/templates/lab-notes.md +0 -16
- package/framework/qualia-framework/templates/milestone-archive.md +0 -123
- package/framework/qualia-framework/templates/milestone.md +0 -115
- package/framework/qualia-framework/templates/phase-prompt.md +0 -567
- package/framework/qualia-framework/templates/planner-subagent-prompt.md +0 -117
- package/framework/qualia-framework/templates/project.md +0 -184
- package/framework/qualia-framework/templates/projects/ai-agent.md +0 -156
- package/framework/qualia-framework/templates/projects/mobile-app.md +0 -181
- package/framework/qualia-framework/templates/projects/voice-agent.md +0 -134
- package/framework/qualia-framework/templates/projects/website.md +0 -137
- package/framework/qualia-framework/templates/requirements.md +0 -231
- package/framework/qualia-framework/templates/research-project/ARCHITECTURE.md +0 -204
- package/framework/qualia-framework/templates/research-project/FEATURES.md +0 -147
- package/framework/qualia-framework/templates/research-project/PITFALLS.md +0 -200
- package/framework/qualia-framework/templates/research-project/STACK.md +0 -120
- package/framework/qualia-framework/templates/research-project/SUMMARY.md +0 -170
- package/framework/qualia-framework/templates/research.md +0 -552
- package/framework/qualia-framework/templates/roadmap.md +0 -206
- package/framework/qualia-framework/templates/state.md +0 -179
- package/framework/qualia-framework/templates/summary-complex.md +0 -59
- package/framework/qualia-framework/templates/summary-minimal.md +0 -41
- package/framework/qualia-framework/templates/summary-standard.md +0 -48
- package/framework/qualia-framework/templates/summary.md +0 -246
- package/framework/qualia-framework/templates/user-setup.md +0 -311
- package/framework/qualia-framework/templates/verification-report.md +0 -322
- package/framework/qualia-framework/workflows/add-phase.md +0 -179
- package/framework/qualia-framework/workflows/add-todo.md +0 -157
- package/framework/qualia-framework/workflows/audit-milestone.md +0 -241
- package/framework/qualia-framework/workflows/check-todos.md +0 -176
- package/framework/qualia-framework/workflows/complete-milestone.md +0 -858
- package/framework/qualia-framework/workflows/diagnose-issues.md +0 -219
- package/framework/qualia-framework/workflows/discovery-phase.md +0 -289
- package/framework/qualia-framework/workflows/discuss-phase.md +0 -534
- package/framework/qualia-framework/workflows/execute-phase.md +0 -559
- package/framework/qualia-framework/workflows/execute-plan.md +0 -438
- package/framework/qualia-framework/workflows/help.md +0 -470
- package/framework/qualia-framework/workflows/insert-phase.md +0 -220
- package/framework/qualia-framework/workflows/list-phase-assumptions.md +0 -178
- package/framework/qualia-framework/workflows/map-codebase.md +0 -327
- package/framework/qualia-framework/workflows/new-milestone.md +0 -363
- package/framework/qualia-framework/workflows/new-project.md +0 -982
- package/framework/qualia-framework/workflows/pause-work.md +0 -122
- package/framework/qualia-framework/workflows/plan-milestone-gaps.md +0 -256
- package/framework/qualia-framework/workflows/plan-phase.md +0 -422
- package/framework/qualia-framework/workflows/progress.md +0 -389
- package/framework/qualia-framework/workflows/quick.md +0 -252
- package/framework/qualia-framework/workflows/remove-phase.md +0 -326
- package/framework/qualia-framework/workflows/research-phase.md +0 -74
- package/framework/qualia-framework/workflows/resume-project.md +0 -306
- package/framework/qualia-framework/workflows/set-profile.md +0 -80
- package/framework/qualia-framework/workflows/settings.md +0 -145
- package/framework/qualia-framework/workflows/transition.md +0 -556
- package/framework/qualia-framework/workflows/update.md +0 -197
- package/framework/qualia-framework/workflows/verify-phase.md +0 -195
- package/framework/qualia-framework/workflows/verify-work.md +0 -625
- package/framework/rules/context7.md +0 -14
- package/framework/rules/frontend.md +0 -33
- package/framework/rules/speed.md +0 -23
- package/framework/scripts/__pycache__/say.cpython-314.pyc +0 -0
- package/framework/scripts/apply-retention.sh +0 -120
- package/framework/scripts/bootstrap-pop-os.sh +0 -354
- package/framework/scripts/claude-voice +0 -13
- package/framework/scripts/cleanup.sh +0 -131
- package/framework/scripts/cowork-mode.sh +0 -141
- package/framework/scripts/generate-project-claude-md.sh +0 -153
- package/framework/scripts/load-test-webhook.js +0 -172
- package/framework/scripts/say.py +0 -236
- package/framework/scripts/showcase-video-recorder/ffmpeg-builder.js +0 -167
- package/framework/scripts/showcase-video-recorder/playwright-helpers.js +0 -216
- package/framework/scripts/speak.py +0 -55
- package/framework/scripts/speak.sh +0 -18
- package/framework/scripts/status.sh +0 -138
- package/framework/scripts/sync-to-framework.sh +0 -65
- package/framework/scripts/voice-hotkey.py +0 -227
- package/framework/scripts/voice-input.sh +0 -51
- package/framework/skills/animate/SKILL.md +0 -202
- package/framework/skills/bolder/SKILL.md +0 -144
- package/framework/skills/browser-qa/SKILL.md +0 -536
- package/framework/skills/clarify/SKILL.md +0 -179
- package/framework/skills/client-handoff/SKILL.md +0 -135
- package/framework/skills/collab-onboard/SKILL.md +0 -111
- package/framework/skills/colorize/SKILL.md +0 -170
- package/framework/skills/critique/SKILL.md +0 -126
- package/framework/skills/deep-research/SKILL.md +0 -240
- package/framework/skills/delight/SKILL.md +0 -329
- package/framework/skills/deploy/SKILL.md +0 -261
- package/framework/skills/deploy-verify/SKILL.md +0 -377
- package/framework/skills/deploy-verify/scripts/canary-check.sh +0 -206
- package/framework/skills/deploy-verify/scripts/check-console-errors.js +0 -147
- package/framework/skills/deploy-verify/scripts/check-cwv.js +0 -139
- package/framework/skills/deploy-verify/scripts/project-detect.sh +0 -84
- package/framework/skills/deploy-verify/scripts/verify.sh +0 -548
- package/framework/skills/design-quieter/SKILL.md +0 -130
- package/framework/skills/distill/SKILL.md +0 -149
- package/framework/skills/docs-lookup/SKILL.md +0 -79
- package/framework/skills/fcm-notifications/SKILL.md +0 -125
- package/framework/skills/financial-ledger/SKILL.md +0 -1039
- package/framework/skills/frontend-master/NOTICE.md +0 -4
- package/framework/skills/frontend-master/SKILL.md +0 -127
- package/framework/skills/frontend-master/reference/color-and-contrast.md +0 -132
- package/framework/skills/frontend-master/reference/interaction-design.md +0 -123
- package/framework/skills/frontend-master/reference/motion-design.md +0 -99
- package/framework/skills/frontend-master/reference/responsive-design.md +0 -114
- package/framework/skills/frontend-master/reference/spatial-design.md +0 -100
- package/framework/skills/frontend-master/reference/typography.md +0 -131
- package/framework/skills/frontend-master/reference/ux-writing.md +0 -107
- package/framework/skills/harden/SKILL.md +0 -357
- package/framework/skills/i18n-rtl/SKILL.md +0 -752
- package/framework/skills/learn/SKILL.md +0 -95
- package/framework/skills/memory/SKILL.md +0 -50
- package/framework/skills/mobile-expo/SKILL.md +0 -977
- package/framework/skills/mobile-expo/references/store-checklist.md +0 -550
- package/framework/skills/nestjs-backend/README.md +0 -73
- package/framework/skills/nestjs-backend/SKILL.md +0 -446
- package/framework/skills/nestjs-backend/references/templates.md +0 -1173
- package/framework/skills/normalize/SKILL.md +0 -79
- package/framework/skills/onboard/SKILL.md +0 -242
- package/framework/skills/openrouter-agent/SKILL.md +0 -922
- package/framework/skills/polish/SKILL.md +0 -209
- package/framework/skills/pr/SKILL.md +0 -66
- package/framework/skills/qualia/SKILL.md +0 -199
- package/framework/skills/qualia-add-todo/SKILL.md +0 -68
- package/framework/skills/qualia-audit-milestone/SKILL.md +0 -95
- package/framework/skills/qualia-check-todos/SKILL.md +0 -55
- package/framework/skills/qualia-complete-milestone/SKILL.md +0 -134
- package/framework/skills/qualia-debug/SKILL.md +0 -149
- package/framework/skills/qualia-design/SKILL.md +0 -203
- package/framework/skills/qualia-discuss-phase/SKILL.md +0 -72
- package/framework/skills/qualia-evolve/SKILL.md +0 -200
- package/framework/skills/qualia-execute-phase/SKILL.md +0 -89
- package/framework/skills/qualia-framework-audit/SKILL.md +0 -604
- package/framework/skills/qualia-guide/SKILL.md +0 -32
- package/framework/skills/qualia-help/SKILL.md +0 -114
- package/framework/skills/qualia-idk/SKILL.md +0 -352
- package/framework/skills/qualia-list-phase-assumptions/SKILL.md +0 -67
- package/framework/skills/qualia-new-milestone/SKILL.md +0 -72
- package/framework/skills/qualia-new-project/SKILL.md +0 -232
- package/framework/skills/qualia-pause-work/SKILL.md +0 -96
- package/framework/skills/qualia-plan-milestone-gaps/SKILL.md +0 -57
- package/framework/skills/qualia-plan-phase/SKILL.md +0 -104
- package/framework/skills/qualia-production-check/SKILL.md +0 -0
- package/framework/skills/qualia-progress/SKILL.md +0 -53
- package/framework/skills/qualia-quick/SKILL.md +0 -89
- package/framework/skills/qualia-report/SKILL.md +0 -166
- package/framework/skills/qualia-research-phase/SKILL.md +0 -88
- package/framework/skills/qualia-resume-work/SKILL.md +0 -62
- package/framework/skills/qualia-review/SKILL.md +0 -263
- package/framework/skills/qualia-start/SKILL.md +0 -161
- package/framework/skills/qualia-verify-work/SKILL.md +0 -132
- package/framework/skills/rag/SKILL.md +0 -750
- package/framework/skills/responsive/SKILL.md +0 -231
- package/framework/skills/retro/SKILL.md +0 -284
- package/framework/skills/sakani-conventions/SKILL.md +0 -136
- package/framework/skills/sakani-conventions/evals/evals.json +0 -23
- package/framework/skills/sakani-conventions/references/entities.md +0 -365
- package/framework/skills/sakani-conventions/references/error-codes.md +0 -95
- package/framework/skills/seo-master/SKILL.md +0 -490
- package/framework/skills/seo-master/references/checklist.md +0 -199
- package/framework/skills/seo-master/references/structured-data.md +0 -609
- package/framework/skills/ship/SKILL.md +0 -239
- package/framework/skills/stack-researcher/SKILL.md +0 -215
- package/framework/skills/status/SKILL.md +0 -154
- package/framework/skills/status/scripts/health-check.sh +0 -562
- package/framework/skills/subscription-payments/SKILL.md +0 -250
- package/framework/skills/supabase/SKILL.md +0 -973
- package/framework/skills/supabase/references/templates.md +0 -159
- package/framework/skills/team/SKILL.md +0 -67
- package/framework/skills/test-runner/SKILL.md +0 -202
- package/framework/skills/voice-agent/SKILL.md +0 -1312
- package/framework/skills/zoho-workflow/SKILL.md +0 -51
- package/framework/statusline-command.sh +0 -117
- package/framework/teams/default/inboxes/plan-04.json +0 -9
- package/framework/teams/review-team.md +0 -75
- package/framework/teams/ship-team.md +0 -86
- package/profiles/fawzi.json +0 -16
- package/profiles/hasan.json +0 -16
- package/profiles/moayad.json +0 -16
- package/templates/CLAUDE-owner.md +0 -52
- package/templates/CLAUDE.md.hbs +0 -58
- package/templates/env.claude.template +0 -12
- package/templates/settings.json +0 -172
- package/uninstall.sh +0 -90
- /package/{framework/rules → rules}/deployment.md +0 -0
- /package/{framework/rules → rules}/security.md +0 -0
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# Ship Team
|
|
2
|
-
|
|
3
|
-
> Quality gate → Deploy → Verify. Pipeline pattern — abort if any step fails.
|
|
4
|
-
|
|
5
|
-
## Agents
|
|
6
|
-
|
|
7
|
-
- **quality-gate**
|
|
8
|
-
- subagent_type: test-agent
|
|
9
|
-
- role: Run tsc, eslint, build. Ensure no type errors, lint violations, or build failures.
|
|
10
|
-
- commands: |
|
|
11
|
-
npx tsc --noEmit
|
|
12
|
-
npx next lint (or eslint .)
|
|
13
|
-
npm run build (or next build)
|
|
14
|
-
- abort_on_fail: true
|
|
15
|
-
|
|
16
|
-
- **deploy**
|
|
17
|
-
- subagent_type: backend-agent
|
|
18
|
-
- role: Commit staged changes, push to remote, deploy to hosting platform
|
|
19
|
-
- commands: |
|
|
20
|
-
git add -A && git commit (if uncommitted changes)
|
|
21
|
-
git push origin {branch}
|
|
22
|
-
vercel --prod (default) OR wrangler deploy (if armenius)
|
|
23
|
-
- abort_on_fail: true
|
|
24
|
-
|
|
25
|
-
- **verify**
|
|
26
|
-
- subagent_type: test-agent
|
|
27
|
-
- role: Run 6-check post-deploy verification against production URL
|
|
28
|
-
- checks: |
|
|
29
|
-
1. HTTP 200 — homepage loads
|
|
30
|
-
2. Auth flow — login/signup endpoint responds
|
|
31
|
-
3. Console errors — no critical JS errors
|
|
32
|
-
4. API latency — key endpoints < 500ms
|
|
33
|
-
5. SSL — valid certificate
|
|
34
|
-
6. Build artifacts — no source maps exposed
|
|
35
|
-
- abort_on_fail: false (report issues but don't rollback)
|
|
36
|
-
|
|
37
|
-
## Pattern
|
|
38
|
-
|
|
39
|
-
pipeline: quality-gate → deploy → verify
|
|
40
|
-
|
|
41
|
-
Each step must succeed before the next begins. If quality-gate fails, deployment is blocked. If deploy fails, verification is skipped.
|
|
42
|
-
|
|
43
|
-
## Shared Context
|
|
44
|
-
|
|
45
|
-
- ~/.claude/knowledge/qualia-context.md — project inventory, deploy commands, Supabase refs
|
|
46
|
-
- .planning/STATE.md — current project state
|
|
47
|
-
- Project's local CLAUDE.md — project-specific deploy config
|
|
48
|
-
|
|
49
|
-
## Coordination Rules
|
|
50
|
-
|
|
51
|
-
- quality-gate runs ALL checks before passing — partial pass is a fail
|
|
52
|
-
- deploy detects hosting platform from project context (Vercel default, Cloudflare for armenius)
|
|
53
|
-
- verify uses the production URL from deploy output
|
|
54
|
-
- If Supabase project: deploy also runs `supabase db push` if pending migrations exist
|
|
55
|
-
|
|
56
|
-
## Output
|
|
57
|
-
|
|
58
|
-
SHIP-REPORT.md in current directory:
|
|
59
|
-
|
|
60
|
-
```markdown
|
|
61
|
-
# Ship Report
|
|
62
|
-
|
|
63
|
-
**Date:** {date}
|
|
64
|
-
**Branch:** {branch}
|
|
65
|
-
**Deploy URL:** {url}
|
|
66
|
-
|
|
67
|
-
## Quality Gate
|
|
68
|
-
- tsc: ✓ / ✗ ({error count})
|
|
69
|
-
- lint: ✓ / ✗ ({warning count})
|
|
70
|
-
- build: ✓ / ✗ ({duration})
|
|
71
|
-
|
|
72
|
-
## Deployment
|
|
73
|
-
- Platform: Vercel / Cloudflare
|
|
74
|
-
- URL: {production url}
|
|
75
|
-
- Commit: {sha}
|
|
76
|
-
|
|
77
|
-
## Verification
|
|
78
|
-
| Check | Status | Details |
|
|
79
|
-
|-------|--------|---------|
|
|
80
|
-
| HTTP 200 | ✓/✗ | {status code} |
|
|
81
|
-
| Auth flow | ✓/✗ | {details} |
|
|
82
|
-
| Console errors | ✓/✗ | {count} |
|
|
83
|
-
| API latency | ✓/✗ | {ms} |
|
|
84
|
-
| SSL | ✓/✗ | {expiry} |
|
|
85
|
-
| Source maps | ✓/✗ | {exposed?} |
|
|
86
|
-
```
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: test-agent
|
|
3
|
-
description: Testing and QA specialist - unit tests, integration tests, E2E with Playwright. Spawned for parallel test development.
|
|
4
|
-
category: testing
|
|
5
|
-
tools: Read, Write, Edit, Glob, Grep, Bash
|
|
6
|
-
model: inherit
|
|
7
|
-
tags: [testing, jest, vitest, playwright, qa]
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Test Agent
|
|
11
|
-
|
|
12
|
-
Specialized agent for testing and QA. Spawned for parallel test development.
|
|
13
|
-
|
|
14
|
-
## Capabilities
|
|
15
|
-
|
|
16
|
-
- Write unit tests (Jest, Vitest)
|
|
17
|
-
- Write integration tests
|
|
18
|
-
- Create E2E tests (Playwright)
|
|
19
|
-
- Generate test fixtures
|
|
20
|
-
- Analyze code coverage
|
|
21
|
-
- Find edge cases
|
|
22
|
-
|
|
23
|
-
## When to Spawn
|
|
24
|
-
|
|
25
|
-
Use this agent when:
|
|
26
|
-
- Writing tests in parallel with implementation
|
|
27
|
-
- Need comprehensive test coverage
|
|
28
|
-
- E2E testing for user flows
|
|
29
|
-
- Test debugging and fixes
|
|
30
|
-
|
|
31
|
-
## Tools Available
|
|
32
|
-
|
|
33
|
-
| Tool | Purpose |
|
|
34
|
-
|------|---------|
|
|
35
|
-
| Read | Read code to test |
|
|
36
|
-
| Write | Create test files |
|
|
37
|
-
| Edit | Fix existing tests |
|
|
38
|
-
| Glob | Find test files |
|
|
39
|
-
| Grep | Search for patterns |
|
|
40
|
-
| Bash | Run tests |
|
|
41
|
-
|
|
42
|
-
## Example Tasks
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
"Write tests for the ProfileCard component"
|
|
46
|
-
"Create E2E test for the checkout flow"
|
|
47
|
-
"Add integration tests for the API endpoints"
|
|
48
|
-
"Fix the failing user registration tests"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## My Process
|
|
52
|
-
|
|
53
|
-
1. **Analyze code** - Understand what to test
|
|
54
|
-
2. **Identify test cases** - Happy paths, edge cases, errors
|
|
55
|
-
3. **Write tests** - Clean, descriptive tests
|
|
56
|
-
4. **Run tests** - Verify they work
|
|
57
|
-
5. **Check coverage** - Ensure adequate coverage
|
|
58
|
-
6. **Report back** - Return test summary
|
|
59
|
-
|
|
60
|
-
## Constraints
|
|
61
|
-
|
|
62
|
-
- Focus on testing, not implementation
|
|
63
|
-
- Use project's test framework
|
|
64
|
-
- Follow existing test patterns
|
|
65
|
-
- Don't modify production code (unless fixing test setup)
|
|
66
|
-
|
|
67
|
-
## Output Format
|
|
68
|
-
|
|
69
|
-
When done, I return:
|
|
70
|
-
```markdown
|
|
71
|
-
## Testing Complete
|
|
72
|
-
|
|
73
|
-
### Tests Created
|
|
74
|
-
- __tests__/ProfileCard.test.tsx (8 tests)
|
|
75
|
-
- e2e/checkout.spec.ts (5 tests)
|
|
76
|
-
|
|
77
|
-
### Coverage Summary
|
|
78
|
-
| File | Statements | Branches | Functions | Lines |
|
|
79
|
-
|------|------------|----------|-----------|-------|
|
|
80
|
-
| ProfileCard.tsx | 95% | 88% | 100% | 95% |
|
|
81
|
-
|
|
82
|
-
### Test Cases
|
|
83
|
-
**Unit Tests:**
|
|
84
|
-
- ✅ renders user profile
|
|
85
|
-
- ✅ shows loading skeleton
|
|
86
|
-
- ✅ handles edit click
|
|
87
|
-
- ✅ displays error state
|
|
88
|
-
|
|
89
|
-
**E2E Tests:**
|
|
90
|
-
- ✅ complete checkout flow
|
|
91
|
-
- ✅ handles payment failure
|
|
92
|
-
- ✅ applies discount code
|
|
93
|
-
|
|
94
|
-
### Run Command
|
|
95
|
-
\`\`\`bash
|
|
96
|
-
npm test ProfileCard
|
|
97
|
-
npx playwright test checkout
|
|
98
|
-
\`\`\`
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Spawn Example
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
// From main orchestrator
|
|
105
|
-
await Task({
|
|
106
|
-
subagent_type: "test-agent",
|
|
107
|
-
prompt: "Write comprehensive tests for the ProfileCard component including: render states, user interactions, loading skeleton, error handling.",
|
|
108
|
-
run_in_background: true
|
|
109
|
-
});
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Test Patterns
|
|
113
|
-
|
|
114
|
-
### Component Test Template
|
|
115
|
-
```typescript
|
|
116
|
-
import { render, screen } from '@testing-library/react';
|
|
117
|
-
import userEvent from '@testing-library/user-event';
|
|
118
|
-
import { Component } from './Component';
|
|
119
|
-
|
|
120
|
-
describe('Component', () => {
|
|
121
|
-
it('renders correctly', () => {
|
|
122
|
-
render(<Component />);
|
|
123
|
-
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('handles user interaction', async () => {
|
|
127
|
-
const onClick = vi.fn();
|
|
128
|
-
render(<Component onClick={onClick} />);
|
|
129
|
-
await userEvent.click(screen.getByRole('button'));
|
|
130
|
-
expect(onClick).toHaveBeenCalled();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('shows loading state', () => {
|
|
134
|
-
render(<Component loading />);
|
|
135
|
-
expect(screen.getByTestId('skeleton')).toBeInTheDocument();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('displays error', () => {
|
|
139
|
-
render(<Component error="Failed" />);
|
|
140
|
-
expect(screen.getByText('Failed')).toBeInTheDocument();
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### E2E Test Template
|
|
146
|
-
```typescript
|
|
147
|
-
import { test, expect } from '@playwright/test';
|
|
148
|
-
|
|
149
|
-
test.describe('Feature', () => {
|
|
150
|
-
test('completes flow', async ({ page }) => {
|
|
151
|
-
await page.goto('/');
|
|
152
|
-
await page.click('button:has-text("Start")');
|
|
153
|
-
await page.fill('input[name="email"]', 'test@example.com');
|
|
154
|
-
await page.click('button:has-text("Submit")');
|
|
155
|
-
await expect(page.locator('.success')).toBeVisible();
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test('handles error', async ({ page }) => {
|
|
159
|
-
await page.route('**/api/**', route => route.fulfill({ status: 500 }));
|
|
160
|
-
await page.goto('/');
|
|
161
|
-
await page.click('button:has-text("Submit")');
|
|
162
|
-
await expect(page.locator('.error')).toBeVisible();
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### API Test Template
|
|
168
|
-
```typescript
|
|
169
|
-
describe('API: /api/users', () => {
|
|
170
|
-
it('returns user list', async () => {
|
|
171
|
-
const response = await fetch('/api/users');
|
|
172
|
-
const data = await response.json();
|
|
173
|
-
expect(response.status).toBe(200);
|
|
174
|
-
expect(data).toHaveProperty('users');
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('requires authentication', async () => {
|
|
178
|
-
const response = await fetch('/api/users');
|
|
179
|
-
expect(response.status).toBe(401);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Auto-format hook for PostToolUse(Write/Edit)
|
|
3
|
-
# Runs prettier on supported file types if available in the project
|
|
4
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
5
|
-
|
|
6
|
-
# Parse file path from stdin JSON (Claude Code hook protocol)
|
|
7
|
-
if [ ! -t 0 ]; then
|
|
8
|
-
INPUT=$(cat)
|
|
9
|
-
FILE_PATH=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.file_path||'')}catch(e){}" 2>/dev/null)
|
|
10
|
-
else
|
|
11
|
-
FILE_PATH=""
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# Skip if no file path
|
|
15
|
-
[ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ] && exit 0
|
|
16
|
-
|
|
17
|
-
# Get file extension
|
|
18
|
-
EXT="${FILE_PATH##*.}"
|
|
19
|
-
|
|
20
|
-
# Only format supported file types
|
|
21
|
-
case "$EXT" in
|
|
22
|
-
ts|tsx|js|jsx|json|css|scss|html|md|yaml|yml) ;;
|
|
23
|
-
*) exit 0 ;;
|
|
24
|
-
esac
|
|
25
|
-
|
|
26
|
-
# Find project root (look for package.json or .git)
|
|
27
|
-
DIR="$(dirname "$FILE_PATH")"
|
|
28
|
-
PROJECT_ROOT=""
|
|
29
|
-
while [ "$DIR" != "/" ]; do
|
|
30
|
-
if [ -f "$DIR/package.json" ] || [ -d "$DIR/.git" ]; then
|
|
31
|
-
PROJECT_ROOT="$DIR"
|
|
32
|
-
break
|
|
33
|
-
fi
|
|
34
|
-
DIR="$(dirname "$DIR")"
|
|
35
|
-
done
|
|
36
|
-
|
|
37
|
-
# Try to format with prettier if available in the project
|
|
38
|
-
if [ -n "$PROJECT_ROOT" ]; then
|
|
39
|
-
if [ -f "$PROJECT_ROOT/node_modules/.bin/prettier" ]; then
|
|
40
|
-
"$PROJECT_ROOT/node_modules/.bin/prettier" --write "$FILE_PATH" 2>/dev/null
|
|
41
|
-
exit 0
|
|
42
|
-
fi
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# No formatter found — notify once per project
|
|
46
|
-
if [ -n "$PROJECT_ROOT" ]; then
|
|
47
|
-
STAMP="/tmp/.no-formatter-$(echo "$PROJECT_ROOT" | md5sum | cut -c1-8)"
|
|
48
|
-
if [ ! -f "$STAMP" ]; then
|
|
49
|
-
touch "$STAMP"
|
|
50
|
-
printf '{"continue":true,"systemMessage":"◆ AUTO-FORMAT: No prettier found in %s — files will not be auto-formatted."}' "$(basename "$PROJECT_ROOT")"
|
|
51
|
-
exit 0
|
|
52
|
-
fi
|
|
53
|
-
fi
|
|
54
|
-
exit 0
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Block .env and credential file editing
|
|
3
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
4
|
-
|
|
5
|
-
if [ ! -t 0 ]; then
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
FILE_PATH=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.file_path||d.tool_input?.filePath||'')}catch(e){}" 2>/dev/null)
|
|
8
|
-
else
|
|
9
|
-
FILE_PATH="${1:-}"
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
if [ -z "$FILE_PATH" ]; then
|
|
13
|
-
printf '{"continue":true}'
|
|
14
|
-
exit 0
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
BASENAME=$(basename "$FILE_PATH")
|
|
18
|
-
|
|
19
|
-
if [[ "$BASENAME" == .env* ]] || [[ "$FILE_PATH" == */.env ]] || [[ "$FILE_PATH" == */.env.* ]]; then
|
|
20
|
-
cat <<EOJSON
|
|
21
|
-
{
|
|
22
|
-
"continue": false,
|
|
23
|
-
"stopReason": "◆ ENV GUARD: editing ${BASENAME} blocked",
|
|
24
|
-
"systemMessage": "◆ BLOCKED: Cannot edit .env files through Claude Code. Tell the user EXACTLY what needs to change: which file, which variable, what value."
|
|
25
|
-
}
|
|
26
|
-
EOJSON
|
|
27
|
-
exit 2
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
if [[ "$FILE_PATH" == *credentials* ]] || [[ "$FILE_PATH" == *secret* ]] || [[ "$FILE_PATH" == *.pem ]] || [[ "$FILE_PATH" == *.key ]]; then
|
|
31
|
-
cat <<EOJSON
|
|
32
|
-
{
|
|
33
|
-
"continue": false,
|
|
34
|
-
"stopReason": "◆ ENV GUARD: credential file blocked",
|
|
35
|
-
"systemMessage": "◆ BLOCKED: Cannot edit credential/secret files through Claude. Tell the user what needs changing."
|
|
36
|
-
}
|
|
37
|
-
EOJSON
|
|
38
|
-
exit 2
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
printf '{"continue":true}'
|
|
42
|
-
exit 0
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Branch protection — role-aware
|
|
3
|
-
# OWNER: allowed to push to main/master
|
|
4
|
-
# DEVELOPER/EMPLOYEE: blocked, told to use /qualia-ship
|
|
5
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
6
|
-
|
|
7
|
-
if [ ! -t 0 ]; then
|
|
8
|
-
INPUT=$(cat)
|
|
9
|
-
COMMAND=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.command||d.tool_input||'')}catch(e){}" 2>/dev/null)
|
|
10
|
-
else
|
|
11
|
-
COMMAND="${1:-}"
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
case "$COMMAND" in
|
|
15
|
-
git\ push*) ;;
|
|
16
|
-
*) exit 0 ;;
|
|
17
|
-
esac
|
|
18
|
-
|
|
19
|
-
BRANCH=$(git branch --show-current 2>/dev/null) || true
|
|
20
|
-
[ -z "$BRANCH" ] && exit 0
|
|
21
|
-
|
|
22
|
-
# Only guard main/master
|
|
23
|
-
if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "master" ]; then
|
|
24
|
-
exit 0
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
# Check role from CLAUDE.md
|
|
28
|
-
ROLE=$(grep -m1 "^## Role:" "$HOME/.claude/CLAUDE.md" 2>/dev/null | sed 's/^## Role: *//')
|
|
29
|
-
|
|
30
|
-
# OWNER can push anywhere
|
|
31
|
-
if [ "$ROLE" = "OWNER" ]; then
|
|
32
|
-
exit 0
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
# DEVELOPER/EMPLOYEE blocked
|
|
36
|
-
cat <<EOJSON
|
|
37
|
-
{
|
|
38
|
-
"continue": false,
|
|
39
|
-
"stopReason": "◆ BRANCH GUARD: push to ${BRANCH} blocked (${ROLE:-unknown} role)",
|
|
40
|
-
"systemMessage": "◆ BLOCKED: As ${ROLE:-DEVELOPER}, cannot push to ${BRANCH}. Use /ship for feature branch workflow."
|
|
41
|
-
}
|
|
42
|
-
EOJSON
|
|
43
|
-
exit 2
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Destructive command guard — blocks dangerous operations
|
|
3
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
4
|
-
|
|
5
|
-
if [ ! -t 0 ]; then
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
COMMAND=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.command||d.tool_input||'')}catch(e){}" 2>/dev/null)
|
|
8
|
-
else
|
|
9
|
-
COMMAND="${1:-}"
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
# Early exit for safe commands
|
|
13
|
-
case "$COMMAND" in
|
|
14
|
-
ls*|cat*|echo*|pwd|cd*|node*|npm\ install*|npm\ run*|npm\ test*|npx*|bun*|pnpm*|grep*|find*|which*|whoami|date|head*|tail*|wc*|sort*|diff*|test*|"["*|true|false|mkdir*|touch*|cp*|mv*|chmod*|stat*|readlink*|basename*|dirname*|realpath*|tsc*|eslint*|prettier*|vitest*|jest*|python*|pip*|curl*|wget*|gh*)
|
|
15
|
-
exit 0
|
|
16
|
-
;;
|
|
17
|
-
esac
|
|
18
|
-
|
|
19
|
-
block() {
|
|
20
|
-
cat <<EOJSON
|
|
21
|
-
{
|
|
22
|
-
"continue": false,
|
|
23
|
-
"stopReason": "◆ BLOCKED: That would $1 — finding a safer way",
|
|
24
|
-
"systemMessage": "◆ BLOCKED: $1. This could cause damage. Find a safer alternative and explain to the user what was blocked and what safer approach you're using instead."
|
|
25
|
-
}
|
|
26
|
-
EOJSON
|
|
27
|
-
exit 2
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
# Dangerous rm patterns
|
|
31
|
-
echo "$COMMAND" | grep -qE 'rm\s+(-rf|-fr|-r)\s+(/|~/|\.\.|[A-Za-z]+/$)' && block "Dangerous recursive delete"
|
|
32
|
-
echo "$COMMAND" | grep -qE 'rm\s.*\s(src/|app/|lib/|components/|public/|pages/|supabase/)' && block "Deleting critical project directory"
|
|
33
|
-
echo "$COMMAND" | grep -qE 'rm\s+(-rf|-fr)\s+\.$' && block "rm -rf current directory"
|
|
34
|
-
|
|
35
|
-
# Dangerous SQL
|
|
36
|
-
echo "$COMMAND" | grep -qiE 'DROP\s+(TABLE|DATABASE|SCHEMA)\s' && block "DROP TABLE/DATABASE/SCHEMA"
|
|
37
|
-
echo "$COMMAND" | grep -qiE 'TRUNCATE\s+TABLE\s' && block "TRUNCATE TABLE"
|
|
38
|
-
echo "$COMMAND" | grep -qiE 'DELETE\s+FROM\s+\w+\s*;' && block "DELETE without WHERE"
|
|
39
|
-
|
|
40
|
-
# Dangerous git
|
|
41
|
-
echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force($|\s)' && ! echo "$COMMAND" | grep -qE '\-\-force-with-lease' && block "git push --force (use --force-with-lease)"
|
|
42
|
-
echo "$COMMAND" | grep -qE 'git\s+reset\s+--hard' && block "git reset --hard discards work"
|
|
43
|
-
echo "$COMMAND" | grep -qE 'git\s+clean\s+-[a-z]*f' && block "git clean -f deletes untracked files"
|
|
44
|
-
|
|
45
|
-
# Supabase destructive
|
|
46
|
-
echo "$COMMAND" | grep -qE 'supabase\s+functions\s+delete' && block "supabase functions delete"
|
|
47
|
-
echo "$COMMAND" | grep -qE 'supabase\s+secrets\s+unset' && block "supabase secrets unset"
|
|
48
|
-
echo "$COMMAND" | grep -qE 'supabase\s+projects\s+delete' && block "supabase projects delete"
|
|
49
|
-
|
|
50
|
-
# Infrastructure
|
|
51
|
-
echo "$COMMAND" | grep -qE 'kubectl\s+delete\s' && block "kubectl delete"
|
|
52
|
-
echo "$COMMAND" | grep -qE 'docker\s+(rm|rmi)\s+-f' && block "docker force remove"
|
|
53
|
-
|
|
54
|
-
# Platform
|
|
55
|
-
echo "$COMMAND" | grep -qiE 'supabase\s+db\s+reset' && block "supabase db reset destroys database"
|
|
56
|
-
echo "$COMMAND" | grep -qiE 'vercel\s+(rm|remove)\s' && block "vercel rm/remove"
|
|
57
|
-
echo "$COMMAND" | grep -qiE 'npm\s+unpublish' && block "npm unpublish"
|
|
58
|
-
|
|
59
|
-
exit 0
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Migration validation — checks SQL for destructive ops and missing RLS
|
|
3
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
4
|
-
|
|
5
|
-
if [ ! -t 0 ]; then
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
FILE_PATH=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.file_path||'')}catch(e){}" 2>/dev/null)
|
|
8
|
-
if [ -z "$FILE_PATH" ]; then
|
|
9
|
-
COMMAND=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.command||d.tool_input||'')}catch(e){}" 2>/dev/null)
|
|
10
|
-
fi
|
|
11
|
-
fi
|
|
12
|
-
|
|
13
|
-
DESTRUCTIVE=0
|
|
14
|
-
WARNINGS_COUNT=0
|
|
15
|
-
|
|
16
|
-
check_sql_file() {
|
|
17
|
-
local file="$1"
|
|
18
|
-
[ ! -f "$file" ] && return 0
|
|
19
|
-
|
|
20
|
-
# Destructive ops → block
|
|
21
|
-
if grep -iE '\bDROP\s+(TABLE|SCHEMA|DATABASE)\b' "$file" > /dev/null 2>&1; then
|
|
22
|
-
q_fail "DROP TABLE/SCHEMA in ${file}"
|
|
23
|
-
DESTRUCTIVE=$((DESTRUCTIVE + 1))
|
|
24
|
-
fi
|
|
25
|
-
if grep -iE '\bTRUNCATE\b' "$file" > /dev/null 2>&1; then
|
|
26
|
-
q_fail "TRUNCATE in ${file}"
|
|
27
|
-
DESTRUCTIVE=$((DESTRUCTIVE + 1))
|
|
28
|
-
fi
|
|
29
|
-
# DELETE-without-WHERE: count DELETEs vs WHERE clauses (per-statement approximation)
|
|
30
|
-
local delete_count=$(grep -ciE '\bDELETE\s+FROM\b' "$file" 2>/dev/null || echo 0)
|
|
31
|
-
local where_count=$(grep -ciE '\bWHERE\b' "$file" 2>/dev/null || echo 0)
|
|
32
|
-
if [ "$delete_count" -gt 0 ] && [ "$delete_count" -gt "$where_count" ]; then
|
|
33
|
-
q_fail "DELETE without WHERE in ${file} (${delete_count} DELETEs, ${where_count} WHEREs)"
|
|
34
|
-
DESTRUCTIVE=$((DESTRUCTIVE + 1))
|
|
35
|
-
fi
|
|
36
|
-
if grep -iE '\bALTER\s+TABLE\b.*\bDROP\s+COLUMN\b' "$file" > /dev/null 2>&1; then
|
|
37
|
-
q_fail "DROP COLUMN in ${file}"
|
|
38
|
-
DESTRUCTIVE=$((DESTRUCTIVE + 1))
|
|
39
|
-
fi
|
|
40
|
-
# Missing RLS → warn only (reminder, not destructive)
|
|
41
|
-
if grep -iE '\bCREATE\s+TABLE\b' "$file" > /dev/null 2>&1 && ! grep -iE '\bENABLE\s+ROW\s+LEVEL\s+SECURITY\b' "$file" > /dev/null 2>&1; then
|
|
42
|
-
q_warn "New table needs RLS in ${file} — tell Claude: 'add RLS policies to the new table'"
|
|
43
|
-
WARNINGS_COUNT=$((WARNINGS_COUNT + 1))
|
|
44
|
-
fi
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
TRIGGERED=false
|
|
48
|
-
|
|
49
|
-
# Mode 1: SQL file written
|
|
50
|
-
if [ -n "$FILE_PATH" ] && [[ "$FILE_PATH" == *.sql ]]; then
|
|
51
|
-
TRIGGERED=true
|
|
52
|
-
check_sql_file "$FILE_PATH"
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
# Mode 2: supabase db push — only scan new/modified migrations (not historical)
|
|
56
|
-
if [ -n "$COMMAND" ] && echo "$COMMAND" | grep -qE 'supabase\s+db\s+push'; then
|
|
57
|
-
TRIGGERED=true
|
|
58
|
-
# Scan only uncommitted or recently modified migration files
|
|
59
|
-
MODIFIED_MIGRATIONS=$(git diff --name-only HEAD -- supabase/migrations/*.sql 2>/dev/null; git diff --cached --name-only -- supabase/migrations/*.sql 2>/dev/null; git ls-files --others -- supabase/migrations/*.sql 2>/dev/null)
|
|
60
|
-
if [ -n "$MODIFIED_MIGRATIONS" ]; then
|
|
61
|
-
while IFS= read -r sql_file; do
|
|
62
|
-
[ -f "$sql_file" ] && check_sql_file "$sql_file"
|
|
63
|
-
done < <(echo "$MODIFIED_MIGRATIONS" | sort -u)
|
|
64
|
-
fi
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# Block on destructive ops, warn on missing RLS
|
|
68
|
-
if $TRIGGERED && [ "$DESTRUCTIVE" -gt 0 ]; then
|
|
69
|
-
printf '{"continue":false,"stopReason":"◆ MIGRATION: %d destructive operation(s) blocked","systemMessage":"◆ MIGRATION BLOCKED: %d destructive operation(s) found. Tell Claude to review the SQL and confirm these operations are intentional."}' "$DESTRUCTIVE" "$DESTRUCTIVE"
|
|
70
|
-
exit 2
|
|
71
|
-
elif $TRIGGERED && [ "$WARNINGS_COUNT" -gt 0 ]; then
|
|
72
|
-
printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: %d warning(s) — tell Claude to review missing RLS policies."}' "$WARNINGS_COUNT"
|
|
73
|
-
elif $TRIGGERED; then
|
|
74
|
-
printf '{"continue":true,"systemMessage":"◆ MIGRATION CHECK: clean"}'
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
exit 0
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Notification hook — passes notification message to TTS
|
|
3
|
-
# Reads message from stdin JSON (Claude Code hook protocol)
|
|
4
|
-
|
|
5
|
-
TEXT=""
|
|
6
|
-
if [ ! -t 0 ]; then
|
|
7
|
-
INPUT=$(cat)
|
|
8
|
-
TEXT=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.message||'')}catch(e){}" 2>/dev/null)
|
|
9
|
-
fi
|
|
10
|
-
|
|
11
|
-
if [ -n "$TEXT" ]; then
|
|
12
|
-
~/.claude/scripts/speak.sh "$TEXT" &
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
printf '{"continue":true}'
|
|
16
|
-
exit 0
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Pre-commit validation — secrets, debug statements, TypeScript, lint
|
|
3
|
-
source "$(dirname "$0")/qualia-colors.sh"
|
|
4
|
-
|
|
5
|
-
if ! command -v node &>/dev/null; then
|
|
6
|
-
[ ! -t 0 ] && cat > /dev/null
|
|
7
|
-
printf '{"continue":false,"stopReason":"PRE-COMMIT: node is not installed — cannot verify safety. Install node to proceed."}'
|
|
8
|
-
exit 2
|
|
9
|
-
fi
|
|
10
|
-
|
|
11
|
-
if [ ! -t 0 ]; then
|
|
12
|
-
INPUT=$(cat)
|
|
13
|
-
COMMAND=$(echo "$INPUT" | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(d.tool_input?.command||d.tool_input||'')}catch(e){}" 2>/dev/null)
|
|
14
|
-
else
|
|
15
|
-
COMMAND="${1:-}"
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
case "$COMMAND" in
|
|
19
|
-
git\ commit*) ;;
|
|
20
|
-
*) exit 0 ;;
|
|
21
|
-
esac
|
|
22
|
-
|
|
23
|
-
git rev-parse --is-inside-work-tree &>/dev/null || exit 0
|
|
24
|
-
|
|
25
|
-
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
|
|
26
|
-
[ -z "$STAGED_FILES" ] && exit 0
|
|
27
|
-
|
|
28
|
-
q_header "PRE-COMMIT"
|
|
29
|
-
BLOCKED=false
|
|
30
|
-
FAIL_DETAILS=""
|
|
31
|
-
|
|
32
|
-
# Check for secrets
|
|
33
|
-
SECRETS_PATTERN="(api[_-]?key|apikey|secret[_-]?key|password|passwd|pwd|token|auth[_-]?token|access[_-]?token|private[_-]?key)[\s]*[=:][\"'\s]*[A-Za-z0-9+/=_-]{20,}"
|
|
34
|
-
for file in $STAGED_FILES; do
|
|
35
|
-
if [ -f "$file" ] && grep -iE "$SECRETS_PATTERN" "$file" > /dev/null 2>&1; then
|
|
36
|
-
q_fail "Secret in ${file}"
|
|
37
|
-
FAIL_DETAILS="${FAIL_DETAILS}A password or API key was found in ${file} — tell Claude: 'remove the secret and use an environment variable instead.' "
|
|
38
|
-
BLOCKED=true
|
|
39
|
-
fi
|
|
40
|
-
done
|
|
41
|
-
|
|
42
|
-
# Check for .env files
|
|
43
|
-
ENV_FILES=$(echo "$STAGED_FILES" | grep -E '\.env($|\.)' | grep -v '.example' | grep -v '.sample' || true)
|
|
44
|
-
if [ -n "$ENV_FILES" ]; then
|
|
45
|
-
q_fail ".env file staged: ${ENV_FILES}"
|
|
46
|
-
FAIL_DETAILS="${FAIL_DETAILS}.env file contains secrets and shouldn't be committed — tell Claude: 'unstage the .env file.' "
|
|
47
|
-
BLOCKED=true
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
# Debug statements in JS/TS (block in production code, allow in tests/stories)
|
|
51
|
-
JS_PROD_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|jsx|ts|tsx)$' | grep -vE '\.test\.|\.spec\.|__tests__/|\.stories\.' || true)
|
|
52
|
-
if [ -n "$JS_PROD_FILES" ]; then
|
|
53
|
-
for file in $JS_PROD_FILES; do
|
|
54
|
-
if [ -f "$file" ] && grep -E "console\.(log|debug|info)|debugger" "$file" > /dev/null 2>&1; then
|
|
55
|
-
q_fail "Debug statement in ${file}"
|
|
56
|
-
FAIL_DETAILS="${FAIL_DETAILS}Debug statement in ${file} — tell Claude: 'remove console.log/debugger from production code.' "
|
|
57
|
-
BLOCKED=true
|
|
58
|
-
fi
|
|
59
|
-
done
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
# TypeScript check (skip if tsc passed in last 5 minutes — pre-deploy-gate also runs tsc)
|
|
63
|
-
TSC_STAMP="/tmp/.tsc-pass-$(echo "$PWD" | md5sum | cut -c1-8)"
|
|
64
|
-
if [ -f "tsconfig.json" ]; then
|
|
65
|
-
if [ -f "$TSC_STAMP" ]; then
|
|
66
|
-
AGE=$(( $(date +%s) - $(stat -c %Y "$TSC_STAMP" 2>/dev/null || echo 0) ))
|
|
67
|
-
if [ "$AGE" -lt 300 ]; then
|
|
68
|
-
q_pass "TypeScript (cached)"
|
|
69
|
-
else
|
|
70
|
-
rm -f "$TSC_STAMP"
|
|
71
|
-
fi
|
|
72
|
-
fi
|
|
73
|
-
# Run tsc only if no valid cache
|
|
74
|
-
if [ ! -f "$TSC_STAMP" ]; then
|
|
75
|
-
if command -v npx &> /dev/null; then
|
|
76
|
-
if npx tsc --noEmit 2>/dev/null; then
|
|
77
|
-
q_pass "TypeScript"
|
|
78
|
-
touch "$TSC_STAMP"
|
|
79
|
-
else
|
|
80
|
-
q_fail "TypeScript errors"
|
|
81
|
-
FAIL_DETAILS="${FAIL_DETAILS}Code errors found — tell Claude: 'fix the TypeScript errors and try committing again.' "
|
|
82
|
-
BLOCKED=true
|
|
83
|
-
fi
|
|
84
|
-
fi
|
|
85
|
-
fi
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
if $BLOCKED; then
|
|
89
|
-
cat <<EOJSON
|
|
90
|
-
{
|
|
91
|
-
"continue": false,
|
|
92
|
-
"stopReason": "◆ Pre-commit: blocked",
|
|
93
|
-
"systemMessage": "◆ PRE-COMMIT BLOCKED: ${FAIL_DETAILS}Tell Claude to fix these issues and try committing again."
|
|
94
|
-
}
|
|
95
|
-
EOJSON
|
|
96
|
-
exit 2
|
|
97
|
-
fi
|
|
98
|
-
|
|
99
|
-
printf '{"continue":true,"systemMessage":"◆ PRE-COMMIT: all checks passed"}'
|
|
100
|
-
exit 0
|