qualia-framework-v2 2.9.0 → 3.0.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.
@@ -1,11 +1,24 @@
1
1
  ---
2
2
  name: qualia-polish
3
- description: "Design and UX pass — critique, polish, harden. Run after all phases are verified."
3
+ description: "Design and UX pass — anti-AI-slop, genuine craft, responsive, accessible. Run after all phases are verified."
4
4
  ---
5
5
 
6
6
  # /qualia-polish — Design Pass
7
7
 
8
- Run after all feature phases are verified. Makes it look production-ready.
8
+ Makes it look like a human designer built it. Kills AI slop. Run after all feature phases are verified.
9
+
10
+ ## The Standard
11
+
12
+ Every site Qualia ships must feel **designed, not generated.** AI-generated sites have tells:
13
+ - Identical card grids with rounded corners and soft shadows
14
+ - Blue-purple gradients on everything
15
+ - Inter/system-ui font with no hierarchy
16
+ - Generic hero with centered text and a stock gradient background
17
+ - Fixed-width containers leaving dead space on wide screens
18
+ - No motion, no personality, no opinion
19
+ - Perfect symmetry everywhere (real design has tension)
20
+
21
+ **Kill all of these.** A Qualia site should make someone ask "who designed this?" — not "which template is this?"
9
22
 
10
23
  ## Process
11
24
 
@@ -19,139 +32,163 @@ node ~/.claude/bin/qualia-ui.js banner polish
19
32
  cat .planning/DESIGN.md 2>/dev/null || echo "NO_DESIGN"
