qualia-framework 3.2.0 → 3.2.1

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.
@@ -25,7 +25,7 @@ node ~/.claude/bin/qualia-ui.js banner design
25
25
  cat .planning/DESIGN.md 2>/dev/null || echo "NO_DESIGN"
26
26
  ```
27
27
 
28
- If DESIGN.md exists → use it. If not → use Qualia defaults: distinctive fonts, sharp accents, layered backgrounds, no card grids, no blue-purple gradients, full-width layouts.
28
+ If DESIGN.md exists → it is law. Use exact values from sections 1-9 (Visual Theme, Color Palette, Typography, Components, Layout, Depth, Do's/Don'ts, Responsive, Agent Prompt Guide). If not → use Qualia defaults from `rules/frontend.md`: distinctive fonts, sharp accents, layered backgrounds, no card grids, no blue-purple gradients, full-width layouts.
29
29
 
30
30
  ### 2. Find Target Files
31
31
 
@@ -41,19 +41,25 @@ Evaluate each file on: AI slop detection, visual hierarchy, typography, color, s
41
41
 
42
42
  ### 4. Fix Everything
43
43
 
44
- **Typography:** Replace generic fonts (Inter, Arial) with distinctive ones. Proper type scale, line-height 1.5-1.7 body.
44
+ Use exact values from DESIGN.md when available. Sections map to fixes:
45
45
 
46
- **Color:** Cohesive palette from DESIGN.md or brand. Sharp accent for CTAs. WCAG AA contrast.
46
+ **Typography (§3):** Apply fonts from hierarchy table. Replace any generic fonts (Inter, Arial) with project fonts. Use exact weights, sizes, letter-spacing from the table. Body line-height 1.5-1.7.
47
47
 
48
- **Layout:** Full-width with fluid padding `clamp(1rem, 5vw, 4rem)`. NO hardcoded max-width caps. Prose gets `max-width: 65ch`.
48
+ **Color (§2):** Apply palette from CSS variables. Replace scattered hex values with `var(--color-*)`. Verify contrast ratios listed in DESIGN.md.
49
49
 
50
- **Spacing:** Consistent scale (8px grid). Generous whitespace between sections, tight within groups.
50
+ **Components (§4):** Match button, card, input, badge specs exactly — padding, radius, shadow, hover states.
51
51
 
52
- **Motion:** CSS transitions 200-300ms on hover/focus. Staggered entrance animations. `prefers-reduced-motion` respected.
52
+ **Layout (§5):** Full-width with fluid padding `clamp(1rem, 5vw, 4rem)`. Apply spacing scale. NO hardcoded max-width caps. Prose gets `max-width: 65ch`.
53
53
 
54
- **States:** Loading skeleton/spinner on async ops. Error states on data fetches. Empty states on lists. Hover/focus/active/disabled on interactive elements.
54
+ **Depth (§6):** Apply shadow levels from elevation table. Use brand-tinted shadows, not neutral gray.
55
55
 
56
- **Responsive:** Mobile-first. Touch targets 44x44px min. Stack on mobile, expand on desktop. No horizontal scroll.
56
+ **Motion (§Motion):** CSS transitions 200-300ms on hover/focus. Staggered entrance animations. `prefers-reduced-motion` respected.
57
+
58
+ **States:** Loading skeleton/spinner on async ops. Error states on data fetches. Empty states on lists. Hover/focus/active/disabled on every interactive element.
59
+
60
+ **Responsive (§8):** Apply collapsing strategy from table. Mobile-first. Touch targets 44x44px min. No horizontal scroll.
61
+
62
+ **Anti-Slop (§12):** Run grep patterns from the detection table. Every match = mandatory fix.
57
63
 
58
64
  **Kill:** Card grids → varied layouts. Generic heroes → distinctive. Blue-purple gradients → brand colors. Static pages → purposeful motion. Fixed widths → fluid.
59
65
 
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: qualia-help
3
+ description: "Open the Qualia Framework reference guide in the browser. A beautiful themed HTML page with all commands, rules, services, and the road. Trigger on 'help', 'how does this work', 'show me the commands', 'qualia help', 'reference'."
4
+ ---
5
+
6
+ # /qualia-help — Framework Reference
7
+
8
+ Opens a Qualia-themed HTML reference guide in your default browser.
9
+
10
+ ## Process
11
+
12
+ ### 1. Generate the HTML
13
+
14
+ ```bash
15
+ # Read the template and inject the current version
16
+ VERSION=$(node -e "console.log(require(require('os').homedir() + '/.claude/.qualia-config.json').version || 'v3')" 2>/dev/null || echo "v3")
17
+ TEMPLATE="$HOME/.claude/qualia-templates/help.html"
18
+ OUTPUT="/tmp/qualia-help.html"
19
+
20
+ # If template doesn't exist, check the framework install
21
+ if [ ! -f "$TEMPLATE" ]; then
22
+ TEMPLATE="$(dirname "$(dirname "$(which qualia-framework 2>/dev/null || echo '')")")/templates/help.html"
23
+ fi
24
+ ```
25
+
26
+ ### 2. Inject version and open
27
+
28
+ ```bash
29
+ # Replace {{VERSION}} placeholder with actual version
30
+ sed "s/{{VERSION}}/$VERSION/g" "$TEMPLATE" > "$OUTPUT"
31
+
32
+ # Open in default browser (cross-platform)
33
+ if command -v xdg-open &>/dev/null; then
34
+ xdg-open "$OUTPUT" # Linux
35
+ elif command -v open &>/dev/null; then
36
+ open "$OUTPUT" # macOS
37
+ elif command -v start &>/dev/null; then
38
+ start "$OUTPUT" # Windows (Git Bash)
39
+ else
40
+ echo "Open this file in your browser: $OUTPUT"
41
+ fi
42
+ ```
43
+
44
+ ### 3. Confirm
45
+
46
+ ```bash
47
+ node ~/.claude/bin/qualia-ui.js banner router
48
+ node ~/.claude/bin/qualia-ui.js ok "Reference guide opened in browser"
49
+ node ~/.claude/bin/qualia-ui.js info "File: /tmp/qualia-help.html"
50
+ ```
51
+
52
+ If the browser does not open automatically, tell the user the file path so they can open it manually.
53
+
54
+ ## Notes
55
+
56
+ - The HTML file is self-contained — no external dependencies except Google Fonts
57
+ - Works offline after first load (fonts cache)
58
+ - Qualia-themed: dark background, teal accents, Outfit + Inter fonts
59
+ - Shows: The Road, all commands grouped, verification scoring, rules, stack, GitHub orgs
60
+ - Version is injected dynamically from .qualia-config.json
@@ -46,17 +46,40 @@ What did you learn?
46
46
  3. Client preference — client-specific requirement
47
47
  ```
