qualia-framework 3.2.0 → 3.3.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 +3 -4
- package/README.md +59 -23
- package/agents/plan-checker.md +158 -0
- package/agents/planner.md +52 -0
- package/agents/research-synthesizer.md +86 -0
- package/agents/researcher.md +119 -0
- package/agents/roadmapper.md +157 -0
- package/agents/verifier.md +180 -32
- package/bin/cli.js +403 -9
- package/bin/install.js +219 -70
- package/bin/qualia-ui.js +11 -11
- package/bin/state.js +200 -6
- package/bin/statusline.js +4 -4
- package/docs/erp-contract.md +161 -0
- package/hooks/branch-guard.js +23 -2
- package/hooks/migration-guard.js +23 -0
- package/hooks/pre-compact.js +20 -0
- package/hooks/pre-deploy-gate.js +39 -0
- package/hooks/pre-push.js +20 -0
- package/hooks/session-start.js +16 -43
- package/package.json +6 -4
- package/references/questioning.md +123 -0
- package/rules/infrastructure.md +87 -0
- package/skills/qualia/SKILL.md +1 -0
- package/skills/qualia-build/SKILL.md +18 -0
- package/skills/qualia-design/SKILL.md +14 -8
- package/skills/qualia-discuss/SKILL.md +115 -0
- package/skills/qualia-help/SKILL.md +60 -0
- package/skills/qualia-learn/SKILL.md +27 -4
- package/skills/qualia-map/SKILL.md +145 -0
- package/skills/qualia-milestone/SKILL.md +148 -0
- package/skills/qualia-new/SKILL.md +374 -229
- package/skills/qualia-plan/SKILL.md +135 -30
- package/skills/qualia-polish/SKILL.md +167 -117
- package/skills/qualia-report/SKILL.md +17 -8
- package/skills/qualia-research/SKILL.md +124 -0
- package/skills/qualia-review/SKILL.md +126 -41
- package/skills/qualia-test/SKILL.md +134 -0
- package/skills/qualia-verify/SKILL.md +1 -1
- package/templates/DESIGN.md +440 -102
- package/templates/help.html +476 -0
- package/templates/phase-context.md +48 -0
- package/templates/plan.md +14 -0
- package/templates/projects/ai-agent.md +55 -0
- package/templates/projects/mobile-app.md +56 -0
- package/templates/projects/voice-agent.md +55 -0
- package/templates/projects/website.md +58 -0
- package/templates/requirements.md +69 -0
- package/templates/research-project/ARCHITECTURE.md +70 -0
- package/templates/research-project/FEATURES.md +60 -0
- package/templates/research-project/PITFALLS.md +73 -0
- package/templates/research-project/STACK.md +51 -0
- package/templates/research-project/SUMMARY.md +86 -0
- package/templates/roadmap.md +71 -0
- package/tests/bin.test.sh +20 -6
- package/tests/hooks.test.sh +76 -7
- package/tests/runner.js +1915 -0
- package/tests/state.test.sh +189 -11
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qualia-research
|
|
3
|
+
description: "Deep-research a niche domain or library BEFORE planning a specific phase. Spawns the researcher agent with Context7/WebFetch access. Writes to .planning/phase-{N}-research.md."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /qualia-research — Per-Phase Deep Research
|
|
7
|
+
|
|
8
|
+
Runs targeted research on a domain, library, or integration that a specific phase depends on. Distinct from `/qualia-new` research (which covers 4 dimensions project-wide) — this one is narrow and phase-scoped.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- A phase touches a library you've never used
|
|
13
|
+
- A phase integrates with a niche API (FHIR, legal forms, payment gateways)
|
|
14
|
+
- SUMMARY.md marked this phase as a "Research flag"
|
|
15
|
+
- You're about to plan and realize you don't know the current best practice
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
`/qualia-research {N}` — research the current phase or phase N
|
|
20
|
+
|
|
21
|
+
## Process
|
|
22
|
+
|
|
23
|
+
### 1. Determine Phase
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node ~/.claude/bin/state.js check 2>/dev/null
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use phase N from args, or current phase from STATE.md.
|
|
30
|
+
|
|
31
|
+
### 2. Load Context
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cat .planning/PROJECT.md 2>/dev/null
|
|
35
|
+
cat .planning/ROADMAP.md 2>/dev/null
|
|
36
|
+
cat .planning/phase-{N}-context.md 2>/dev/null # if /qualia-discuss was run first
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Identify what this phase needs to know.
|
|
40
|
+
|
|
41
|
+
### 3. Ask the User What to Research
|
|
42
|
+
|
|
43
|
+
Inline free text:
|
|
44
|
+
|
|
45
|
+
**"I'm about to research Phase {N}: {phase name}. What specifically do you want me to dig into? Library, domain, integration, pattern?"**
|
|
46
|
+
|
|
47
|
+
Wait for their answer. Their answer defines the research question.
|
|
48
|
+
|
|
49
|
+
### 4. Spawn the Researcher
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Agent(prompt="
|
|
53
|
+
Read your role: @~/.claude/agents/qualia-researcher.md
|
|
54
|
+
|
|
55
|
+
<dimension>phase-specific</dimension>
|
|
56
|
+
|
|
57
|
+
<question>
|
|
58
|
+
{user's research question}
|
|
59
|
+
</question>
|
|
60
|
+
|
|
61
|
+
<phase_context>
|
|
62
|
+
Phase: {N}
|
|
63
|
+
Goal: {phase goal from ROADMAP.md}
|
|
64
|
+
Requirements: {REQ-IDs covered by this phase}
|
|
65
|
+
</phase_context>
|
|
66
|
+
|
|
67
|
+
<project_context>
|
|
68
|
+
{PROJECT.md summary}
|
|
69
|
+
</project_context>
|
|
70
|
+
|
|
71
|
+
<output_path>
|
|
72
|
+
.planning/phase-{N}-research.md
|
|
73
|
+
</output_path>
|
|
74
|
+
|
|
75
|
+
Research using Context7 first, then WebFetch, then WebSearch. Be specific and concrete.
|
|
76
|
+
Include: recommendation, rationale, version numbers (if applicable), code examples,
|
|
77
|
+
alternatives considered, what to avoid, sources.
|
|
78
|
+
", subagent_type="qualia-researcher", description="Phase {N} research")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 5. Review Output
|
|
82
|
+
|
|
83
|
+
Read `.planning/phase-{N}-research.md`. Present the key findings:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
node ~/.claude/bin/qualia-ui.js divider
|
|
87
|
+
node ~/.claude/bin/qualia-ui.js ok "Research complete"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Show:
|
|
91
|
+
- Recommendation
|
|
92
|
+
- Confidence
|
|
93
|
+
- Top 3 key findings
|
|
94
|
+
- Sources used
|
|
95
|
+
|
|
96
|
+
### 6. User Confirms or Asks More
|
|
97
|
+
|
|
98
|
+
- header: "Enough?"
|
|
99
|
+
- question: "Is this enough research, or should I dig deeper?"
|
|
100
|
+
- options:
|
|
101
|
+
- "Enough" — Move to planning
|
|
102
|
+
- "Dig deeper" — I have more questions
|
|
103
|
+
|
|
104
|
+
If "Dig deeper" — ask what they want, re-spawn the researcher with additional questions.
|
|
105
|
+
|
|
106
|
+
### 7. Commit
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git add .planning/phase-{N}-research.md
|
|
110
|
+
git commit -m "docs(phase-{N}): research findings"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 8. Route
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
node ~/.claude/bin/qualia-ui.js end "PHASE {N} RESEARCH DONE" "/qualia-plan {N}"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Rules
|
|
120
|
+
|
|
121
|
+
1. **One research session per run.** Don't try to research phases 1 through 5 in one call.
|
|
122
|
+
2. **Must produce a file.** The research is worthless if it only lives in conversation context.
|
|
123
|
+
3. **Honor locked decisions from phase-{N}-context.md.** Don't research alternatives to something already locked.
|
|
124
|
+
4. **Context7 first.** Always try Context7 MCP before WebFetch — it's fastest and most current for known libraries.
|
|
@@ -1,76 +1,161 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qualia-review
|
|
3
|
-
description: "Production audit
|
|
3
|
+
description: "Production audit with scored diagnostics. Runs real commands, scores findings by severity. Trigger on 'review', 'audit', 'code review', 'security check', 'production check'."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /qualia-review — Production Audit
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Runs real diagnostic commands and scores every finding. Not a checklist — an executable audit.
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
12
|
-
- `/qualia-review` —
|
|
13
|
-
- `/qualia-review --web` —
|
|
14
|
-
- `/qualia-review --ai` — AI/voice agent
|
|
12
|
+
- `/qualia-review` — Full audit (security + quality + performance)
|
|
13
|
+
- `/qualia-review --web` — Adds web-specific checks (headers, CORS, vitals)
|
|
14
|
+
- `/qualia-review --ai` — Adds AI/voice agent checks (prompt safety, latency)
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Process
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
node ~/.claude/bin/qualia-ui.js banner review
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
### 0. Load Context
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
5. **Test Coverage** — Gaps, edge cases, test quality
|
|
24
|
+
```bash
|
|
25
|
+
cat ~/.claude/knowledge/common-fixes.md 2>/dev/null
|
|
26
|
+
cat ~/.claude/knowledge/learned-patterns.md 2>/dev/null
|
|
27
|
+
```
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
Detect project shape:
|
|
30
|
+
```bash
|
|
31
|
+
ls package.json next.config.* tsconfig.json supabase/ app/ src/ 2>/dev/null
|
|
32
|
+
```
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
### 1. Security Scan
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
Run every command. Record each finding with severity.
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
```bash
|
|
39
|
+
# CRITICAL: service_role in client code
|
|
40
|
+
grep -rn "service_role" --include="*.ts" --include="*.tsx" --include="*.js" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | grep -v "\.server\.\|[\\/]server[\\/]\|[\\/]app[\\/]api[\\/]\|route\.\|middleware\."
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
# CRITICAL: hardcoded secrets
|
|
43
|
+
grep -rn "sk_live\|sk_test\|SUPABASE_SERVICE_ROLE\|eyJhbGciOi" --include="*.ts" --include="*.tsx" --include="*.js" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | grep -v "\.env"
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
# CRITICAL: dangerous patterns
|
|
46
|
+
grep -rn "dangerouslySetInnerHTML\|eval(" --include="*.ts" --include="*.tsx" --include="*.js" app/ components/ src/ 2>/dev/null | grep -v node_modules
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
# CRITICAL: .env files tracked in git
|
|
49
|
+
git ls-files | grep -i "\.env" | grep -v "\.example\|\.template\|\.sample"
|
|
43
50
|
|
|
44
|
-
|
|
51
|
+
# HIGH: API routes without auth
|
|
52
|
+
for f in $(find app/api -name "route.ts" -o -name "route.js" 2>/dev/null); do
|
|
53
|
+
grep -qL "getUser\|getSession\|auth()\|createClient" "$f" && echo "UNPROTECTED: $f"
|
|
54
|
+
done
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
# HIGH: API routes without input validation
|
|
57
|
+
for f in $(find app/api -name "route.ts" -o -name "route.js" 2>/dev/null); do
|
|
58
|
+
grep -L "z\.\|zod\|Zod\|parse\|safeParse" "$f" 2>/dev/null
|
|
59
|
+
done
|
|
47
60
|
|
|
48
|
-
|
|
61
|
+
# HIGH: client-side database mutations
|
|
62
|
+
grep -rn "\.insert\|\.update\|\.delete\|\.upsert" --include="*.tsx" --include="*.jsx" app/ components/ 2>/dev/null | grep -v "use server" | grep -v "\.server\."
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
# MEDIUM: npm vulnerabilities
|
|
65
|
+
npm audit --json 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync(0,'utf8'));const v=d.metadata?.vulnerabilities||{};console.log('critical:',v.critical||0,'high:',v.high||0,'moderate:',v.moderate||0)}catch{console.log('audit unavailable')}"
|
|
66
|
+
```
|
|
51
67
|
|
|
52
|
-
|
|
68
|
+
### 2. Code Quality Scan
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
```bash
|
|
71
|
+
# TypeScript errors (HIGH if >0)
|
|
72
|
+
npx tsc --noEmit 2>&1 | grep -c "error TS"
|
|
55
73
|
|
|
56
|
-
|
|
74
|
+
# 'any' type usage (MEDIUM — count)
|
|
75
|
+
grep -rn ": any\| as any" --include="*.ts" --include="*.tsx" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | wc -l
|
|
57
76
|
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
- **Where** — `file:line`
|
|
61
|
-
- **Fix** — concrete suggestion
|
|
62
|
-
- **Severity** — CRITICAL / HIGH / MEDIUM / LOW
|
|
77
|
+
# Empty catch blocks (HIGH)
|
|
78
|
+
grep -rn "catch\s*{}\|catch\s*(.*)\s*{\s*}" --include="*.ts" --include="*.tsx" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | head -10
|
|
63
79
|
|
|
64
|
-
|
|
80
|
+
# TODO/FIXME left in code (LOW — count)
|
|
81
|
+
grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.ts" --include="*.tsx" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | wc -l
|
|
65
82
|
|
|
83
|
+
# console.log in production code (LOW — count)
|
|
84
|
+
grep -rn "console\.log" --include="*.ts" --include="*.tsx" app/ components/ src/ 2>/dev/null | grep -v node_modules | wc -l
|
|
66
85
|
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
|
|
87
|
+
### 3. Performance Scan
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Build output — route sizes and first load JS
|
|
91
|
+
npx next build 2>&1 | grep -E "Route|First Load|shared by all|○|●|ƒ|λ" | tail -25
|
|
92
|
+
|
|
93
|
+
# Heavy files (>300 lines often means split needed)
|
|
94
|
+
find app/ components/ src/ -name "*.tsx" -o -name "*.ts" 2>/dev/null | xargs wc -l 2>/dev/null | sort -rn | head -10
|
|
95
|
+
|
|
96
|
+
# Missing next/image (MEDIUM)
|
|
97
|
+
grep -rn "<img " --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | grep -v "next/image" | wc -l
|
|
98
|
+
|
|
99
|
+
# Client component ratio
|
|
100
|
+
echo "use client: $(grep -rl "'use client'" --include="*.tsx" app/ components/ src/ 2>/dev/null | wc -l)"
|
|
101
|
+
echo "total tsx: $(find app/ components/ src/ -name '*.tsx' 2>/dev/null | wc -l)"
|
|
102
|
+
|
|
103
|
+
# Sequential data fetching (HIGH)
|
|
104
|
+
grep -rn "const.*=.*await" --include="*.tsx" --include="*.ts" app/ src/ 2>/dev/null | grep -v "Promise.all\|Promise.allSettled" | head -10
|
|
76
105
|
```
|
|
106
|
+
|
|
107
|
+
### 4. Score and Report
|
|
108
|
+
|
|
109
|
+
Write to `.planning/REVIEW.md`:
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
# Production Review — {YYYY-MM-DD}
|
|
113
|
+
|
|
114
|
+
## Summary
|
|
115
|
+
| Category | Critical | High | Medium | Low | Score |
|
|
116
|
+
|----------|----------|------|--------|-----|-------|
|
|
117
|
+
| Security | {n} | {n} | {n} | {n} | {1-5} |
|
|
118
|
+
| Quality | {n} | {n} | {n} | {n} | {1-5} |
|
|
119
|
+
| Perf | {n} | {n} | {n} | {n} | {1-5} |
|
|
120
|
+
| **Total** | {n} | {n} | {n} | {n} | **{avg}/5** |
|
|
121
|
+
|
|
122
|
+
## Findings
|
|
123
|
+
|
|
124
|
+
### CRITICAL
|
|
125
|
+
- **{title}** — `{file}:{line}` — {what's wrong} — Fix: {how}
|
|
126
|
+
|
|
127
|
+
### HIGH
|
|
128
|
+
- ...
|
|
129
|
+
|
|
130
|
+
### MEDIUM
|
|
131
|
+
- ...
|
|
132
|
+
|
|
133
|
+
### LOW
|
|
134
|
+
- ...
|
|
135
|
+
|
|
136
|
+
## Verdict
|
|
137
|
+
{PASS: no critical/high | FAIL: N blockers — fix before /qualia-ship}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Scoring:**
|
|
141
|
+
- 5 = zero high/critical, fewer than 3 medium
|
|
142
|
+
- 4 = zero critical, 1 high or fewer than 5 medium
|
|
143
|
+
- 3 = zero critical, 2-3 high
|
|
144
|
+
- 2 = 1 critical or 4+ high
|
|
145
|
+
- 1 = multiple critical
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
node ~/.claude/bin/qualia-ui.js divider
|
|
149
|
+
node ~/.claude/bin/qualia-ui.js info "Security: {score}/5 ({n} findings)"
|
|
150
|
+
node ~/.claude/bin/qualia-ui.js info "Quality: {score}/5 ({n} findings)"
|
|
151
|
+
node ~/.claude/bin/qualia-ui.js info "Perf: {score}/5 ({n} findings)"
|
|
152
|
+
node ~/.claude/bin/qualia-ui.js end "REVIEW: {PASS|FAIL}" "{next command}"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Rules
|
|
156
|
+
|
|
157
|
+
1. **Run every command.** Don't skip scans because "the code looks clean."
|
|
158
|
+
2. **Every finding gets a severity.** No prose — CRITICAL/HIGH/MEDIUM/LOW.
|
|
159
|
+
3. **Every finding gets a fix suggestion.** Not just "this is bad" — say what to do.
|
|
160
|
+
4. **Review detects. It does NOT fix.** This is an audit, not a refactor. Tell the user what to fix.
|
|
161
|
+
5. **CRITICAL or HIGH = deploy blocker.** `/qualia-ship` checks for these.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qualia-test
|
|
3
|
+
description: "Generate or run tests for client projects. Trigger on 'write tests', 'add tests', 'test this', 'run tests', 'test coverage', 'need tests for'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /qualia-test — Test Generator
|
|
7
|
+
|
|
8
|
+
Generate tests for client project code. Detect framework, classify targets, write tests, run them.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
- `/qualia-test` — Generate tests for recently changed files
|
|
13
|
+
- `/qualia-test {file}` — Generate tests for a specific file
|
|
14
|
+
- `/qualia-test --run` — Run existing tests and report
|
|
15
|
+
- `/qualia-test --coverage` — Run with coverage report
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
node ~/.claude/bin/qualia-ui.js banner test
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 1. Detect Test Framework
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node -e "
|
|
27
|
+
const p=JSON.parse(require('fs').readFileSync('package.json','utf8'));
|
|
28
|
+
const d={...p.dependencies,...p.devDependencies};
|
|
29
|
+
console.log(JSON.stringify({
|
|
30
|
+
vitest: !!d.vitest,
|
|
31
|
+
jest: !!d.jest,
|
|
32
|
+
playwright: !!d['@playwright/test'],
|
|
33
|
+
testing_library: !!d['@testing-library/react']
|
|
34
|
+
}))
|
|
35
|
+
"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If no test framework found, install vitest (lighter than jest for Next.js/Vite):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Add to `vitest.config.ts` if it doesn't exist:
|
|
45
|
+
```typescript
|
|
46
|
+
import { defineConfig } from 'vitest/config'
|
|
47
|
+
import react from '@vitejs/plugin-react'
|
|
48
|
+
|
|
49
|
+
export default defineConfig({
|
|
50
|
+
plugins: [react()],
|
|
51
|
+
test: {
|
|
52
|
+
environment: 'jsdom',
|
|
53
|
+
setupFiles: ['./vitest.setup.ts'],
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Find Targets
|
|
59
|
+
|
|
60
|
+
If specific file given → use that.
|
|
61
|
+
If `--run` → skip to step 4.
|
|
62
|
+
Otherwise find recently changed untested files:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Files changed in last 5 commits that don't have tests
|
|
66
|
+
git diff --name-only HEAD~5 --diff-filter=AM -- '*.ts' '*.tsx' 2>/dev/null | grep -v "test\|spec\|__test__\|\.d\.ts" | head -10
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3. Generate Tests
|
|
70
|
+
|
|
71
|
+
For each target file, classify it and generate the appropriate test:
|
|
72
|
+
|
|
73
|
+
**API route** (`app/api/**/route.ts`):
|
|
74
|
+
- Test each exported handler (GET, POST, PUT, DELETE)
|
|
75
|
+
- Test with valid input → expected response
|
|
76
|
+
- Test with invalid input → 400 error
|
|
77
|
+
- Test without auth → 401 (if auth is required)
|
|
78
|
+
|
|
79
|
+
**Server action** (has `"use server"`):
|
|
80
|
+
- Test each exported function
|
|
81
|
+
- Test with valid args → expected result
|
|
82
|
+
- Test with invalid args → error handling
|
|
83
|
+
|
|
84
|
+
**React component** (`*.tsx` with JSX):
|
|
85
|
+
- Test rendering without crashing
|
|
86
|
+
- Test interactive elements (clicks, form submissions)
|
|
87
|
+
- Test loading, error, and empty states if they exist
|
|
88
|
+
- Test accessibility (role, aria-label presence)
|
|
89
|
+
|
|
90
|
+
**Utility function** (`lib/*.ts`, `utils/*.ts`):
|
|
91
|
+
- Test each exported function with normal input
|
|
92
|
+
- Test edge cases: empty, null, undefined, boundary values
|
|
93
|
+
- Test error cases: invalid input, missing data
|
|
94
|
+
|
|
95
|
+
Write test file next to the source: `{file}.test.ts` or `{file}.test.tsx`.
|
|
96
|
+
|
|
97
|
+
### 4. Run Tests
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Vitest
|
|
101
|
+
npx vitest run --reporter=verbose 2>&1 | tail -30
|
|
102
|
+
|
|
103
|
+
# Or Jest
|
|
104
|
+
npx jest --verbose 2>&1 | tail -30
|
|
105
|
+
|
|
106
|
+
# Coverage (if --coverage flag)
|
|
107
|
+
npx vitest run --coverage 2>&1 | tail -30
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 5. Report
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
node ~/.claude/bin/qualia-ui.js divider
|
|
114
|
+
node ~/.claude/bin/qualia-ui.js info "Files tested: {N}"
|
|
115
|
+
node ~/.claude/bin/qualia-ui.js ok "Passing: {pass}/{total}"
|
|
116
|
+
node ~/.claude/bin/qualia-ui.js end "TESTS DONE"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If any tests fail, show the failures and offer to fix them.
|
|
120
|
+
|
|
121
|
+
### 6. Commit
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git add {test files}
|
|
125
|
+
git commit -m "test: add tests for {files}"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Rules
|
|
129
|
+
|
|
130
|
+
1. **Test behavior, not implementation.** Don't test internal state — test what the user/caller sees.
|
|
131
|
+
2. **No snapshot tests.** They're brittle and meaningless.
|
|
132
|
+
3. **No mocking unless necessary.** Test real behavior. Mock only external services (APIs, databases).
|
|
133
|
+
4. **Each test file is self-contained.** No shared mutable state between tests.
|
|
134
|
+
5. **Name tests as sentences.** `it("returns 401 when user is not authenticated")` not `it("test auth")`.
|
|
@@ -33,7 +33,7 @@ node ~/.claude/bin/qualia-ui.js spawn verifier "Goal-backward check..."
|
|
|
33
33
|
Agent(prompt="
|
|
34
34
|
Read your role: @agents/verifier.md
|
|
35
35
|
|
|
36
|
-
Phase plan with success criteria:
|
|
36
|
+
Phase plan with success criteria AND verification contracts:
|
|
37
37
|
@.planning/phase-{N}-plan.md
|
|
38
38
|
|
|
39
39
|
{If re-verification: Previous verification with gaps:}
|