20
33
  ```
21
34
 
22
- If DESIGN.md exists → use it as the standard. If not → use Qualia defaults from `rules/frontend.md`.
35
+ If DESIGN.md exists → it's the standard. If not → use `rules/frontend.md` defaults.
23
36
 
24
37
  Read EVERY frontend file before modifying. No blind edits.
25
38
 
26
- ### 1. Critique (Structured Audit)
27
-
28
- Review the entire UI against this checklist. Check each item, note violations with file:line.
29
-
30
- **Typography:**
31
- - [ ] No generic fonts (Inter, Roboto, Arial, system-ui, Space Grotesk)
32
- - [ ] Proper type scale with clear hierarchy (display → heading → body → caption)
33
- - [ ] Body text: 16px+, line-height 1.5–1.7
34
- - [ ] Headings: tighter line-height (1.1–1.3), negative letter-spacing for large sizes
35
- - [ ] Prose max-width: 65ch
36
- - [ ] Font weights used for hierarchy (Regular, Medium, Semibold, Bold)
37
-
38
- **Color & Contrast:**
39
- - [ ] Cohesive palette via CSS variables (not scattered hex values)
40
- - [ ] All text passes WCAG AA contrast (4.5:1 normal, 3:1 large)
41
- - [ ] CTA buttons use accent color — stand out from the page
42
- - [ ] No blue-purple gradients, no rainbow palettes
43
- - [ ] Dark mode: rethought surfaces (not just inverted)
44
- - [ ] Semantic colors used consistently (success=green, error=red, warning=amber)
45
-
46
- **Layout & Spacing:**
47
- - [ ] Full-width fluid layouts — no hardcoded max-width caps
48
- - [ ] 8px spacing grid followed consistently
49
- - [ ] Tight spacing within groups, generous between sections
50
- - [ ] Fluid padding: `clamp(1rem, 5vw, 4rem)` horizontal
51
- - [ ] No identical card grids — varied visual hierarchy
52
- - [ ] No generic heroes — purposeful, distinctive
53
-
54
- **Interactive States:**
55
- - [ ] Every button/link: hover (color shift, 150ms), focus (visible ring), active (press feedback), disabled
56
- - [ ] Loading: skeleton or spinner on all async operations
57
- - [ ] Empty: helpful message + action on empty lists/data
58
- - [ ] Error: user-friendly message + recovery action on failed fetches
59
- - [ ] Form validation: inline errors with `aria-describedby`
60
-
61
- **Motion:**
62
- - [ ] Hover/focus: 150–200ms transitions
63
- - [ ] Page load: staggered entrance animations (50–80ms delay)
64
- - [ ] Expand/collapse: 250ms ease-in-out
65
- - [ ] `prefers-reduced-motion` respected (no animation for users who opt out)
66
- - [ ] No jank: transforms and opacity only for animated properties
67
-
68
- **Accessibility:**
69
- - [ ] Semantic HTML: `nav`, `main`, `section`, `article`, `header`, `footer`
70
- - [ ] One `h1` per page, sequential heading hierarchy
71
- - [ ] All images: descriptive `alt` (or `alt=""` + `aria-hidden` if decorative)
72
- - [ ] All form inputs: visible `<label>` with `htmlFor` — not placeholder-only
73
- - [ ] All interactive elements: keyboard accessible (Tab/Enter/Escape)
74
- - [ ] Touch targets: 44px minimum
75
- - [ ] Skip link: `<a href="#main">` as first focusable element
76
- - [ ] No `outline: none` without focus replacement
77
- - [ ] `<html lang="en">` set
78
- - [ ] Color not sole information carrier — icons/text as supplements
79
-
80
- **Responsive:**
81
- - [ ] Mobile-first approach (base styles for mobile, min-width breakpoints for larger)
82
- - [ ] No horizontal scroll at 320px
83
- - [ ] Navigation: hamburger on mobile, expanded on desktop
84
- - [ ] Touch targets adequate on mobile (44px min)
85
- - [ ] Fluid typography with `clamp()`
86
- - [ ] Images: `max-width: 100%`, responsive srcset where needed
87
- - [ ] Tables: card view or horizontal scroll on mobile
88
-
89
- **Performance:**
90
- - [ ] Server Components by default — `'use client'` only when needed
91
- - [ ] Images via `next/image` with width/height
92
- - [ ] No barrel file imports — direct imports from source
93
- - [ ] Heavy components lazy-loaded with `next/dynamic`
94
- - [ ] Data fetched in parallel, not sequentially
95
-
96
- ### 2. Fix Everything
97
-
98
- Work through violations from the critique. Fix each category:
99
-
100
- 1. Typography first (sets the visual foundation)
101
- 2. Color & contrast (palette coherence)
102
- 3. Layout & spacing (structural fixes)
103
- 4. Interactive states (loading, empty, error, hover, focus)
104
- 5. Motion (transitions, entrance animations, reduced-motion)
105
- 6. Accessibility (semantic HTML, ARIA, keyboard, labels)
106
- 7. Responsive (mobile breakpoints, fluid sizing)
107
- 8. Performance (quick wins — image optimization, dynamic imports)
108
-
109
- ### 3. Harden
110
-
111
- After polish, stress-test edge cases:
112
- - Long text content (overflow, truncation, word-break)
113
- - Extremely long usernames or email addresses
114
- - Empty data everywhere simultaneously
115
- - Error state on every fetch simultaneously
116
- - 320px viewport width
117
- - Keyboard-only navigation through entire flow
118
- - Screen reader landmarks check (semantic HTML)
119
- - Right-to-left text (if i18n is planned)
120
- - Slow network (loading states visible, no flash of empty content)
121
-
122
- ### 4. Verify
39
+ ### 1. AI Slop Detector
40
+
41
+ Run these checks first. Any hits = mandatory fixes.
123
42
 
124
43
  ```bash
