qualia-framework 4.4.0 → 5.1.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.
Files changed (70) hide show
  1. package/AGENTS.md +24 -0
  2. package/CLAUDE.md +12 -63
  3. package/README.md +24 -18
  4. package/agents/builder.md +13 -33
  5. package/agents/plan-checker.md +18 -0
  6. package/agents/planner.md +17 -0
  7. package/agents/verifier.md +70 -0
  8. package/agents/visual-evaluator.md +132 -0
  9. package/bin/cli.js +64 -23
  10. package/bin/install.js +375 -29
  11. package/bin/qualia-ui.js +208 -1
  12. package/bin/slop-detect.mjs +362 -0
  13. package/bin/state.js +218 -2
  14. package/docs/erp-contract.md +5 -0
  15. package/docs/install-redesign-builder-prompt.md +290 -0
  16. package/docs/install-redesign-pilot.md +234 -0
  17. package/docs/playwright-loop-builder-prompt.md +185 -0
  18. package/docs/playwright-loop-design-notes.md +108 -0
  19. package/docs/playwright-loop-pilot-results.md +170 -0
  20. package/docs/playwright-loop-review-2026-05-03.md +65 -0
  21. package/docs/playwright-loop-tester-prompt.md +213 -0
  22. package/docs/reviews/matt-pocock-skills-analysis.md +300 -0
  23. package/guide.md +9 -5
  24. package/hooks/env-empty-guard.js +74 -0
  25. package/hooks/pre-compact.js +19 -9
  26. package/hooks/pre-deploy-gate.js +8 -2
  27. package/hooks/pre-push.js +26 -12
  28. package/hooks/supabase-destructive-guard.js +62 -0
  29. package/hooks/vercel-account-guard.js +91 -0
  30. package/package.json +2 -1
  31. package/rules/design-brand.md +114 -0
  32. package/rules/design-laws.md +148 -0
  33. package/rules/design-product.md +114 -0
  34. package/rules/design-rubric.md +157 -0
  35. package/rules/grounding.md +4 -0
  36. package/skills/qualia-build/SKILL.md +40 -46
  37. package/skills/qualia-discuss/SKILL.md +51 -68
  38. package/skills/qualia-handoff/SKILL.md +1 -0
  39. package/skills/qualia-issues/SKILL.md +151 -0
  40. package/skills/qualia-map/SKILL.md +78 -35
  41. package/skills/qualia-new/REFERENCE.md +139 -0
  42. package/skills/qualia-new/SKILL.md +85 -124
  43. package/skills/qualia-optimize/REFERENCE.md +202 -0
  44. package/skills/qualia-optimize/SKILL.md +72 -237
  45. package/skills/qualia-plan/SKILL.md +58 -65
  46. package/skills/qualia-polish/SKILL.md +180 -136
  47. package/skills/qualia-polish-loop/REFERENCE.md +265 -0
  48. package/skills/qualia-polish-loop/SKILL.md +201 -0
  49. package/skills/qualia-polish-loop/fixtures/broken.html +117 -0
  50. package/skills/qualia-polish-loop/fixtures/clean.html +196 -0
  51. package/skills/qualia-polish-loop/scripts/loop.mjs +302 -0
  52. package/skills/qualia-polish-loop/scripts/playwright-capture.mjs +197 -0
  53. package/skills/qualia-polish-loop/scripts/score.mjs +176 -0
  54. package/skills/qualia-report/SKILL.md +141 -180
  55. package/skills/qualia-research/SKILL.md +28 -33
  56. package/skills/qualia-road/SKILL.md +103 -0
  57. package/skills/qualia-ship/SKILL.md +1 -0
  58. package/skills/qualia-task/SKILL.md +1 -1
  59. package/skills/qualia-test/SKILL.md +50 -2
  60. package/skills/qualia-triage/SKILL.md +152 -0
  61. package/skills/qualia-verify/SKILL.md +63 -104
  62. package/skills/qualia-zoom/SKILL.md +51 -0
  63. package/skills/zoho-workflow/SKILL.md +64 -0
  64. package/templates/CONTEXT.md +36 -0
  65. package/templates/DESIGN.md +229 -435
  66. package/templates/PRODUCT.md +95 -0
  67. package/templates/decisions/ADR-template.md +30 -0
  68. package/tests/bin.test.sh +451 -7
  69. package/tests/state.test.sh +58 -0
  70. package/skills/qualia-design/SKILL.md +0 -169
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ // ~/.claude/hooks/vercel-account-guard.js — block deploys from wrong Vercel account.
3
+ //
4
+ // PreToolUse hook on `Bash`. Reads the proposed command from the Claude Code
5
+ // hook payload (stdin JSON: tool_input.command) and exits 2 to BLOCK, 0 to
6
+ // allow. Triggers only when the command matches `vercel --prod` or `vercel deploy`.
7
+ //
8
+ // Allowed teams are read from ~/.claude/.vercel-allowed-teams (one slug per
9
+ // line, mode 0600). Missing config file = fail-open with stderr warning.
10
+ //
11
+ // Cross-platform (Windows/macOS/Linux). No external dependencies.
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ const os = require("os");
16
+ const { spawnSync } = require("child_process");
17
+
18
+ const _traceStart = Date.now();
19
+
20
+ function _trace(result, extra) {
21
+ try {
22
+ const traceDir = path.join(os.homedir(), ".claude", ".qualia-traces");
23
+ if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
24
+ const entry = {
25
+ hook: "vercel-account-guard",
26
+ result,
27
+ timestamp: new Date().toISOString(),
28
+ duration_ms: Date.now() - _traceStart,
29
+ ...extra,
30
+ };
31
+ const file = path.join(traceDir, `${new Date().toISOString().split("T")[0]}.jsonl`);
32
+ fs.appendFileSync(file, JSON.stringify(entry) + "\n");
33
+ } catch {}
34
+ }
35
+
36
+ // Read hook payload from stdin.
37
+ let command = "";
38
+ try {
39
+ if (!process.stdin.isTTY) {
40
+ const raw = fs.readFileSync(0, "utf8");
41
+ if (raw) command = (JSON.parse(raw).tool_input || {}).command || "";
42
+ }
43
+ } catch {}
44
+
45
+ if (!command) {
46
+ _trace("allow", { reason: "no-command" });
47
+ process.exit(0);
48
+ }
49
+
50
+ // Only act on vercel deploy commands.
51
+ if (!/vercel\s+(--prod|deploy)/.test(command)) {
52
+ _trace("allow", { reason: "not-vercel-deploy" });
53
+ process.exit(0);
54
+ }
55
+
56
+ // Read allowed teams (one slug per line).
57
+ const teamsFile = path.join(os.homedir(), ".claude", ".vercel-allowed-teams");
58
+ let allowed;
59
+ try {
60
+ allowed = fs.readFileSync(teamsFile, "utf8").split(/\r?\n/).map(l => l.trim()).filter(Boolean);
61
+ } catch {
62
+ allowed = [];
63
+ }
64
+ if (allowed.length === 0) {
65
+ console.error("No .vercel-allowed-teams configured -- skipping account check");
66
+ _trace("skipped", { reason: "no-config" });
67
+ process.exit(0);
68
+ }
69
+
70
+ // Run `vercel whoami` to get the active account (fail-open on error).
71
+ const r = spawnSync("vercel", ["whoami"], {
72
+ encoding: "utf8", timeout: 5000, shell: process.platform === "win32",
73
+ });
74
+ const actual = ((r.status === 0 && !r.error) ? (r.stdout || "") : "").trim();
75
+ if (!actual) {
76
+ console.error("vercel whoami failed or empty -- skipping account check");
77
+ _trace("skipped", { reason: "whoami-unavailable" });
78
+ process.exit(0);
79
+ }
80
+
81
+ if (allowed.includes(actual)) {
82
+ _trace("allow", { actual, allowed_count: allowed.length });
83
+ process.exit(0);
84
+ }
85
+
86
+ // Block: wrong account.
87
+ const msg = `BLOCKED: Wrong Vercel account/team. Active: '${actual}'. Allowed: ${allowed.join(", ")}. Run \`vercel switch ${allowed[0]}\` first, or add this team to ~/.claude/.vercel-allowed-teams.`;
88
+ console.error(msg);
89
+ console.log(msg);
90
+ _trace("block", { actual, allowed_count: allowed.length, reason: "wrong-account" });
91
+ process.exit(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qualia-framework",
3
- "version": "4.4.0",
3
+ "version": "5.1.0",
4
4
  "description": "Claude Code workflow framework by Qualia Solutions. Plan, build, verify, ship.",
5
5
  "bin": {
6
6
  "qualia-framework": "./bin/cli.js"
@@ -42,6 +42,7 @@
42
42
  "tests/",
43
43
  "docs/",
44
44
  "CLAUDE.md",
45
+ "AGENTS.md",
45
46
  "guide.md"
46
47
  ],
47
48
  "engines": {
@@ -0,0 +1,114 @@
1
+ ---
2
+ globs: ["*.tsx", "*.jsx", "*.css", "*.scss", "*.html", "*.vue", "*.svelte"]
3
+ ---
4
+
5
+ # Design — Brand register
6
+
7
+ **When this register applies:** marketing pages, landing pages, campaign sites, portfolios, brand microsites, anything where the design IS the product.
8
+
9
+ **The bar:** distinctiveness. Memorable beats safe. If a visitor can't remember what your site looked like an hour later, you failed.
10
+
11
+ This register inherits all of `design-laws.md`. The rules below add what changes when distinctiveness, not familiarity, is the goal.
12
+
13
+ ## The brand brief (what the agent commits to first)
14
+
15
+ Before any code, the agent writes a 4-line brief and waits for user confirmation:
16
+
17
+ ```
18
+ Aesthetic direction: [editorial · brutalist · luxury · maximalist · retro-futuristic · organic · terminal-native · sci-fi · pastoral · industrial · ...]
19
+ Color strategy: [Restrained · Committed · Full palette · Drenched]
20
+ Scene sentence: [single concrete sentence — who, where, ambient light, mood]
21
+ Differentiation: [what someone will remember 24 hours later]
22
+ ```
23
+
24
+ This is mandatory. Skipping it produces generic output that ignores the brand.
25
+
26
+ ## Reflex-reject aesthetic lanes
27
+
28
+ The currently-saturated AI-design families. Reject by default unless the user explicitly asks for one and you confirmed they understand it's a saturated lane.
29
+
30
+ | Lane | Tells | Reject because |
31
+ |---|---|---|
32
+ | **Generic SaaS-cream** | Off-white bg, soft shadows, rounded cards, slate text, one-color accent | Notion clone aesthetic. Every AI tool builds this first |
33
+ | **Vercel-terminal-native** | Dark + monospace + green/blue accents + grain | The 2024-2025 v0 aesthetic. Saturated |
34
+ | **Crypto-neon** | Pure black + electric accent + glow + grid | Web3 cliché |
35
+ | **Healthcare-clinical** | White + teal + rounded sans + soft icons | Every health app |
36
+ | **Fintech-navy-gold** | Navy + gold accent + serif headings | Every bank, every wealth tool |
37
+ | **Sleek-corporate** | Inter + blue + gradient mesh + isometric illustrations | Every B2B SaaS landing 2020-2024 |
38
+
39
+ If the project lands in one of these by default, the slop test failed at second-order. Rework.
40
+
41
+ ## Brand register — additional laws
42
+
43
+ ### Typography
44
+
45
+ - Pick a **distinctive display face**. Editorial serifs (Fraunces, Reckless, Ogg, Editorial New, Mazius). Geometric grotesques (Migra, Söhne, Gambarino). Variable display fonts (Authentic Sans, Departure Mono).
46
+ - Pair the display with a **refined body**. JetBrains Mono, Geist, Inter Display (NOT Inter), Söhne, Untitled Sans, Mona Sans, Switzer.
47
+ - **Banned display fonts:** Inter, Roboto, Arial, system-ui, Space Grotesk, Montserrat, Poppins, Lato, Open Sans. These are the AI defaults — and the worst signal of "designer didn't choose this."
48
+ - **Variable fonts encouraged.** A single variable font with axis-driven weight/optical-size is more interesting than three static cuts.
49
+
50
+ ### Color
51
+
52
+ - Brand register defaults to **Committed** color strategy. One saturated color carries identity.
53
+ - **Drenched** is a strong choice for hero sections. Don't be afraid.
54
+ - Accent should be **sharp** — not a desaturated pastel-of-the-brand. The accent is the loudest element on the page.
55
+
56
+ ### Layout
57
+
58
+ - **Asymmetry > symmetry.** Real design has tension. Centered-everything is the AI default.
59
+ - **Diagonal flow, overlap, grid-breaking elements** when they serve the design.
60
+ - **Scale contrast.** Hero text at clamp(4rem, 9vw, 8rem) next to body at 1rem creates drama. Hero at 2.5rem next to body at 1rem is timid.
61
+ - **Negative space is content.** Generous whitespace > dense layouts for marketing.
62
+
63
+ ### Motion
64
+
65
+ - One **signature motion** that gives the site personality:
66
+ - Parallax scroll-triggered reveal
67
+ - Magnetic buttons
68
+ - Cursor-following element
69
+ - Letter-by-letter text reveal on hero
70
+ - Scroll-driven scrubbed scene
71
+ - Morphing shapes between sections
72
+ - Subtle elsewhere. Restraint everywhere except the signature.
73
+ - Use the Web Animations API or Framer Motion for orchestrated sequences. CSS keyframes for one-offs.
74
+
75
+ ### Backgrounds and visual details
76
+
77
+ This is where Brand earns its register. Allowed and encouraged:
78
+
79
+ - Gradient meshes (CSS or SVG)
80
+ - Noise textures (subtle, 2-5% opacity)
81
+ - Geometric patterns (SVG, not images)
82
+ - Layered transparencies
83
+ - Dramatic shadows (with brand-tinted color, not gray)
84
+ - Decorative borders (sparingly)
85
+ - Custom cursors (page-specific, not site-wide)
86
+ - Grain overlays on images
87
+ - Scroll-progress indicators (interesting ones, not generic top bars)
88
+
89
+ Don't use all of these on one page. Pick 1-2 that serve the brief.
90
+
91
+ ## Brand-specific anti-patterns
92
+
93
+ In addition to `design-laws.md` absolute bans:
94
+
95
+ - **Hero pattern: text-center + gradient bg + 2 CTAs + screenshot below.** The single most overused brand pattern of 2020-2025.
96
+ - **Three-column feature grid in section 2.** The default AI brand layout.
97
+ - **"Trusted by" logo strip in faded gray.** Lazy social proof. If the logos matter, design with them. If they don't, omit.
98
+ - **Parallax scroll on every section.** Heavy-handed. Use it for the signature, nowhere else.
99
+ - **Animated dots / pulsing orbs / blinking status indicators.** Decorative noise.
100
+ - **Generic "Get Started" / "Learn More" CTA pair.** Always specify the action.
101
+ - **Stock photography of diverse smiling people in offices.** Use illustration, abstract imagery, product screenshots, or no imagery at all.
102
+
103
+ ## Brand register success criteria
104
+
105
+ If you can answer YES to all of these, the brand register passed:
106
+
107
+ - [ ] A designer would call this **distinctive** — not "polished" but **specific**
108
+ - [ ] The aesthetic direction is identifiable in 3 seconds
109
+ - [ ] The color strategy is one of the four (and reads that way)
110
+ - [ ] The scene sentence and the page agree
111
+ - [ ] One signature motion, executed well
112
+ - [ ] No reflex-reject lane (first or second order)
113
+ - [ ] All anti-references avoided
114
+ - [ ] Implementation matches vision (effort proportional to ambition)
@@ -0,0 +1,148 @@
1
+ ---
2
+ globs: ["*.tsx", "*.jsx", "*.css", "*.scss", "*.html", "*.vue", "*.svelte"]
3
+ ---
4
+
5
+ # Design Laws
6
+
7
+ The non-negotiable rules every Qualia frontend honors. Both registers (Brand and Product) inherit from this file. Skip nothing.
8
+
9
+ These laws exist because AI-generated UI has identifiable defaults — Inter font, purple gradients, identical card grids, gray-on-gray, modal-as-first-thought — and shipping the defaults is shipping AI slop. Each rule below has a specific failure mode it prevents.
10
+
11
+ ## 1. Color: OKLCH only
12
+
13
+ Use the OKLCH color space for every color in the codebase. RGB / hex / HSL are translated values, not source values.
14
+
15
+ ```css
16
+ /* yes */
17
+ --bg: oklch(0.16 0.012 220);
18
+ --accent: oklch(0.78 0.14 196);
19
+
20
+ /* no */
21
+ --bg: #1a1d22;
22
+ --accent: #00ced1;
23
+ ```
24
+
25
+ **Why:** OKLCH is perceptually uniform. Equal lightness numbers look equally light to the eye, regardless of hue. Hex doesn't give you that — `#777777` and `#7777ff` are nominally equal lightness but the blue reads darker.
26
+
27
+ **Reduce chroma at the extremes.** As lightness approaches 0 or 100, high chroma reads garish. Cap chroma at 0.04 below L=0.20 and above L=0.92.
28
+
29
+ **Never use `#000` or `#fff`.** Tint every neutral toward the brand hue with chroma 0.005–0.01. Pure black/white reads as untuned and generic — the dead giveaway of "designer didn't pick this color, the framework did."
30
+
31
+ ```css
32
+ /* tinted neutrals */
33
+ --text: oklch(0.94 0.006 220); /* 220 is the brand hue */
34
+ --bg: oklch(0.16 0.012 220);
35
+ --muted: oklch(0.62 0.010 220);
36
+ ```
37
+
38
+ ## 2. Color strategy: pick one, commit to it
39
+
40
+ Before picking colors, pick a strategy. Four steps on a commitment axis:
41
+
42
+ | Strategy | Rule | When |
43
+ |---|---|---|
44
+ | **Restrained** | Tinted neutrals + one accent at ≤10% surface coverage | Product default; brand minimalism |
45
+ | **Committed** | One saturated color carries 30–60% of the surface | Brand default for identity-driven pages |
46
+ | **Full palette** | 3–4 named roles, each used deliberately | Brand campaigns; product data viz |
47
+ | **Drenched** | The surface IS the color | Brand heroes; campaign pages |
48
+
49
+ The "≤10% accent" rule is **Restrained only**. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
50
+
51
+ ## 3. Theme: write a scene sentence
52
+
53
+ Dark vs light is never a default. Not dark "because tools look cool dark." Not light "to be safe." Before choosing, write **one sentence of physical scene**: who uses this, where, under what ambient light, in what mood.
54
+
55
+ | Vague (no answer) | Concrete (forces an answer) |
56
+ |---|---|
57
+ | "Observability dashboard" | "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" |
58
+ | "Customer support tool" | "Agent at a coffee-lit desk juggling 4 chats while a coworker asks a question" |
59
+ | "Marketing site" | "Founder showing the page to an investor on an iPad in a sunlit lobby" |
60
+
61
+ Run the sentence, not the category. If the sentence doesn't force an answer, add detail until it does.
62
+
63
+ ## 4. Typography
64
+
65
+ - Body line length capped at 65–75ch
66
+ - Hierarchy through scale + weight contrast (≥1.25 ratio between adjacent steps)
67
+ - Avoid flat scales — if h1 is 32px and h2 is 28px, the hierarchy is invisible
68
+ - Letter-spacing as a semantic signal:
69
+ - Display headlines: tight (-0.02em to -0.04em)
70
+ - Body: neutral (0)
71
+ - Labels and badges: open (+0.04em to +0.08em)
72
+ - Category tags: wide (+0.08em to +0.14em)
73
+
74
+ ## 5. Layout
75
+
76
+ - **Vary spacing for rhythm.** Same padding everywhere is monotony. Tight within groups, generous between sections.
77
+ - **Cards are the lazy answer.** Use them only when they're truly the best affordance. Nested cards are always wrong.
78
+ - **Container depth max 2.** Card → content. Not card → panel → pill → content.
79
+ - **Don't wrap everything in a container.** Most things don't need one.
80
+ - **Full-width with fluid padding.** No hardcoded `max-width: 1200px` or `max-w-7xl`. Use `clamp(1rem, 5vw, 4rem)` for horizontal padding.
81
+
82
+ ## 6. Motion
83
+
84
+ - Don't animate CSS layout properties (`width`, `height`, `top`, `left`, `margin`, `padding`). Animate `transform` and `opacity`.
85
+ - Ease out with exponential curves: `cubic-bezier(0.22, 1, 0.36, 1)` (out-quart) or `cubic-bezier(0.16, 1, 0.3, 1)` (out-expo). No bounce. No elastic.
86
+ - One signature motion per page > scattered micro-interactions
87
+ - Always respect `prefers-reduced-motion: reduce`
88
+
89
+ ## 7. Copy
90
+
91
+ - Every word earns its place
92
+ - No restated headings
93
+ - No intros that repeat the title
94
+ - **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
95
+ - CTAs name the action. "Download invoice" not "Get Started". "Continue setup" not "Learn More".
96
+
97
+ ## 8. Absolute bans (match-and-refuse)
98
+
99
+ If you're about to write any of these, rewrite the element with different structure. No exceptions.
100
+
101
+ | Banned pattern | Why | Rewrite with |
102
+ |---|---|---|
103
+ | **Side-stripe borders** — `border-left: 4px` colored as accent on cards / list items / callouts | Decorative noise, never semantic | Full borders, background tints, leading numbers/icons, or nothing |
104
+ | **Gradient text** — `background-clip: text` with a gradient | Decorative, never meaningful | Single solid color. Emphasis via weight or size |
105
+ | **Glassmorphism by default** — blur + glass cards used everywhere | Trendy slop from 2023-2024 | Rare and purposeful, or nothing |
106
+ | **Hero-metric template** — big number, small label, three supporting stats, gradient accent | SaaS cliché | Vary layout per metric. Don't grid them |
107
+ | **Identical card grids** — same-sized cards with icon + heading + text repeated 3+ times | The default AI hero pattern | Vary card sizes, layouts, content shapes |
108
+ | **Modal as first thought** — every action goes through a modal | Lazy interaction design | Inline expansion, progressive disclosure, dedicated route |
109
+
110
+ ## 9. The AI slop test (run at two altitudes)
111
+
112
+ If someone could look at this interface and say "AI made that" without doubt, it failed.
113
+
114
+ **First-order check.** If someone could guess the theme + palette from the category alone, the first reflex won:
115
+ - Observability → dark blue
116
+ - Healthcare → white + teal
117
+ - Finance → navy + gold
118
+ - Crypto → neon on black
119
+
120
+ If yes, rework the scene sentence and color strategy until the answer isn't obvious from the domain.
121
+
122
+ **Second-order check.** If someone could guess the aesthetic family from category-plus-anti-references, the trap one tier deeper won:
123
+ - AI workflow tool that's not SaaS-cream → editorial-typographic
124
+ - Fintech that's not navy-and-gold → terminal-native dark mode
125
+ - Health app that's not white-and-teal → soft-pastel
126
+
127
+ The first reflex was avoided; the second wasn't. Rework until both answers are not obvious. The Brand register's reflex-reject aesthetic lanes catch the currently-saturated families.
128
+
129
+ ## 10. Single-icon-family rule
130
+
131
+ Pick one icon family per project and enforce it. Lucide OR Heroicons OR Phosphor OR Radix Icons. Never mixed. Mixing icon families is the visual equivalent of mixing fonts.
132
+
133
+ ## 11. Anti-references are mandatory
134
+
135
+ Every PRODUCT.md must list 3–5 sites the project should NOT look like. Anti-references are more useful than positive references because they pin down what the design is reacting against.
136
+
137
+ ```
138
+ Anti-references:
139
+ - generic SaaS-cream (Notion clones)
140
+ - terminal-nostalgia (vercel/v0 dark)
141
+ - corporate-navy fintech (most banks)
142
+ ```
143
+
144
+ ## 12. The implementation must match the vision
145
+
146
+ Maximalist designs need elaborate code. Minimalist designs need restraint, precision, and careful attention to spacing and typography. The failure mode is mismatch: elaborate animation on a "clean minimal" claim, or flat execution of an ambitious concept.
147
+
148
+ If you wrote 200 lines of CSS to render a "minimal" landing page, the page is not minimal. If your "bold and maximalist" page uses 4 colors and `text-center`, it's not bold.
@@ -0,0 +1,114 @@
1
+ ---
2
+ globs: ["*.tsx", "*.jsx", "*.css", "*.scss", "*.html", "*.vue", "*.svelte"]
3
+ ---
4
+
5
+ # Design — Product register
6
+
7
+ **When this register applies:** app UI, admin consoles, dashboards, internal tools, settings pages, anything where the design SERVES the product.
8
+
9
+ **The bar:** earned familiarity. Fluent users of Linear, Figma, Notion, Stripe, Raycast should trust the interface on first glance. Distinctiveness is allowed but never at the cost of usability.
10
+
11
+ This register inherits all of `design-laws.md`. The rules below add what changes when familiarity, not distinctiveness, is the goal.
12
+
13
+ ## The product brief (what the agent commits to first)
14
+
15
+ Before any code, the agent writes a 4-line brief and waits for user confirmation:
16
+
17
+ ```
18
+ Reference apps: [Linear · Stripe · Notion · Figma · Raycast · Vercel · Plaid Dashboard · Pylon · ...]
19
+ Color strategy: [Restrained — almost always]
20
+ Scene sentence: [physical scene — focus on context of use, not aesthetic mood]
21
+ Density: [comfortable · standard · compact · ultra-compact]
22
+ ```
23
+
24
+ Reference apps anchor the visual language. Pick 2-3 that share the user mental model and the density.
25
+
26
+ ## Density target
27
+
28
+ Product UIs have to choose density. State it explicitly.
29
+
30
+ | Density | Examples | Use when |
31
+ |---|---|---|
32
+ | **Comfortable** | Notion, Linear (default), Mailchimp | Knowledge work, low-frequency |
33
+ | **Standard** | Stripe Dashboard, Vercel | Mainstream SaaS |
34
+ | **Compact** | Linear (compact mode), Figma left rail | Power users, workflow tools |
35
+ | **Ultra-compact** | Bloomberg Terminal, Trader UIs | Information-dense, professional users |
36
+
37
+ Higher density = smaller font sizes (down to 12px), tighter padding, more rows per viewport. Don't pretend the app is comfortable when it's compact, or vice versa. Match the user's actual workflow.
38
+
39
+ ## Product register — additional laws
40
+
41
+ ### Typography
42
+
43
+ - **One typeface family is fine** for product. Variable fonts shine here (Inter Display, Geist, Switzer, Mona Sans, Söhne, Untitled Sans).
44
+ - Banned (per laws): Inter (regular cut), Roboto, Arial, system-ui, Space Grotesk
45
+ - Body: 13-15px depending on density (comfortable=15, standard=14, compact=13, ultra-compact=12)
46
+ - Hierarchy through weight (400 body, 500 labels, 600 headings) more than size
47
+ - Tabular numerals for any numeric data: `font-feature-settings: "tnum" 1`
48
+ - Truncate long strings with ellipsis + tooltip — never let layout collapse on a long username
49
+
50
+ ### Color
51
+
52
+ - **Restrained is the default.** Tinted neutrals + one accent.
53
+ - **Semantic colors required:** success (green) / warning (amber) / error (red) / info (blue). Always paired with non-color signal (icon, label, pattern).
54
+ - Status indicators must work for color-blind users. Run the design through a deuteranopia simulator.
55
+ - Background depth: 3 surface levels max (`bg`, `surface`, `elevated`). Subtle differences (oklch L delta of 0.03-0.05).
56
+
57
+ ### Layout
58
+
59
+ - **Density first, aesthetics second.** A beautiful UI a user can't navigate quickly is a failed product UI.
60
+ - **Predictable layout.** Sidebar left, main center, optional right rail. Don't reinvent navigation patterns.
61
+ - **Sticky headers** for long-scroll views (tables, lists)
62
+ - **Keyboard-first.** Every action accessible via keyboard. Power users will memorize shortcuts; expose them.
63
+ - **Fitts's Law.** Frequently-used controls go to screen edges. Action buttons in tight clusters.
64
+
65
+ ### Components
66
+
67
+ | Pattern | Product register rule |
68
+ |---|---|
69
+ | **Buttons** | 3 variants max: primary / secondary / ghost. Destructive variant where needed. No "outline + filled + ghost + soft + subtle" proliferation. |
70
+ | **Inputs** | Always have visible labels (not placeholder-only). Validation inline, on blur. Error messages specific and actionable. |
71
+ | **Tables** | Tabular numerals. Right-align numbers. Sort indicators on hover, persistent on active. Sticky headers. |
72
+ | **Empty states** | Always include: icon, single sentence of context, primary action |
73
+ | **Loading** | Skeleton (not spinner) for known-shape content. Spinner only for unknown duration. |
74
+ | **Empty data** | Never "No results." Always "No invoices yet — try [action]." |
75
+ | **Toasts** | Auto-dismiss at 5s minimum. Always dismissible. Errors don't auto-dismiss. |
76
+ | **Modals** | Last resort (per laws). When unavoidable: trap focus, ESC to close, restore focus on close. |
77
+
78
+ ### Motion
79
+
80
+ - Restrained. Product UI motion exists to communicate state changes, not to delight.
81
+ - Hover transitions: 100-150ms ease-out
82
+ - Panel slides: 200ms ease-out
83
+ - Page transitions: 0ms (yes, zero) for navigation between similar views. Motion when it would disorient should be skipped.
84
+ - Skeleton shimmer: 1500ms loop, subtle
85
+ - No bounce. No elastic. No overshoot.
86
+
87
+ ### States (every interactive element)
88
+
89
+ - Default
90
+ - Hover (within 100ms)
91
+ - Focus (visible ring, 2px+ offset, contrasting color)
92
+ - Active/pressed (subtle scale or color shift)
93
+ - Disabled (opacity 0.5, `cursor: not-allowed`, `aria-disabled="true"`)
94
+ - Loading (per-element spinner or skeleton)
95
+ - Error (inline message + `aria-describedby`)
96
+
97
+ Every state on every interactive element. No exceptions.
98
+
99
+ ## Product register success criteria
100
+
101
+ If you can answer YES to all of these, the product register passed:
102
+
103
+ - [ ] A user fluent in the reference apps would feel oriented in 5 seconds
104
+ - [ ] Density is consistent across the app (one chosen value, applied)
105
+ - [ ] Keyboard navigation reaches every action
106
+ - [ ] Empty / loading / error states present on every async surface
107
+ - [ ] Color is never the sole information signal
108
+ - [ ] Tabular numerals on numeric columns
109
+ - [ ] No reinvented navigation pattern
110
+ - [ ] Implementation matches vision (precision and restraint, not flourish)
111
+
112
+ ## When in doubt
113
+
114
+ Ask: "Would Linear ship this?" If the answer is no, rework. Linear is not the only standard, but it is the highest commonly-cited bar for product design in 2025-2026 — fluency, restraint, density, motion all dialed in. Most product work will land within ±10% of Linear's bar; be honest about which side.
@@ -0,0 +1,157 @@
1
+ ---
2
+ globs: ["*.tsx", "*.jsx", "*.css", "*.scss", "*.html", "*.vue", "*.svelte"]
3
+ ---
4
+
5
+ # Design Rubric
6
+
7
+ 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.
8
+
9
+ ## How to score
10
+
11
+ Every dimension is scored 1-5 with EVIDENCE on the next line. Score without evidence is rejected.
12
+
13
+ Anchored definitions:
14
+ - **1** — Fails. Hard violation. WCAG fails, broken layout, absolute-ban hit.
15
+ - **2** — Below acceptable. Functions but signals "AI generated this."
16
+ - **3** — Acceptable. Ships. Not memorable, not embarrassing.
17
+ - **4** — Good. Specific choices visible. A designer would approve.
18
+ - **5** — Excellent. Distinctive. Worth screenshotting and sharing.
19
+
20
+ **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.
21
+
22
+ If a vision model is critiquing screenshots, it must score against this rubric. Without anchoring, vision models say "looks great!" to everything.
23
+
24
+ ## Scope guard
25
+
26
+ 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.
27
+
28
+ A whole-app `/qualia-polish` scores all 8 dimensions across multiple representative routes.
29
+
30
+ ## The 8 dimensions
31
+
32
+ ### 1. Typography
33
+
34
+ | Score | Criteria |
35
+ |---|---|
36
+ | 1 | Inter / Roboto / Arial / system-ui / Space Grotesk as primary. Or single weight throughout. |
37
+ | 2 | Project font loaded but only one weight, no scale, no letter-spacing variation. |
38
+ | 3 | Project font with 2-3 weights, basic scale (h1/h2/body), readable. |
39
+ | 4 | Distinctive display + refined body pair. Letter-spacing varied semantically (tight headlines, open labels). Tabular numerals on numeric data. |
40
+ | 5 | Variable font with axis-driven weight/optical-size. Hierarchy through weight + scale + letter-spacing combined. Line lengths capped at 65-75ch. |
41
+
42
+ Evidence format: `font-family: "<name>" used at line N, scale 14/16/24/40 visible, weights 400/500/700`
43
+
44
+ ### 2. Color cohesion
45
+
46
+ | Score | Criteria |
47
+ |---|---|
48
+ | 1 | Hex values scattered in JSX. No CSS variables. Pure `#000` or `#fff`. |
49
+ | 2 | CSS variables defined but unused (raw hex still appears). RGB used. |
50
+ | 3 | All colors as CSS variables. Tinted neutrals (no pure black/white). One color strategy implied. |
51
+ | 4 | OKLCH throughout. Strategy explicit (Restrained / Committed / Full / Drenched). WCAG AA verified. |
52
+ | 5 | OKLCH with documented strategy. Chroma reduced at extremes. Brand-tinted shadows. APCA contrast verified for dense text. |
53
+
54
+ Evidence: count of CSS custom properties for color, presence of OKLCH, evidence of strategy commitment
55
+
56
+ ### 3. Spatial rhythm
57
+
58
+ | Score | Criteria |
59
+ |---|---|
60
+ | 1 | Arbitrary px values everywhere. No system. |
61
+ | 2 | 8px grid roughly followed. Same padding everywhere. |
62
+ | 3 | 8px grid consistently. Tight within groups, generous between sections. |
63
+ | 4 | Fluid `clamp()` padding. Spacing varies by content type. Vertical rhythm identifiable. |
64
+ | 5 | Spatial system reads as composed — different spacing for different relationships. Generous negative space. Asymmetry where intentional. |
65
+
66
+ Evidence: presence of spacing tokens, padding values divisible by 4, `clamp()` usage
67
+
68
+ ### 4. Layout originality
69
+
70
+ | Score | Criteria |
71
+ |---|---|
72
+ | 1 | Three-column feature grid in section 2. Card grid of 3 identical items. Centered hero with gradient. |
73
+ | 2 | Standard hero + sections + footer. Symmetric throughout. |
74
+ | 3 | Some layout variation across sections. No card monotony. |
75
+ | 4 | Asymmetry, full-bleed, varied component sizes within a section. Negative space used. |
76
+ | 5 | Layout reads as composed by a designer. Diagonal flow, overlap, scale contrast. Each section a different shape. |
77
+
78
+ Evidence: file:line references showing layout choices
79
+
80
+ ### 5. Shadow & depth hierarchy
81
+
82
+ | Score | Criteria |
83
+ |---|---|
84
+ | 1 | Single shadow value applied to everything (or no shadows). Nested cards. |
85
+ | 2 | 2 shadow levels but applied inconsistently. |
86
+ | 3 | 3 elevation levels (subtle / medium / pronounced). Brand-tinted, not pure gray. |
87
+ | 4 | Shadows match elevation semantically. Different shadow for hover than rest. |
88
+ | 5 | Multi-layer shadows (offset + ambient + directional). Brand-hue tinted at chroma 0.02-0.04. Spatial logic clear. |
89
+
90
+ Evidence: count of distinct `box-shadow` values, OKLCH chroma in shadow color
91
+
92
+ ### 6. Motion intent
93
+
94
+ | Score | Criteria |
95
+ |---|---|
96
+ | 1 | No transitions. Or: bounce/elastic everywhere. Animates layout properties. |
97
+ | 2 | Default browser transitions on hover. No stagger. |
98
+ | 3 | Considered transitions on interactive elements. Respects `prefers-reduced-motion`. |
99
+ | 4 | One signature motion identified and executed. Stagger on entrance. Easing curves chosen (ease-out-quart or expo). |
100
+ | 5 | Orchestrated motion that communicates structure. Scroll-driven if appropriate. Restraint elsewhere. |
101
+
102
+ Evidence: easing curves used, presence of `prefers-reduced-motion`, file:line of signature motion
103
+
104
+ ### 7. Microcopy specificity
105
+
106
+ | Score | Criteria |
107
+ |---|---|
108
+ | 1 | "Get Started" / "Learn More" / "Welcome to <product>" / "Click here". Lorem ipsum. |
109
+ | 2 | Generic but functional ("Save", "Cancel", "Submit"). Empty states say "No results." |
110
+ | 3 | Action-named CTAs ("Download invoice"). Empty states with one-sentence context. |
111
+ | 4 | Voice consistent with brand. Errors specific and actionable ("This file is 12MB; max is 10MB. Compress and retry."). |
112
+ | 5 | Microcopy you'd quote. Voice unmistakable. Every word earned. |
113
+
114
+ Evidence: grep for banned phrases, sample of empty/error states
115
+
116
+ ### 8. Container depth & nesting
117
+
118
+ | Score | Criteria |
119
+ |---|---|
120
+ | 1 | Card → panel → pill → content (depth ≥ 4). Side-stripe borders. Gradient text. |
121
+ | 2 | Card-on-card pattern (depth 3). Most things wrapped in containers. |
122
+ | 3 | Container depth ≤ 2. No decorative side-stripes. |
123
+ | 4 | Containers used semantically only. Things that don't need a container don't have one. |
124
+ | 5 | Layout reads as elements arranged on a surface, not boxes inside boxes. |
125
+
126
+ Evidence: max DOM nesting depth on cards/panels, grep for `border-left` decorative usage
127
+
128
+ ## Aggregate score
129
+
130
+ ```
131
+ total = sum of dimension scores (max 40)
132
+ average = total / count_of_scored_dimensions
133
+ phase_pass = ALL scored dimensions ≥ 3
134
+ phase_fail = ANY scored dimension < 3
135
+ ```
136
+
137
+ A phase fails if any dimension is below 3. Same gate as functional verification.
138
+
139
+ ## Output format (verifier agent contract)
140
+
141
+ ```markdown
142
+ ## Design Rubric — Phase {N}
143
+
144
+ | Dim | Score | Evidence |
145
+ |---|---|---|
146
+ | Typography | 4 | `app/page.tsx:14` Fraunces + JetBrains Mono pair, weights 400/500/700, clamp() scale visible |
147
+ | Color cohesion | 3 | All CSS vars in `app/globals.css:8-22`. OKLCH used. Strategy: Restrained. WCAG AA verified |
148
+ | Spatial rhythm | 5 | Fluid clamp padding throughout, varied within section, generous between |
149
+ | Layout originality | 2 | `app/page.tsx:42-78` is a three-column feature grid in section 2 — first-order slop. Rework. |
150
+ | ... | ... | ... |
151
+
152
+ **Aggregate:** 28/40 (avg 3.5)
153
+ **Phase verdict:** FAIL — Layout Originality at 2 blocks the phase.
154
+ **Fix priority:** Rework section 2. Replace three-column grid with varied-height layout per `design-brand.md` §Layout.
155
+ ```
156
+
157
+ If the score < 3, the verifier writes the diagnosis. The fix is the next builder's task.
@@ -1,3 +1,7 @@
1
+ ---
2
+ globs: ["agents/**", "skills/**"]
3
+ ---
4
+
1
5
  # Grounding Protocol & Rubrics
2
6
 
3
7
  Shared quality standards for every Qualia skill and subagent. Reference from every SKILL.md and agent prompt that produces findings, scores, or recommendations.