48
48
 
49
- ### 2. Format Entry
49
+ ### 2. Check for Duplicates
50
+
51
+ Before saving, check if a similar entry already exists:
52
+
53
+ ```bash
54
+ # Search for the title (case-insensitive substring match)
55
+ grep -i "{title keywords}" ~/.claude/knowledge/{type}.md 2>/dev/null
56
+ ```
57
+
58
+ If a near-match exists (title is similar to an existing entry):
59
+ - Show the existing entry to the user
60
+ - Ask: "A similar entry exists. Update it, create a new one, or skip?"
61
+ - If update: replace the existing entry. If new: append. If skip: done.
62
+
63
+ ### 3. Format Entry
64
+
65
+ Each entry gets a unique ID and ISO timestamp for dedup and ordering:
50
66
 
51
67
  ```markdown
52
- ### {Title} ({date})
68
+
69
+ ---
70
+
71
+ ### {Title}
72
+ **ID:** {random 8-char hex, e.g. a3f7c1e9}
73
+ **Date:** {ISO 8601, e.g. 2026-04-11}
53
74
  **Project:** {current project name or "general"}
54
75
  **Context:** {brief context — what you were building when you learned this}
55
76
 
56
77
  {The learning — be specific enough that future-you understands without context}
57
78
  ```