125
- npx tsc --noEmit 2>&1 | head -20
44
+ # Generic fonts (the #1 AI tell)
45
+ grep -rn "Inter\|Roboto\|Arial\|Helvetica\|system-ui\|Space.Grotesk" --include="*.tsx" --include="*.css" --include="*.scss" --include="tailwind*" app/ components/ src/ 2>/dev/null | grep -v node_modules
46
+
47
+ # Hardcoded max-width containers (screams template)
48
+ grep -rn "max-w-7xl\|max-w-\[1200\|max-w-\[1280\|max-width.*1200\|max-width.*1280" --include="*.tsx" --include="*.css" app/ components/ src/ 2>/dev/null
49
+
50
+ # Blue-purple gradients
51
+ grep -rn "from-blue.*to-purple\|from-purple.*to-blue\|linear-gradient.*blue.*purple\|linear-gradient.*purple.*blue\|from-indigo.*to-violet" --include="*.tsx" --include="*.css" app/ components/ src/ 2>/dev/null
52
+
53
+ # Card grid monotony (same card component repeated in a grid)
54
+ grep -rn "grid-cols-3\|grid-cols-4" --include="*.tsx" app/ components/ src/ 2>/dev/null | head -5
55
+
56
+ # Generic hero patterns
57
+ grep -rn "text-center.*mx-auto\|Hero\|hero" --include="*.tsx" app/ components/ src/ 2>/dev/null | head -5
58
+
59
+ # Scattered hardcoded colors (no design system)
60
+ grep -rn "text-\[#\|bg-\[#\|border-\[#\|color:.*#\|background:.*#" --include="*.tsx" app/ components/ src/ 2>/dev/null | wc -l
126
61
  ```
127
62
 
128
- Fix any TypeScript errors before committing.
63
+ **Every hit gets fixed.** Not flagged — fixed.
64
+
65
+ ### 2. Typography Pass
66
+
67
+ **Goal:** A reader should feel the type was chosen, not defaulted.
68
+
69
+ - Pick a distinctive display font. Not Inter, not Roboto, not system. Something with character: Clash Display, Cabinet Grotesk, General Sans, Satoshi, Plus Jakarta Sans, Outfit, Sora, Manrope. Pair with a clean body font.
70
+ - Establish clear hierarchy: display (hero text) → h1 → h2 → h3 → body → caption
71
+ - Body: 16px minimum, line-height 1.5-1.7
72
+ - Headings: tighter line-height (1.1-1.3), negative letter-spacing (-0.02em) for display sizes
73
+ - Weight hierarchy: Regular (400) for body, Medium (500) for labels, Semibold (600) for headings, Bold (700) for display
74
+ - Prose content: `max-width: 65ch`. Everything else: fluid full-width.
75
+ - Use `clamp()` for fluid sizing: `clamp(2rem, 1rem + 3vw, 3.75rem)` for h1
76
+
77
+ ### 3. Color & Surfaces
78
+
79
+ **Goal:** A palette that looks intentional, not random.
80
+
81
+ - Define all colors as CSS variables or Tailwind config — zero scattered hex values
82
+ - One dominant brand color. One sharp accent for CTAs that pops against the page.
83
+ - Surfaces: layer them. Background → card → elevated card. Use subtle shade differences, not just white-on-white.
84
+ - Dark mode (if present): rethink surfaces, don't just invert. Slightly reduce contrast. Use darker brand colors, not just white→black swap.
85
+ - Semantic colors with non-color indicators: success (green + checkmark), error (red + icon), warning (amber + triangle)
86
+ - Verify WCAG AA: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+)
87
+
88
+ ### 4. Layout & Spacing
89
+
90
+ **Goal:** Full-width, fluid, generous. No dead space gutters.
91
+
92
+ - Full-width layouts with fluid padding: `clamp(1rem, 5vw, 4rem)` horizontal
93
+ - 8px spacing grid: 4, 8, 12, 16, 24, 32, 48, 64, 96
94
+ - Tight spacing within groups (related items). Generous spacing between sections.
95
+ - Break symmetry where it serves the design — offset grids, overlapping elements, diagonal flow
96
+ - Varied layouts: not every section should be a centered-text-with-cards-below. Use side-by-side, staggered, asymmetric, full-bleed.
97
+ - Section spacing: `clamp(2rem, 8vw, 6rem)` vertical padding
98
+
99
+ ### 5. Interactive States
129
100
 
130
- ### 5. Commit & Transition
101
+ **Goal:** Every clickable thing responds. Every async operation shows progress.
102
+
103
+ - **Hover:** color shift or underline within 150ms ease-out. `cursor: pointer` on ALL clickables.
104
+ - **Focus:** visible ring (2px+ offset, contrasting color). Never `outline: none` without replacement.
105
+ - **Active/pressed:** subtle scale down (`transform: scale(0.98)`) or color shift.
106
+ - **Disabled:** opacity 0.5 + `cursor: not-allowed` + `aria-disabled="true"`
107
+ - **Loading:** skeleton shimmer or spinner on every async operation. Never a blank void.
108
+ - **Empty:** helpful message + CTA on empty lists/tables. Not just "No results."
109
+ - **Error:** user-friendly message + recovery action. Not raw error text. Use `aria-live="assertive"`.
110
+
111
+ ### 6. Motion & Personality
112
+
113
+ **Goal:** The site feels alive, not static. But tasteful — not a circus.
114
+
115
+ - Page load: stagger children entrance (50-80ms delay between items, `fadeUp` animation, 300ms)
116
+ - Hover transitions: 150-200ms ease-out
117
+ - Section transitions: 300-500ms with `cubic-bezier(0.4, 0, 0.2, 1)`
118
+ - One signature motion that gives the site personality (parallax, scroll-triggered reveal, magnetic buttons, morphing shapes)
119
+ - **Always** `prefers-reduced-motion: reduce` — disable non-essential animation
120
+ - CSS-only for static sites, `motion/react` (formerly Framer Motion) for React
121
+
122
+ ### 7. Accessibility (Non-Negotiable)
123
+
124
+ - Semantic HTML: `nav`, `main`, `section`, `article`, `header`, `footer` — not div soup
125
+ - One `h1` per page, sequential heading order (no h1 → h3 skip)
126
+ - All images: descriptive `alt` (or `alt=""` + `aria-hidden` if decorative)
127
+ - All form inputs: visible `<label>` with `htmlFor` — not placeholder-only
128
+ - All interactive elements: keyboard accessible (Tab, Enter, Escape, Arrow keys)
129
+ - Touch targets: 44x44px minimum
130
+ - Skip link: `<a href="#main" class="sr-only focus:not-sr-only">` as first focusable element
131
+ - `<html lang="en">` set
132
+ - Color never the sole information carrier — icons, text, patterns as supplements
133
+ - `aria-live="polite"` for toast notifications and dynamic content updates
134
+
135
+ ### 8. Responsive (Mobile-First)
136
+
137
+ - Base styles for mobile (320px), scale up with `min-width` breakpoints
138
+ - Test at: 320px (small phone), 375px (iPhone), 768px (iPad), 1024px (laptop), 1440px (desktop)
139
+ - No horizontal scroll at any viewport
140
+ - Navigation: hamburger/drawer on mobile, full horizontal on desktop
141
+ - Stack on mobile, expand on desktop
142
+ - Fluid typography with `clamp()`
143
+ - Images: `max-width: 100%`, responsive `srcset`, `next/image` with width/height
144
+ - Tables: card layout or horizontal scroll on mobile
145
+
146
+ ### 9. Harden (Edge Cases)
147
+
148
+ After all visual work, stress-test:
149
+ - Long text: does a 200-character username break the layout?
150
+ - Empty everywhere: all lists empty, all data missing — does it still make sense?
151
+ - Error everywhere: every fetch fails — are error states visible and helpful?
152
+ - 320px viewport: nothing overflows, nothing clips, nothing overlaps
153
+ - Keyboard only: Tab through the entire app — can you reach everything? Is focus visible?
154
+ - Slow network: are loading states visible? Does content stream in or flash?
155
+
156
+ ### 10. Verify & Ship
157
+
158
+ ```bash
159
+ npx tsc --noEmit 2>&1 | head -20
160
+ ```
161
+
162
+ Fix any TypeScript errors.
131
163
 
132
164
  ```bash
