qualia-framework 4.4.0 → 4.5.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 +13 -1
- package/README.md +1 -2
- package/agents/builder.md +12 -20
- package/agents/plan-checker.md +18 -0
- package/agents/planner.md +9 -0
- package/agents/verifier.md +62 -0
- package/bin/cli.js +10 -5
- package/bin/install.js +6 -0
- package/bin/slop-detect.mjs +357 -0
- package/bin/state.js +184 -1
- package/docs/erp-contract.md +5 -0
- package/package.json +1 -1
- package/rules/design-brand.md +110 -0
- package/rules/design-laws.md +144 -0
- package/rules/design-product.md +110 -0
- package/rules/design-rubric.md +153 -0
- package/skills/qualia-new/SKILL.md +40 -3
- package/skills/qualia-polish/SKILL.md +180 -136
- package/skills/qualia-report/SKILL.md +24 -4
- package/skills/zoho-workflow/SKILL.md +64 -0
- package/templates/DESIGN.md +229 -435
- package/templates/PRODUCT.md +95 -0
- package/skills/qualia-design/SKILL.md +0 -169
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Design Rubric
|
|
2
|
+
|
|
3
|
+
Anchored 1-5 scoring across 8 dimensions. Used by the verifier agent to score frontend phases. Used by `/qualia-polish --critique` for read-only audits.
|
|
4
|
+
|
|
5
|
+
## How to score
|
|
6
|
+
|
|
7
|
+
Every dimension is scored 1-5 with EVIDENCE on the next line. Score without evidence is rejected.
|
|
8
|
+
|
|
9
|
+
Anchored definitions:
|
|
10
|
+
- **1** — Fails. Hard violation. WCAG fails, broken layout, absolute-ban hit.
|
|
11
|
+
- **2** — Below acceptable. Functions but signals "AI generated this."
|
|
12
|
+
- **3** — Acceptable. Ships. Not memorable, not embarrassing.
|
|
13
|
+
- **4** — Good. Specific choices visible. A designer would approve.
|
|
14
|
+
- **5** — Excellent. Distinctive. Worth screenshotting and sharing.
|
|
15
|
+
|
|
16
|
+
**Default to 3.** Only score above 3 if you can cite a specific design principle the work excels at. Only score below 3 if you can quote evidence of a violation.
|
|
17
|
+
|
|
18
|
+
If a vision model is critiquing screenshots, it must score against this rubric. Without anchoring, vision models say "looks great!" to everything.
|
|
19
|
+
|
|
20
|
+
## Scope guard
|
|
21
|
+
|
|
22
|
+
Score only what is scope-relevant. A `/qualia-polish src/components/Button.tsx` review scores Typography, Color, States, Motion, Microcopy. Skip Layout Originality and Container Depth — they're component-internal concerns at most.
|
|
23
|
+
|
|
24
|
+
A whole-app `/qualia-polish` scores all 8 dimensions across multiple representative routes.
|
|
25
|
+
|
|
26
|
+
## The 8 dimensions
|
|
27
|
+
|
|
28
|
+
### 1. Typography
|
|
29
|
+
|
|
30
|
+
| Score | Criteria |
|
|
31
|
+
|---|---|
|
|
32
|
+
| 1 | Inter / Roboto / Arial / system-ui / Space Grotesk as primary. Or single weight throughout. |
|
|
33
|
+
| 2 | Project font loaded but only one weight, no scale, no letter-spacing variation. |
|
|
34
|
+
| 3 | Project font with 2-3 weights, basic scale (h1/h2/body), readable. |
|
|
35
|
+
| 4 | Distinctive display + refined body pair. Letter-spacing varied semantically (tight headlines, open labels). Tabular numerals on numeric data. |
|
|
36
|
+
| 5 | Variable font with axis-driven weight/optical-size. Hierarchy through weight + scale + letter-spacing combined. Line lengths capped at 65-75ch. |
|
|
37
|
+
|
|
38
|
+
Evidence format: `font-family: "<name>" used at line N, scale 14/16/24/40 visible, weights 400/500/700`
|
|
39
|
+
|
|
40
|
+
### 2. Color cohesion
|
|
41
|
+
|
|
42
|
+
| Score | Criteria |
|
|
43
|
+
|---|---|
|
|
44
|
+
| 1 | Hex values scattered in JSX. No CSS variables. Pure `#000` or `#fff`. |
|
|
45
|
+
| 2 | CSS variables defined but unused (raw hex still appears). RGB used. |
|
|
46
|
+
| 3 | All colors as CSS variables. Tinted neutrals (no pure black/white). One color strategy implied. |
|
|
47
|
+
| 4 | OKLCH throughout. Strategy explicit (Restrained / Committed / Full / Drenched). WCAG AA verified. |
|
|
48
|
+
| 5 | OKLCH with documented strategy. Chroma reduced at extremes. Brand-tinted shadows. APCA contrast verified for dense text. |
|
|
49
|
+
|
|
50
|
+
Evidence: count of CSS custom properties for color, presence of OKLCH, evidence of strategy commitment
|
|
51
|
+
|
|
52
|
+
### 3. Spatial rhythm
|
|
53
|
+
|
|
54
|
+
| Score | Criteria |
|
|
55
|
+
|---|---|
|
|
56
|
+
| 1 | Arbitrary px values everywhere. No system. |
|
|
57
|
+
| 2 | 8px grid roughly followed. Same padding everywhere. |
|
|
58
|
+
| 3 | 8px grid consistently. Tight within groups, generous between sections. |
|
|
59
|
+
| 4 | Fluid `clamp()` padding. Spacing varies by content type. Vertical rhythm identifiable. |
|
|
60
|
+
| 5 | Spatial system reads as composed — different spacing for different relationships. Generous negative space. Asymmetry where intentional. |
|
|
61
|
+
|
|
62
|
+
Evidence: presence of spacing tokens, padding values divisible by 4, `clamp()` usage
|
|
63
|
+
|
|
64
|
+
### 4. Layout originality
|
|
65
|
+
|
|
66
|
+
| Score | Criteria |
|
|
67
|
+
|---|---|
|
|
68
|
+
| 1 | Three-column feature grid in section 2. Card grid of 3 identical items. Centered hero with gradient. |
|
|
69
|
+
| 2 | Standard hero + sections + footer. Symmetric throughout. |
|
|
70
|
+
| 3 | Some layout variation across sections. No card monotony. |
|
|
71
|
+
| 4 | Asymmetry, full-bleed, varied component sizes within a section. Negative space used. |
|
|
72
|
+
| 5 | Layout reads as composed by a designer. Diagonal flow, overlap, scale contrast. Each section a different shape. |
|
|
73
|
+
|
|
74
|
+
Evidence: file:line references showing layout choices
|
|
75
|
+
|
|
76
|
+
### 5. Shadow & depth hierarchy
|
|
77
|
+
|
|
78
|
+
| Score | Criteria |
|
|
79
|
+
|---|---|
|
|
80
|
+
| 1 | Single shadow value applied to everything (or no shadows). Nested cards. |
|
|
81
|
+
| 2 | 2 shadow levels but applied inconsistently. |
|
|
82
|
+
| 3 | 3 elevation levels (subtle / medium / pronounced). Brand-tinted, not pure gray. |
|
|
83
|
+
| 4 | Shadows match elevation semantically. Different shadow for hover than rest. |
|
|
84
|
+
| 5 | Multi-layer shadows (offset + ambient + directional). Brand-hue tinted at chroma 0.02-0.04. Spatial logic clear. |
|
|
85
|
+
|
|
86
|
+
Evidence: count of distinct `box-shadow` values, OKLCH chroma in shadow color
|
|
87
|
+
|
|
88
|
+
### 6. Motion intent
|
|
89
|
+
|
|
90
|
+
| Score | Criteria |
|
|
91
|
+
|---|---|
|
|
92
|
+
| 1 | No transitions. Or: bounce/elastic everywhere. Animates layout properties. |
|
|
93
|
+
| 2 | Default browser transitions on hover. No stagger. |
|
|
94
|
+
| 3 | Considered transitions on interactive elements. Respects `prefers-reduced-motion`. |
|
|
95
|
+
| 4 | One signature motion identified and executed. Stagger on entrance. Easing curves chosen (ease-out-quart or expo). |
|
|
96
|
+
| 5 | Orchestrated motion that communicates structure. Scroll-driven if appropriate. Restraint elsewhere. |
|
|
97
|
+
|
|
98
|
+
Evidence: easing curves used, presence of `prefers-reduced-motion`, file:line of signature motion
|
|
99
|
+
|
|
100
|
+
### 7. Microcopy specificity
|
|
101
|
+
|
|
102
|
+
| Score | Criteria |
|
|
103
|
+
|---|---|
|
|
104
|
+
| 1 | "Get Started" / "Learn More" / "Welcome to <product>" / "Click here". Lorem ipsum. |
|
|
105
|
+
| 2 | Generic but functional ("Save", "Cancel", "Submit"). Empty states say "No results." |
|
|
106
|
+
| 3 | Action-named CTAs ("Download invoice"). Empty states with one-sentence context. |
|
|
107
|
+
| 4 | Voice consistent with brand. Errors specific and actionable ("This file is 12MB; max is 10MB. Compress and retry."). |
|
|
108
|
+
| 5 | Microcopy you'd quote. Voice unmistakable. Every word earned. |
|
|
109
|
+
|
|
110
|
+
Evidence: grep for banned phrases, sample of empty/error states
|
|
111
|
+
|
|
112
|
+
### 8. Container depth & nesting
|
|
113
|
+
|
|
114
|
+
| Score | Criteria |
|
|
115
|
+
|---|---|
|
|
116
|
+
| 1 | Card → panel → pill → content (depth ≥ 4). Side-stripe borders. Gradient text. |
|
|
117
|
+
| 2 | Card-on-card pattern (depth 3). Most things wrapped in containers. |
|
|
118
|
+
| 3 | Container depth ≤ 2. No decorative side-stripes. |
|
|
119
|
+
| 4 | Containers used semantically only. Things that don't need a container don't have one. |
|
|
120
|
+
| 5 | Layout reads as elements arranged on a surface, not boxes inside boxes. |
|
|
121
|
+
|
|
122
|
+
Evidence: max DOM nesting depth on cards/panels, grep for `border-left` decorative usage
|
|
123
|
+
|
|
124
|
+
## Aggregate score
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
total = sum of dimension scores (max 40)
|
|
128
|
+
average = total / count_of_scored_dimensions
|
|
129
|
+
phase_pass = ALL scored dimensions ≥ 3
|
|
130
|
+
phase_fail = ANY scored dimension < 3
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
A phase fails if any dimension is below 3. Same gate as functional verification.
|
|
134
|
+
|
|
135
|
+
## Output format (verifier agent contract)
|
|
136
|
+
|
|
137
|
+
```markdown
|
|
138
|
+
## Design Rubric — Phase {N}
|
|
139
|
+
|
|
140
|
+
| Dim | Score | Evidence |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| Typography | 4 | `app/page.tsx:14` Fraunces + JetBrains Mono pair, weights 400/500/700, clamp() scale visible |
|
|
143
|
+
| Color cohesion | 3 | All CSS vars in `app/globals.css:8-22`. OKLCH used. Strategy: Restrained. WCAG AA verified |
|
|
144
|
+
| Spatial rhythm | 5 | Fluid clamp padding throughout, varied within section, generous between |
|
|
145
|
+
| Layout originality | 2 | `app/page.tsx:42-78` is a three-column feature grid in section 2 — first-order slop. Rework. |
|
|
146
|
+
| ... | ... | ... |
|
|
147
|
+
|
|
148
|
+
**Aggregate:** 28/40 (avg 3.5)
|
|
149
|
+
**Phase verdict:** FAIL — Layout Originality at 2 blocks the phase.
|
|
150
|
+
**Fix priority:** Rework section 2. Replace three-column grid with varied-height layout per `design-brand.md` §Layout.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
If the score < 3, the verifier writes the diagnosis. The fix is the next builder's task.
|
|
@@ -107,6 +107,25 @@ git add .planning/PROJECT.md
|
|
|
107
107
|
git commit -m "docs: initialize project"
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
### Step 5b. Write PRODUCT.md (v4.5.0 — REQUIRED)
|
|
111
|
+
|
|
112
|
+
`PRODUCT.md` is the "who and why" every road agent reads before designing or building. It is **required** — the planner, builder, and verifier all load it as substrate.
|
|
113
|
+
|
|
114
|
+
Ask the user 5 short questions (one at a time, each with a sensible default they can `[Enter]` past):
|
|
115
|
+
|
|
116
|
+
1. **Register** — "Is this design IS the product (marketing/landing/portfolio → `brand`) or design SERVES the product (app/admin/dashboard → `product`)?" Default: infer from project type.
|
|
117
|
+
2. **Three users** — "Name 3 specific humans who will use this. Not personas — real names + their workflow scenario." Default: project type defaults.
|
|
118
|
+
3. **Brand voice** — "Three adjectives, then one paragraph showing the voice in motion (an error message, a confirmation, an empty state)." Default: derive from PROJECT.md.
|
|
119
|
+
4. **Anti-references** — "Three sites this should NOT look like, with why." Required, no defaults — anti-references are more useful than positive references.
|
|
120
|
+
5. **One-sentence differentiation** — "What does someone remember 24 hours after first using this?" Required.
|
|
121
|
+
|
|
122
|
+
Write `.planning/PRODUCT.md` from `templates/PRODUCT.md`, filling the user's answers.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git add .planning/PRODUCT.md
|
|
126
|
+
git commit -m "docs: PRODUCT.md — register, users, voice, anti-references"
|
|
127
|
+
```
|
|
128
|
+
|
|
110
129
|
### Step 6. Create config.json
|
|
111
130
|
|
|
112
131
|
```json
|
|
@@ -124,13 +143,31 @@ git commit -m "docs: initialize project"
|
|
|
124
143
|
|
|
125
144
|
**Note:** `workflow.research` is ALWAYS `true` for v4. It exists for telemetry but is no longer read as a gate.
|
|
126
145
|
|
|
127
|
-
### Step 7. Create DESIGN.md (frontend projects)
|
|
146
|
+
### Step 7. Create DESIGN.md (frontend projects — v4.5.0 OKLCH-first)
|
|
147
|
+
|
|
148
|
+
If frontend work is involved, generate `.planning/DESIGN.md` from `templates/DESIGN.md`. The generation MUST commit to four things upfront (these go in §1 of DESIGN.md):
|
|
149
|
+
|
|
150
|
+
1. **Aesthetic direction** — pick ONE: `editorial · brutalist · luxury · maximalist · retro-futuristic · organic · terminal-native · sci-fi · pastoral · industrial · ...`. Don't hedge ("modern minimal" is hedging — pick one extreme).
|
|
151
|
+
2. **Color strategy** — pick ONE: `Restrained · Committed · Full palette · Drenched`. See `rules/design-laws.md` §2.
|
|
152
|
+
3. **Scene sentence** — one concrete sentence: who uses this, where, ambient light, mood. NOT "observability dashboard" — "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room." Run the sentence, not the category.
|
|
153
|
+
4. **Differentiation** — one sentence: what someone remembers 24 hours later.
|
|
154
|
+
|
|
155
|
+
Then fill the rest of DESIGN.md:
|
|
156
|
+
- §2 Color: OKLCH only, no `#000`/`#fff`, neutrals tinted toward brand hue (chroma 0.005-0.015), accent within the chosen strategy
|
|
157
|
+
- §3 Typography: distinctive display + refined body pair. **NEVER** Inter, Roboto, Arial, Helvetica, system-ui, Space Grotesk
|
|
158
|
+
- §4 Spacing: 8px grid + fluid `clamp()` for page padding
|
|
159
|
+
- §5 Components: token-driven button/input/card/table specs
|
|
160
|
+
- §6 Depth: 3-level shadow elevation, OKLCH-tinted (not gray)
|
|
161
|
+
- §7 Motion: easing tokens (ease-out-quart/expo), no bounce, `prefers-reduced-motion` respected
|
|
162
|
+
- §8 Iconography: ONE family
|
|
163
|
+
- §9 Responsive: mobile-first
|
|
164
|
+
- §10 Anti-pattern checklist (the auto-runnable one)
|
|
128
165
|
|
|
129
|
-
|
|
166
|
+
Cross-check the result against `rules/design-laws.md` §8 absolute bans BEFORE writing — the design must not propose any banned pattern.
|
|
130
167
|
|
|
131
168
|
```bash
|
|
132
169
|
git add .planning/DESIGN.md .planning/config.json
|
|
133
|
-
git commit -m "docs:
|
|
170
|
+
git commit -m "docs: DESIGN.md — direction commit + OKLCH palette + tokens"
|
|
134
171
|
```
|
|
135
172
|
|
|
136
173
|
### Step 8. Run Research (ALWAYS, no permission ask)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qualia-polish
|
|
3
|
-
description: "
|
|
3
|
+
description: "Scope-adaptive design pass — works on a single component, a route, the whole app, or a ground-up redesign. Trigger on 'polish', 'design pass', 'fix the design', 'redesign', 'critique', 'audit design', 'looks ugly', 'make it look better'. Replaces both /qualia-polish and /qualia-design from earlier versions."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash
|
|
6
6
|
- Read
|
|
@@ -9,207 +9,251 @@ allowed-tools:
|
|
|
9
9
|
- Grep
|
|
10
10
|
- Glob
|
|
11
11
|
- Agent
|
|
12
|
+
argument-hint: "[file|route|--redesign|--critique|--quick] [--register=brand|product]"
|
|
12
13
|
---
|
|
13
14
|
|
|
14
|
-
# /qualia-polish — Design Pass
|
|
15
|
+
# /qualia-polish — Scope-Adaptive Design Pass
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
One command. Six scopes. Use it whenever you need design work — from a 30-second component touch-up to a 30-minute ground-up redesign.
|
|
17
18
|
|
|
18
|
-
##
|
|
19
|
+
## Scopes
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
- Identical card grids with rounded corners and soft shadows
|
|
22
|
-
- Blue-purple gradients on everything
|
|
23
|
-
- Inter/system-ui font with no hierarchy
|
|
24
|
-
- Generic hero with centered text and a stock gradient background
|
|
25
|
-
- Fixed-width containers leaving dead space on wide screens
|
|
26
|
-
- No motion, no personality, no opinion
|
|
27
|
-
- Perfect symmetry everywhere (real design has tension)
|
|
21
|
+
The first argument selects the scope. Stage selection follows from scope.
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
| Invocation | Scope | Runtime | Stages |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| `/qualia-polish src/components/Button.tsx` | **Component** | ~30s | 0, 2, 3, 7 |
|
|
26
|
+
| `/qualia-polish app/dashboard` | **Section** | ~3m | 0, 1 (light), 2, 3, 4, 7 |
|
|
27
|
+
| `/qualia-polish` | **App** | ~12m | all 7 (fan-out batches of 5) |
|
|
28
|
+
| `/qualia-polish --redesign` | **Redesign** | ~30m | all + Stage 1 mandatory + 2 vision iterations |
|
|
29
|
+
| `/qualia-polish --critique` | **Critique** | read-only | 0, 4, 5 (no edits) |
|
|
30
|
+
| `/qualia-polish --quick` | **Quick** | ~1m | 0, 2, 7 (gates only, no vision loop) |
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
Other flags: `--register=brand|product` to override register inference.
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
## Setup gates (non-optional, every scope)
|
|
35
|
+
|
|
36
|
+
Before any work — design or otherwise — pass these gates. Skipping them produces generic output that ignores the project.
|
|
37
|
+
|
|
38
|
+
| Gate | Required check | If fail |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Substrate | `rules/design-laws.md`, `design-brand.md`, `design-product.md`, `design-rubric.md` exist and have been read | Read them. |
|
|
41
|
+
| PRODUCT | `PRODUCT.md` exists at project root, has `register:` field, and is not placeholder (`[TODO]` markers, < 200 chars) | Run setup: ask 5 questions and generate it. Never synthesize from prompt alone. |
|
|
42
|
+
| DESIGN | `DESIGN.md` exists. If missing on App / Redesign scope, BLOCK and run setup. If missing on Component / Section / Critique / Quick scope, NUDGE and proceed. | Generate from PRODUCT.md + 3 questions. |
|
|
43
|
+
| Slop-detect | `bin/slop-detect.mjs` is callable | Install or pull from framework. |
|
|
44
|
+
| Mutation | All gates above pass | Do not edit project files yet. |
|
|
45
|
+
|
|
46
|
+
State this preflight explicitly before editing:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
POLISH_PREFLIGHT: substrate=pass product=pass design=pass|nudged slop_detect=pass mutation=open
|
|
35
50
|
```
|
|
36
51
|
|
|
37
|
-
|
|
52
|
+
## Process
|
|
38
53
|
|
|
39
54
|
```bash
|
|
40
|
-
|
|
55
|
+
node ~/.claude/bin/qualia-ui.js banner polish
|
|
41
56
|
```
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
- §1 Visual Theme — the feel and signature details
|
|
45
|
-
- §2 Color Palette — exact hex values, CSS variables, contrast ratios
|
|
46
|
-
- §3 Typography — hierarchy table with exact sizes/weights/spacing
|
|
47
|
-
- §4 Components — exact button/card/input/badge specs
|
|
48
|
-
- §5 Layout — spacing scale, grid strategy
|
|
49
|
-
- §6 Depth & Elevation — shadow levels with exact rgba values
|
|
50
|
-
- §7 Do's/Don'ts — brand-specific guardrails
|
|
51
|
-
- §9 Agent Prompt Guide — quick reference for common patterns
|
|
52
|
-
- §10 Accessibility — WCAG checklist
|
|
53
|
-
- §11 Hardening — stress-test criteria
|
|
54
|
-
- §12 Anti-Slop Detection — grep patterns for automated checks
|
|
58
|
+
### Stage 0 — Direction commit (mandatory; light on small scopes)
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
Read PRODUCT.md and DESIGN.md. Identify the **register** — Brand (marketing/landing/portfolio) or Product (app/admin/dashboard). Priority for register inference:
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
1. The path of the target file/route (e.g., `/marketing/*` → brand; `/app/*` → product)
|
|
63
|
+
2. `register:` field in PRODUCT.md
|
|
64
|
+
3. `--register` flag override
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
For App / Redesign scope, write the brief BEFORE any code (use `ultrathink`):
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
```
|
|
69
|
+
Aesthetic direction: {editorial · brutalist · luxury · maximalist · retro-futuristic · organic · terminal-native · ...}
|
|
70
|
+
Color strategy: {Restrained · Committed · Full palette · Drenched}
|
|
71
|
+
Scene sentence: {who uses this, where, ambient light, mood — concrete}
|
|
72
|
+
Differentiation: {what someone remembers 24 hours later}
|
|
73
|
+
```
|
|
63
74
|
|
|
64
|
-
|
|
65
|
-
# Generic fonts (the #1 AI tell)
|
|
66
|
-
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
|
|
75
|
+
For Component / Section / Quick scope, the brief is implicit (loaded from DESIGN.md). Skip the ultrathink step but cite the relevant DESIGN.md tokens you'll touch.
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
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
|
|
77
|
+
For Critique scope, no commit needed — you're scoring, not editing.
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
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
|
|
79
|
+
### Stage 1 — Static gates (no browser, deterministic)
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
```bash
|
|
82
|
+
# Anti-pattern scan (the slop-detect script)
|
|
83
|
+
node bin/slop-detect.mjs {target_paths}
|
|
76
84
|
|
|
77
|
-
#
|
|
78
|
-
|
|
85
|
+
# TypeScript still compiles?
|
|
86
|
+
npx tsc --noEmit 2>&1 | head -20
|
|
79
87
|
|
|
80
|
-
#
|
|
81
|
-
|
|
88
|
+
# Token enforcement (if Stylelint configured)
|
|
89
|
+
npx stylelint "src/**/*.css" 2>&1 | head -20 # optional, skip silently if not configured
|
|
82
90
|
```
|
|
83
91
|
|
|
84
|
-
|
|
92
|
+
ANY critical-severity slop hit = mandatory fix before proceeding. Don't stage anything until critical findings are zero.
|
|
85
93
|
|
|
86
|
-
### 2
|
|
94
|
+
### Stage 2 — Generation (forked subagents, batches of 5 files)
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
For App / Redesign / Section scope on multi-file work:
|
|
89
97
|
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- Headings: tighter line-height (1.1-1.3), negative letter-spacing (-0.02em) for display sizes
|
|
94
|
-
- Weight hierarchy: Regular (400) for body, Medium (500) for labels, Semibold (600) for headings, Bold (700) for display
|
|
95
|
-
- Prose content: `max-width: 65ch`. Everything else: fluid full-width.
|
|
96
|
-
- Use `clamp()` for fluid sizing: `clamp(2rem, 1rem + 3vw, 3.75rem)` for h1
|
|
98
|
+
- Count target files. If ≤ 5, process in main context.
|
|
99
|
+
- If > 5, fan out: spawn one Agent per batch of 5 files IN THE SAME RESPONSE TURN (parallel execution).
|
|
100
|
+
- If the conversation already contains design-taste discussion (font/color/motion preferences threaded across multiple turns), prefer **forked subagents** (`--fork-session`) so they inherit the taste context. Otherwise, blank-context fan-out is fine for mechanical fixes.
|
|
97
101
|
|
|
98
|
-
|
|
102
|
+
Each agent receives:
|
|
103
|
+
- `rules/design-laws.md` + the matching register file
|
|
104
|
+
- `PRODUCT.md` + `DESIGN.md` (inlined)
|
|
105
|
+
- Its 5 files (paths + contents)
|
|
106
|
+
- Instruction: apply the Design Quality Rubric per file. Fix every dimension scoring < 3. Make literal edits. Do NOT change logic — only styling.
|
|
99
107
|
|
|
100
|
-
|
|
108
|
+
For Component scope: do the work in main context. Read, fix, verify.
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
- One dominant brand color. One sharp accent for CTAs that pops against the page.
|
|
104
|
-
- Surfaces: layer them. Background → card → elevated card. Use subtle shade differences, not just white-on-white.
|
|
105
|
-
- Dark mode (if present): rethink surfaces, don't just invert. Slightly reduce contrast. Use darker brand colors, not just white→black swap.
|
|
106
|
-
- Semantic colors with non-color indicators: success (green + checkmark), error (red + icon), warning (amber + triangle)
|
|
107
|
-
- Verify WCAG AA: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+)
|
|
110
|
+
**Apply fixes scoped by what's missing:**
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
| If the file scores low on… | Apply fix from… |
|
|
113
|
+
|---|---|
|
|
114
|
+
| Typography | DESIGN.md §3 — font tokens, scale, weight hierarchy, tabular numerals |
|
|
115
|
+
| Color cohesion | DESIGN.md §2 — OKLCH tokens, replace hex, verify contrast |
|
|
116
|
+
| Spatial rhythm | DESIGN.md §4 — fluid spacing scale, vary by content |
|
|
117
|
+
| Layout originality | register file (brand or product) — kill three-column grids, vary layout |
|
|
118
|
+
| Shadow hierarchy | DESIGN.md §6 — elevation tokens, brand-tinted shadows |
|
|
119
|
+
| Motion intent | DESIGN.md §7 — easing, stagger, signature motion |
|
|
120
|
+
| Microcopy | rename "Get Started" / "Learn More" to action-named CTAs |
|
|
121
|
+
| Container depth | flatten card-on-card; remove side-stripe borders |
|
|
110
122
|
|
|
111
|
-
|
|
123
|
+
### Stage 3 — Runtime gates (App / Section / Redesign only — needs dev server)
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
- 8px spacing grid: 4, 8, 12, 16, 24, 32, 48, 64, 96
|
|
115
|
-
- Tight spacing within groups (related items). Generous spacing between sections.
|
|
116
|
-
- Break symmetry where it serves the design — offset grids, overlapping elements, diagonal flow
|
|
117
|
-
- Varied layouts: not every section should be a centered-text-with-cards-below. Use side-by-side, staggered, asymmetric, full-bleed.
|
|
118
|
-
- Section spacing: `clamp(2rem, 8vw, 6rem)` vertical padding
|
|
125
|
+
If a dev server is up at `http://localhost:3000` (or detected via `lsof` on common ports):
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
```bash
|
|
128
|
+
# Lighthouse-CI — numeric a11y/perf/best-practices
|
|
129
|
+
npx lhci autorun \
|
|
130
|
+
--collect.url=http://localhost:3000{route} \
|
|
131
|
+
--collect.numberOfRuns=1 \
|
|
132
|
+
--assert.assertions='{
|
|
133
|
+
"categories:accessibility": ["error", {"minScore": 0.9}],
|
|
134
|
+
"categories:performance": ["warn", {"minScore": 0.7}],
|
|
135
|
+
"categories:best-practices": ["warn", {"minScore": 0.8}]
|
|
136
|
+
}' 2>&1 | tail -30
|
|
137
|
+
|
|
138
|
+
# axe-core direct (catches what Lighthouse misses)
|
|
139
|
+
npx @axe-core/cli http://localhost:3000{route} --exit 2>&1 | tail -30
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If Lighthouse/axe not installed, skip silently and note in the report. Don't fail the polish over missing tooling.
|
|
121
143
|
|
|
122
|
-
**
|
|
144
|
+
If a11y < 90 OR axe critical/serious violations: **fix programmatically** (these are deterministic — no vision needed). Re-run to confirm.
|
|
123
145
|
|
|
124
|
-
|
|
125
|
-
- **Focus:** visible ring (2px+ offset, contrasting color). Never `outline: none` without replacement.
|
|
126
|
-
- **Active/pressed:** subtle scale down (`transform: scale(0.98)`) or color shift.
|
|
127
|
-
- **Disabled:** opacity 0.5 + `cursor: not-allowed` + `aria-disabled="true"`
|
|
128
|
-
- **Loading:** skeleton shimmer or spinner on every async operation. Never a blank void.
|
|
129
|
-
- **Empty:** helpful message + CTA on empty lists/tables. Not just "No results."
|
|
130
|
-
- **Error:** user-friendly message + recovery action. Not raw error text. Use `aria-live="assertive"`.
|
|
146
|
+
### Stage 4 — Vision loop (Redesign scope only — max 2 iterations)
|
|
131
147
|
|
|
132
|
-
|
|
148
|
+
Use Anthropic's `webapp-testing` skill (Playwright). Capture screenshots at 3 viewports: 375 / 768 / 1280. Single browser (Chromium) is fine in 2026 — cross-browser CSS rendering differences are vanishingly rare.
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
```
|
|
151
|
+
viewports: [
|
|
152
|
+
{ width: 375, height: 812, name: 'mobile' },
|
|
153
|
+
{ width: 768, height: 1024, name: 'tablet' },
|
|
154
|
+
{ width: 1280, height: 800, name: 'desktop' }
|
|
155
|
+
]
|
|
156
|
+
```
|
|
135
157
|
|
|
136
|
-
|
|
137
|
-
- Hover transitions: 150-200ms ease-out
|
|
138
|
-
- Section transitions: 300-500ms with `cubic-bezier(0.4, 0, 0.2, 1)`
|
|
139
|
-
- One signature motion that gives the site personality (parallax, scroll-triggered reveal, magnetic buttons, morphing shapes)
|
|
140
|
-
- **Always** `prefers-reduced-motion: reduce` — disable non-essential animation
|
|
141
|
-
- CSS-only for static sites, `motion/react` (formerly Framer Motion) for React
|
|
158
|
+
For each iteration:
|
|
142
159
|
|
|
143
|
-
|
|
160
|
+
1. Capture all 3 viewports
|
|
161
|
+
2. Pass to a vision-model agent with `rules/design-rubric.md` as the prompt anchor + DESIGN.md as the spec
|
|
162
|
+
3. The agent scores 8 dimensions, anchored 1-5, with evidence per dimension
|
|
163
|
+
4. Apply fixes ONLY to dimensions scored 1 or 2 (don't nitpick 3s; prevents oscillation)
|
|
164
|
+
5. STOP if: all dimensions ≥ 3 (success), OR any dimension regressed from previous iteration (regression-stop), OR 2 iterations reached (hard cap)
|
|
144
165
|
|
|
145
|
-
|
|
146
|
-
- One `h1` per page, sequential heading order (no h1 → h3 skip)
|
|
147
|
-
- All images: descriptive `alt` (or `alt=""` + `aria-hidden` if decorative)
|
|
148
|
-
- All form inputs: visible `<label>` with `htmlFor` — not placeholder-only
|
|
149
|
-
- All interactive elements: keyboard accessible (Tab, Enter, Escape, Arrow keys)
|
|
150
|
-
- Touch targets: 44x44px minimum
|
|
151
|
-
- Skip link: `<a href="#main" class="sr-only focus:not-sr-only">` as first focusable element
|
|
152
|
-
- `<html lang="en">` set
|
|
153
|
-
- Color never the sole information carrier — icons, text, patterns as supplements
|
|
154
|
-
- `aria-live="polite"` for toast notifications and dynamic content updates
|
|
166
|
+
**The anchored rubric is mandatory.** Without it, vision models say "looks great!" to everything. Quote from the rubric prompt: "Score 3 = acceptable. Only 1-2 = must fix. 4-5 = exceeds. Default to 3 unless you can cite specific evidence."
|
|
155
167
|
|
|
156
|
-
###
|
|
168
|
+
### Stage 5 — Drift audit (App / Redesign / Critique scope)
|
|
157
169
|
|
|
158
|
-
|
|
159
|
-
- Test at: 320px (small phone), 375px (iPhone), 768px (iPad), 1024px (laptop), 1440px (desktop)
|
|
160
|
-
- No horizontal scroll at any viewport
|
|
161
|
-
- Navigation: hamburger/drawer on mobile, full horizontal on desktop
|
|
162
|
-
- Stack on mobile, expand on desktop
|
|
163
|
-
- Fluid typography with `clamp()`
|
|
164
|
-
- Images: `max-width: 100%`, responsive `srcset`, `next/image` with width/height
|
|
165
|
-
- Tables: card layout or horizontal scroll on mobile
|
|
170
|
+
Compare the implementation against DESIGN.md as source of truth. Flag deltas.
|
|
166
171
|
|
|
167
|
-
|
|
172
|
+
```bash
|
|
173
|
+
# Find tokens used in code that don't exist in DESIGN.md
|
|
174
|
+
grep -rE "var\(--[a-z-]+\)" src/ app/ components/ 2>/dev/null | \
|
|
175
|
+
awk -F'var\\(--' '{print $2}' | awk -F'\\)' '{print $1}' | sort -u > /tmp/used-tokens
|
|
176
|
+
grep -E "^\s*--[a-z-]+:" templates/DESIGN.md | sed -E 's/.*--([a-z-]+):.*/\1/' | sort -u > /tmp/declared-tokens
|
|
177
|
+
comm -23 /tmp/used-tokens /tmp/declared-tokens > /tmp/orphan-tokens
|
|
178
|
+
[ -s /tmp/orphan-tokens ] && echo "── orphan tokens (used in code, missing from DESIGN.md) ──" && cat /tmp/orphan-tokens
|
|
179
|
+
|
|
180
|
+
# Find raw hex still appearing
|
|
181
|
+
grep -rnE "#[0-9a-fA-F]{6}\b" src/ app/ components/ --include="*.tsx" --include="*.css" 2>/dev/null | \
|
|
182
|
+
grep -v "shadow\|outline\|currentColor" | head -20
|
|
183
|
+
```
|
|
168
184
|
|
|
169
|
-
|
|
170
|
-
- Long text: does a 200-character username break the layout?
|
|
171
|
-
- Empty everywhere: all lists empty, all data missing — does it still make sense?
|
|
172
|
-
- Error everywhere: every fetch fails — are error states visible and helpful?
|
|
173
|
-
- 320px viewport: nothing overflows, nothing clips, nothing overlaps
|
|
174
|
-
- Keyboard only: Tab through the entire app — can you reach everything? Is focus visible?
|
|
175
|
-
- Slow network: are loading states visible? Does content stream in or flash?
|
|
185
|
+
Drift findings get reported, not auto-fixed (drift may be intentional). For Critique scope, this IS the deliverable.
|
|
176
186
|
|
|
177
|
-
###
|
|
187
|
+
### Stage 6 — Verify (every scope)
|
|
178
188
|
|
|
179
189
|
```bash
|
|
180
|
-
|
|
190
|
+
# Re-run Stage 1 — all critical findings must be zero
|
|
191
|
+
node bin/slop-detect.mjs {target_paths}
|
|
192
|
+
[ $? -eq 0 ] || { echo "polish failed — slop-detect still finds critical issues"; exit 1; }
|
|
193
|
+
|
|
194
|
+
# TypeScript clean
|
|
195
|
+
npx tsc --noEmit 2>&1 | tail -10
|
|
181
196
|
```
|
|
182
197
|
|
|
183
|
-
|
|
198
|
+
### Stage 7 — Commit & state
|
|
199
|
+
|
|
200
|
+
For Critique scope: write the report to `.planning/polish-critique-{timestamp}.md` and STOP. Do not edit, do not commit.
|
|
201
|
+
|
|
202
|
+
For all other scopes:
|
|
184
203
|
|
|
185
204
|
```bash
|
|
186
|
-
git add {
|
|
187
|
-
git
|
|
205
|
+
git add {modified files}
|
|
206
|
+
git -c user.name="Qualia Solutions" -c user.email="info@qualiasolutions.net" commit -m "$(cat <<'EOF'
|
|
207
|
+
polish({scope}): {brief summary}
|
|
208
|
+
|
|
209
|
+
- {key change 1}
|
|
210
|
+
- {key change 2}
|
|
211
|
+
- rubric scores: typography {N}, color {N}, ..., aggregate {N}/40
|
|
212
|
+
|
|
213
|
+
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
214
|
+
EOF
|
|
215
|
+
)"
|
|
188
216
|
```
|
|
189
217
|
|
|
218
|
+
If this is the FINAL polish before deploy (Handoff milestone, last phase):
|
|
219
|
+
|
|
190
220
|
```bash
|
|
191
221
|
node ~/.claude/bin/state.js transition --to polished
|
|
192
222
|
```
|
|
193
223
|
|
|
224
|
+
Otherwise, no state transition (polish is now a normal verb, not a phase boundary).
|
|
225
|
+
|
|
226
|
+
### Output
|
|
227
|
+
|
|
194
228
|
```bash
|
|
195
229
|
node ~/.claude/bin/qualia-ui.js divider
|
|
196
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
197
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
198
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
199
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
200
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
201
|
-
node ~/.claude/bin/qualia-ui.js ok "
|
|
202
|
-
node ~/.claude/bin/qualia-ui.js
|
|
203
|
-
node ~/.claude/bin/qualia-ui.js ok "Responsive: {brief}"
|
|
204
|
-
node ~/.claude/bin/qualia-ui.js ok "Hardened: {brief}"
|
|
205
|
-
node ~/.claude/bin/qualia-ui.js end "POLISHED" "/qualia-ship"
|
|
230
|
+
node ~/.claude/bin/qualia-ui.js ok "Scope: {component|section|app|redesign|critique|quick}"
|
|
231
|
+
node ~/.claude/bin/qualia-ui.js ok "Files: {N}"
|
|
232
|
+
node ~/.claude/bin/qualia-ui.js ok "Slop-detect: {N critical, M high, K medium}"
|
|
233
|
+
node ~/.claude/bin/qualia-ui.js ok "Rubric aggregate: {N}/40 (avg {N})"
|
|
234
|
+
node ~/.claude/bin/qualia-ui.js ok "Vision iterations: {0|1|2}"
|
|
235
|
+
node ~/.claude/bin/qualia-ui.js ok "Drift findings: {N}"
|
|
236
|
+
node ~/.claude/bin/qualia-ui.js end "POLISHED" "{next command — depends on context}"
|
|
206
237
|
```
|
|
207
238
|
|
|
208
239
|
## Rules
|
|
209
240
|
|
|
210
241
|
1. **Read before write.** Understand every file before changing it.
|
|
211
|
-
2. **DESIGN.md is law.** If
|
|
242
|
+
2. **DESIGN.md is law.** If a project decision exists, follow it. Don't override.
|
|
212
243
|
3. **Don't break functionality.** Only change styling, never logic.
|
|
213
|
-
4. **
|
|
244
|
+
4. **Slop is a bug.** Critical-severity findings block commit. No overriding the script.
|
|
214
245
|
5. **TypeScript must pass** after every change.
|
|
215
|
-
6. **One commit
|
|
246
|
+
6. **One commit per polish run** — not per category, not per file.
|
|
247
|
+
7. **Forked subagents inherit taste.** When the conversation has design discussion, fork. Otherwise blank-context.
|
|
248
|
+
8. **The rubric is anchored.** Score = 3 means ships. Default there. Justify deviations.
|
|
249
|
+
|
|
250
|
+
## Failure modes (handle gracefully)
|
|
251
|
+
|
|
252
|
+
| Symptom | Likely cause | Action |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| `bin/slop-detect.mjs not found` | Framework not installed in project | Run `npx qualia install` or pull script from framework repo |
|
|
255
|
+
| `PRODUCT.md missing` | Pre-v4.5.0 project | Run setup (ask 5 questions, generate). For Component scope, can proceed with nudge. |
|
|
256
|
+
| `Lighthouse not installed` | Optional tool | Skip Stage 3 numeric gates, note in report. Don't fail. |
|
|
257
|
+
| `webapp-testing skill not present` | Optional Anthropic skill | Skip Stage 4 vision loop on Redesign scope. Note in report. Recommend installing. |
|
|
258
|
+
| Vision loop oscillates between iterations | Rubric not anchored properly | Verify rubric prompt instructs "default to 3, only 1-2 = fix". Hard cap at 2 iterations. |
|
|
259
|
+
| User says "you missed X" after polish completes | Scope was too narrow | Re-run with wider scope (`/qualia-polish` whole-app). Don't argue scope. |
|