58
79
 
59
- ### 3. Append to Knowledge File
80
+ ### 4. Append to Knowledge File
81
+
82
+ Append-only — never overwrite the file, always add at the end:
60
83
 
61
84
  ```bash
62
85
  # Append to the right file
@@ -67,7 +90,7 @@ echo "{formatted entry}" >> ~/.claude/knowledge/{type}.md
67
90
  - Fix → `~/.claude/knowledge/common-fixes.md`
68
91
  - Client pref → `~/.claude/knowledge/client-prefs.md`
69
92
 
70
- ### 4. Confirm
93
+ ### 5. Confirm
71
94
 
72
95
  ```
73
96
  ⬢ Saved to {file}
@@ -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,176 @@ 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. Read ALL 12 sections. Key sections for polish:
36
+ - §1 Visual Theme — the feel and signature details
37
+ - §2 Color Palette — exact hex values, CSS variables, contrast ratios
38
+ - §3 Typography — hierarchy table with exact sizes/weights/spacing
39
+ - §4 Components — exact button/card/input/badge specs
40
+ - §5 Layout — spacing scale, grid strategy
41
+ - §6 Depth & Elevation — shadow levels with exact rgba values
42
+ - §7 Do's/Don'ts — brand-specific guardrails
43
+ - §9 Agent Prompt Guide — quick reference for common patterns
44
+ - §10 Accessibility — WCAG checklist
45
+ - §11 Hardening — stress-test criteria
46
+ - §12 Anti-Slop Detection — grep patterns for automated checks
47
+
48
+ If no DESIGN.md → use `rules/frontend.md` defaults.
23
49
 
24
50
  Read EVERY frontend file before modifying. No blind edits.
25
51
 
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
52
+ ### 1. AI Slop Detector
53
+
54
+ Run these checks first. Any hits = mandatory fixes.
123
55
 
124
56
  ```bash
125
- npx tsc --noEmit 2>&1 | head -20
57
+ # Generic fonts (the #1 AI tell)
58
+ 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
59
+
60
+ # Hardcoded max-width containers (screams template)
61
+ 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
62
+
63
+ # Blue-purple gradients
64
+ 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
65
+
66
+ # Card grid monotony (same card component repeated in a grid)
67
+ grep -rn "grid-cols-3\|grid-cols-4" --include="*.tsx" app/ components/ src/ 2>/dev/null | head -5
68
+
69
+ # Generic hero patterns
70
+ grep -rn "text-center.*mx-auto\|Hero\|hero" --include="*.tsx" app/ components/ src/ 2>/dev/null | head -5
71
+
72
+ # Scattered hardcoded colors (no design system)
73
+ grep -rn "text-\[#\|bg-\[#\|border-\[#\|color:.*#\|background:.*#" --include="*.tsx" app/ components/ src/ 2>/dev/null | wc -l
126
74
  ```
127
75
 