133
165
  git add {changed files}
134
- git commit -m "polish: design and UX pass — typography, accessibility, responsive, states"
166
+ git commit -m "polish: design pass — typography, color, states, motion, responsive, a11y"
135
167
  ```
136
168
 
137
169
  ```bash
138
170
  node ~/.claude/bin/state.js transition --to polished
139
171
  ```
140
- Do NOT manually edit STATE.md or tracking.json — state.js handles both.
141
-
142
- ### 6. Report
143
172
 
144
173
  ```bash
145
174
  node ~/.claude/bin/qualia-ui.js divider
146
- node ~/.claude/bin/qualia-ui.js info "Files modified: {N}"
147
- node ~/.claude/bin/qualia-ui.js ok "Typography {brief}"
148
- node ~/.claude/bin/qualia-ui.js ok "Color {brief}"
149
- node ~/.claude/bin/qualia-ui.js ok "Layout {brief}"
150
- node ~/.claude/bin/qualia-ui.js ok "States {brief}"
151
- node ~/.claude/bin/qualia-ui.js ok "Motion {brief}"
152
- node ~/.claude/bin/qualia-ui.js ok "Accessibility {brief}"
153
- node ~/.claude/bin/qualia-ui.js ok "Responsive {brief}"
154
- node ~/.claude/bin/qualia-ui.js ok "Performance {brief}"
155
- node ~/.claude/bin/qualia-ui.js ok "Hardening — {brief}"
175
+ node ~/.claude/bin/qualia-ui.js ok "AI slop: killed"
176
+ node ~/.claude/bin/qualia-ui.js ok "Typography: {brief}"
177
+ node ~/.claude/bin/qualia-ui.js ok "Color: {brief}"
178
+ node ~/.claude/bin/qualia-ui.js ok "Layout: {brief}"
179
+ node ~/.claude/bin/qualia-ui.js ok "States: {brief}"
180
+ node ~/.claude/bin/qualia-ui.js ok "Motion: {brief}"
181
+ node ~/.claude/bin/qualia-ui.js ok "Accessibility: {brief}"
182
+ node ~/.claude/bin/qualia-ui.js ok "Responsive: {brief}"
183
+ node ~/.claude/bin/qualia-ui.js ok "Hardened: {brief}"
156
184
  node ~/.claude/bin/qualia-ui.js end "POLISHED" "/qualia-ship"