128
- Fix any TypeScript errors before committing.
76
+ **Every hit gets fixed.** Not flagged — fixed.
77
+
78
+ ### 2. Typography Pass
79
+
80
+ **Goal:** A reader should feel the type was chosen, not defaulted.
81
+
82
+ - 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.
83
+ - Establish clear hierarchy: display (hero text) → h1 → h2 → h3 → body → caption
84
+ - Body: 16px minimum, line-height 1.5-1.7
85
+ - Headings: tighter line-height (1.1-1.3), negative letter-spacing (-0.02em) for display sizes
86
+ - Weight hierarchy: Regular (400) for body, Medium (500) for labels, Semibold (600) for headings, Bold (700) for display
87
+ - Prose content: `max-width: 65ch`. Everything else: fluid full-width.
88
+ - Use `clamp()` for fluid sizing: `clamp(2rem, 1rem + 3vw, 3.75rem)` for h1
89
+
90
+ ### 3. Color & Surfaces
91
+
92
+ **Goal:** A palette that looks intentional, not random.
93
+
94
+ - Define all colors as CSS variables or Tailwind config — zero scattered hex values
95
+ - One dominant brand color. One sharp accent for CTAs that pops against the page.
96
+ - Surfaces: layer them. Background → card → elevated card. Use subtle shade differences, not just white-on-white.
97
+ - Dark mode (if present): rethink surfaces, don't just invert. Slightly reduce contrast. Use darker brand colors, not just white→black swap.
98
+ - Semantic colors with non-color indicators: success (green + checkmark), error (red + icon), warning (amber + triangle)
99
+ - Verify WCAG AA: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+)
100
+
101
+ ### 4. Layout & Spacing
102
+
103
+ **Goal:** Full-width, fluid, generous. No dead space gutters.
104
+
105
+ - Full-width layouts with fluid padding: `clamp(1rem, 5vw, 4rem)` horizontal
106
+ - 8px spacing grid: 4, 8, 12, 16, 24, 32, 48, 64, 96
107
+ - Tight spacing within groups (related items). Generous spacing between sections.
108
+ - Break symmetry where it serves the design — offset grids, overlapping elements, diagonal flow
109
+ - Varied layouts: not every section should be a centered-text-with-cards-below. Use side-by-side, staggered, asymmetric, full-bleed.
110
+ - Section spacing: `clamp(2rem, 8vw, 6rem)` vertical padding
111
+
112
+ ### 5. Interactive States
129
113
 
130
- ### 5. Commit & Transition
114
+ **Goal:** Every clickable thing responds. Every async operation shows progress.
115
+
116
+ - **Hover:** color shift or underline within 150ms ease-out. `cursor: pointer` on ALL clickables.
117
+ - **Focus:** visible ring (2px+ offset, contrasting color). Never `outline: none` without replacement.
118
+ - **Active/pressed:** subtle scale down (`transform: scale(0.98)`) or color shift.
119
+ - **Disabled:** opacity 0.5 + `cursor: not-allowed` + `aria-disabled="true"`
120
+ - **Loading:** skeleton shimmer or spinner on every async operation. Never a blank void.
121
+ - **Empty:** helpful message + CTA on empty lists/tables. Not just "No results."
122
+ - **Error:** user-friendly message + recovery action. Not raw error text. Use `aria-live="assertive"`.
123
+
124
+ ### 6. Motion & Personality
125
+
126
+ **Goal:** The site feels alive, not static. But tasteful — not a circus.
127
+
128
+ - Page load: stagger children entrance (50-80ms delay between items, `fadeUp` animation, 300ms)
129
+ - Hover transitions: 150-200ms ease-out
130
+ - Section transitions: 300-500ms with `cubic-bezier(0.4, 0, 0.2, 1)`
131
+ - One signature motion that gives the site personality (parallax, scroll-triggered reveal, magnetic buttons, morphing shapes)
132
+ - **Always** `prefers-reduced-motion: reduce` — disable non-essential animation
133
+ - CSS-only for static sites, `motion/react` (formerly Framer Motion) for React
134
+
135
+ ### 7. Accessibility (Non-Negotiable)
136
+
137
+ - Semantic HTML: `nav`, `main`, `section`, `article`, `header`, `footer` — not div soup
138
+ - One `h1` per page, sequential heading order (no h1 → h3 skip)
139
+ - All images: descriptive `alt` (or `alt=""` + `aria-hidden` if decorative)
140
+ - All form inputs: visible `<label>` with `htmlFor` — not placeholder-only
141
+ - All interactive elements: keyboard accessible (Tab, Enter, Escape, Arrow keys)
142
+ - Touch targets: 44x44px minimum
143
+ - Skip link: `<a href="#main" class="sr-only focus:not-sr-only">` as first focusable element
144
+ - `<html lang="en">` set
145
+ - Color never the sole information carrier — icons, text, patterns as supplements
146
+ - `aria-live="polite"` for toast notifications and dynamic content updates
147
+
148
+ ### 8. Responsive (Mobile-First)
149
+
150
+ - Base styles for mobile (320px), scale up with `min-width` breakpoints
151
+ - Test at: 320px (small phone), 375px (iPhone), 768px (iPad), 1024px (laptop), 1440px (desktop)
152
+ - No horizontal scroll at any viewport
153
+ - Navigation: hamburger/drawer on mobile, full horizontal on desktop
154
+ - Stack on mobile, expand on desktop
155
+ - Fluid typography with `clamp()`
156
+ - Images: `max-width: 100%`, responsive `srcset`, `next/image` with width/height
157
+ - Tables: card layout or horizontal scroll on mobile
158
+
159
+ ### 9. Harden (Edge Cases)
160
+
161
+ After all visual work, stress-test:
162
+ - Long text: does a 200-character username break the layout?
163
+ - Empty everywhere: all lists empty, all data missing — does it still make sense?
164
+ - Error everywhere: every fetch fails — are error states visible and helpful?
165
+ - 320px viewport: nothing overflows, nothing clips, nothing overlaps
166
+ - Keyboard only: Tab through the entire app — can you reach everything? Is focus visible?
167
+ - Slow network: are loading states visible? Does content stream in or flash?
168
+
169
+ ### 10. Verify & Ship
170
+
171
+ ```bash
172
+ npx tsc --noEmit 2>&1 | head -20
173
+ ```
174
+
175
+ Fix any TypeScript errors.
131
176
 