157
185
  ```
186
+
187
+ ## Rules
188
+
189
+ 1. **Read before write.** Understand every file before changing it.
190
+ 2. **DESIGN.md is law.** If it exists, follow it. Don't override client decisions.
191
+ 3. **Don't break functionality.** Only change styling, never logic.
192
+ 4. **AI slop is a bug.** Generic fonts, card grids, blue-purple gradients, centered-everything — treat these as defects, not preferences.
193
+ 5. **TypeScript must pass** after every change.
194
+ 6. **One commit** at the end — not per category.
@@ -73,26 +73,35 @@ git commit -m "report: session {YYYY-MM-DD}"
73
73
  git push
74
74
  ```
75
75
 
76
- ### 5. Upload to ERP
76
+ ### 5. Upload to ERP (if enabled)
77
77
 
78
- **This step is MANDATORY** — the clock-out modal requires the report to be uploaded.
78
+ Read `~/.claude/.qualia-config.json` and check the `erp` object:
79
+ - If `erp.enabled` is `false`, skip this step and print: "ERP upload skipped (disabled in config)."
80
+ - If `erp.enabled` is `true` (default) or the `erp` field is missing (backward compatibility), proceed with the upload.
79
81
 
80
82
  ```bash
81
- ERP_URL="https://portal.qualiasolutions.net"
83
+ # Read ERP config
84
+ ERP_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.claude/.qualia-config.json','utf8'));console.log(c.erp?.url||'https://portal.qualiasolutions.net')}catch{console.log('https://portal.qualiasolutions.net')}")
85
+ ERP_ENABLED=$(node -e "try{const c=JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.claude/.qualia-config.json','utf8'));console.log(c.erp?.enabled!==false)}catch{console.log('true')}")
86
+
82
87
  API_KEY=$(cat ~/.claude/.erp-api-key 2>/dev/null)
83
88
  REPORT_FILE=".planning/reports/report-{date}.md"
84
89
  EMAIL=$(git config user.email)
85
90
  PROJECT=$(basename $(pwd))
86
91
 
87
- curl -s -X POST "$ERP_URL/api/claude/report-upload" \
88
- -H "X-API-Key: $API_KEY" \
89
- -F "file=@$REPORT_FILE" \
90
- -F "employee_email=$EMAIL" \
91
- -F "project_name=$PROJECT"
92
+ # Only upload if ERP is enabled
93
+ if [ "$ERP_ENABLED" = "true" ]; then
94
+ curl -s -X POST "$ERP_URL/api/claude/report-upload" \
95
+ -H "X-API-Key: $API_KEY" \
96
+ -F "file=@$REPORT_FILE" \
97
+ -F "employee_email=$EMAIL" \
98
+ -F "project_name=$PROJECT"
99
+ fi
92
100
  ```