132
177
  ```bash
133
178
  git add {changed files}
134
- git commit -m "polish: design and UX pass — typography, accessibility, responsive, states"
179
+ git commit -m "polish: design pass — typography, color, states, motion, responsive, a11y"
135
180
  ```
136
181
 
137
182
  ```bash
138
183
  node ~/.claude/bin/state.js transition --to polished
139
184
  ```
140
- Do NOT manually edit STATE.md or tracking.json — state.js handles both.
141
-
142
- ### 6. Report
143
185
 
144
186
  ```bash
145
187
  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}"
188
+ node ~/.claude/bin/qualia-ui.js ok "AI slop: killed"
189
+ node ~/.claude/bin/qualia-ui.js ok "Typography: {brief}"
190
+ node ~/.claude/bin/qualia-ui.js ok "Color: {brief}"
191
+ node ~/.claude/bin/qualia-ui.js ok "Layout: {brief}"
192
+ node ~/.claude/bin/qualia-ui.js ok "States: {brief}"
193
+ node ~/.claude/bin/qualia-ui.js ok "Motion: {brief}"
194
+ node ~/.claude/bin/qualia-ui.js ok "Accessibility: {brief}"
195
+ node ~/.claude/bin/qualia-ui.js ok "Responsive: {brief}"
196
+ node ~/.claude/bin/qualia-ui.js ok "Hardened: {brief}"
156
197
  node ~/.claude/bin/qualia-ui.js end "POLISHED" "/qualia-ship"
157
198
  ```
199
+
200
+ ## Rules
201
+
202
+ 1. **Read before write.** Understand every file before changing it.
203
+ 2. **DESIGN.md is law.** If it exists, follow it. Don't override client decisions.
204
+ 3. **Don't break functionality.** Only change styling, never logic.
205
+ 4. **AI slop is a bug.** Generic fonts, card grids, blue-purple gradients, centered-everything — treat these as defects, not preferences.
206
+ 5. **TypeScript must pass** after every change.
207
+ 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