93
101
 
94
102
  If the upload succeeds, print: "Report uploaded to ERP. You can now clock out."
95
103
  If it fails (no API key, network error), print the error and tell the employee to ask Fawzi.
104
+ If ERP is disabled, print: "ERP upload skipped (disabled in config)."
96
105
 
97
106
  ### 6. Update State
98
107
 
@@ -1,76 +1,161 @@
1
1
  ---
2
2
  name: qualia-review
3
- description: "Production audit and code review. General review, --web for web app audit, --ai for AI/voice agent audit. Trigger on 'review', 'audit', 'code review', 'security check', 'production check'."
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
- Deep review with severity-scored findings. Different from `/qualia-verify` (which checks phase goals). This checks production readiness.
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` — General code review
13
- - `/qualia-review --web` — Web app production audit
14
- - `/qualia-review --ai` — AI/voice agent audit
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
- ## General Review (default)
16
+ ## Process
17
17
 
18
18
  ```bash
19
19
  node ~/.claude/bin/qualia-ui.js banner review
20
20
  ```
21
21
 
22
- Spawn parallel agents analyzing:
22
+ ### 0. Load Context
23
23
 
24
- 1. **Code Quality** — Clean code, TypeScript strictness, naming, readability
25
- 2. **Security** — OWASP top 10, auth server-side, RLS policies, secrets scan
26
- 3. **Architecture** — Component boundaries, coupling, API contracts
27
- 4. **Performance** — N+1 queries, bundle size, caching, render performance
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
- ## --web (Web App Audit)
29
+ Detect project shape:
30
+ ```bash
31
+ ls package.json next.config.* tsconfig.json supabase/ app/ src/ 2>/dev/null
32
+ ```
31
33
 
32
- Full production readiness for Next.js + Supabase + Vercel:
34
+ ### 1. Security Scan
33
35
 
34
- **Security:** No secrets in code, HTTPS, CORS restricted, CSP headers, rate limiting, npm audit clean.
36
+ Run every command. Record each finding with severity.
35
37
 
36
- **Performance:** Core Web Vitals (LCP < 2.5s, CLS < 0.1), image optimization, bundle analysis, query performance.
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
- **Reliability:** Error boundaries, API error handling, graceful degradation, health check endpoint.
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
- **Observability:** Error tracking (Sentry), structured logging, uptime monitoring, analytics.
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
- ## --ai (AI/Voice Agent Audit)
48
+ # CRITICAL: .env files tracked in git
49
+ git ls-files | grep -i "\.env" | grep -v "\.example\|\.template\|\.sample"
43
50
 
44
- Auto-detect stack (VAPI, ElevenLabs, Retell, OpenAI, Anthropic, pgvector).
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
- **Prompt Safety:** System prompts not exposed, injection defenses, no eval() on AI output, token limits.
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
- **Conversation Flow:** Off-topic handling, context window management, error recovery, human handoff.
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
- **Voice (if detected):** Latency < 500ms, interruption handling, silence timeout, webhook security.
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
- **RAG (if detected):** Embedding consistency, chunk size, retrieval relevance, index refresh.
68
+ ### 2. Code Quality Scan
53
69
 
54
- **Resilience:** Provider failover, timeout handling, cost monitoring, streaming error recovery.
70
+ ```bash
71
+ # TypeScript errors (HIGH if >0)
72
+ npx tsc --noEmit 2>&1 | grep -c "error TS"
55
73
 
56
- ## Output
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
- Every finding:
59
- - **What** description
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
- Write to `.planning/REVIEW.md`. CRITICAL or HIGH findings are deploy blockers `/qualia-ship` checks for them.
80
+ # TODO/FIXME left in code (LOWcount)
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
- ◆ Review Complete
68
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
69
- Critical: {N}
70
- High: {N}
71
- Medium: {N}
72
- Low: {N}
73
-
74
- {If blockers: Fix CRITICAL/HIGH before /qualia-ship}
75
- {If clean: Ready to ship}
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.