qualia-framework 5.1.0 → 5.4.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 (53) hide show
  1. package/README.md +50 -26
  2. package/agents/builder.md +8 -0
  3. package/agents/plan-checker.md +10 -1
  4. package/agents/planner.md +1 -1
  5. package/agents/qa-browser.md +10 -0
  6. package/agents/research-synthesizer.md +10 -0
  7. package/agents/researcher.md +38 -2
  8. package/agents/roadmapper.md +10 -0
  9. package/agents/verifier.md +15 -3
  10. package/agents/visual-evaluator.md +1 -1
  11. package/bin/install.js +42 -0
  12. package/bin/state.js +155 -133
  13. package/docs/archive/session-report-2026-04-18.md +199 -0
  14. package/docs/archive/v4.0.0-review.md +288 -0
  15. package/docs/instruction-budget-audit.md +113 -0
  16. package/docs/polish-loop-supervised-run.md +111 -0
  17. package/guide.md +11 -4
  18. package/hooks/session-start.js +1 -1
  19. package/package.json +5 -2
  20. package/rules/architecture.md +125 -0
  21. package/rules/infrastructure.md +1 -2
  22. package/rules/speed.md +55 -0
  23. package/skills/qualia-help/SKILL.md +1 -1
  24. package/skills/qualia-hook-gen/SKILL.md +206 -0
  25. package/skills/qualia-map/SKILL.md +1 -1
  26. package/skills/qualia-milestone/SKILL.md +1 -1
  27. package/skills/qualia-new/SKILL.md +2 -2
  28. package/skills/qualia-optimize/REFERENCE.md +65 -2
  29. package/skills/qualia-optimize/SKILL.md +26 -1
  30. package/skills/qualia-polish/SKILL.md +3 -3
  31. package/skills/qualia-polish-loop/REFERENCE.md +1 -1
  32. package/skills/qualia-polish-loop/SKILL.md +3 -3
  33. package/skills/qualia-polish-loop/fixtures/broken.html +2 -2
  34. package/skills/qualia-polish-loop/scripts/loop.mjs +26 -5
  35. package/skills/qualia-polish-loop/scripts/playwright-capture.mjs +14 -5
  36. package/skills/qualia-polish-loop/scripts/score.mjs +1 -1
  37. package/skills/qualia-postmortem/SKILL.md +1 -1
  38. package/skills/qualia-prd/SKILL.md +199 -0
  39. package/skills/qualia-quick/SKILL.md +1 -1
  40. package/skills/qualia-research/SKILL.md +5 -3
  41. package/skills/qualia-road/SKILL.md +15 -5
  42. package/skills/qualia-task/SKILL.md +1 -1
  43. package/templates/PRODUCT.md +1 -1
  44. package/tests/bin.test.sh +155 -8
  45. package/tests/skills.test.sh +143 -0
  46. package/tests/slop-detect.test.sh +160 -0
  47. package/docs/playwright-loop-review-2026-05-03.md +0 -65
  48. /package/{rules → qualia-design}/design-brand.md +0 -0
  49. /package/{rules → qualia-design}/design-laws.md +0 -0
  50. /package/{rules → qualia-design}/design-product.md +0 -0
  51. /package/{rules → qualia-design}/design-reference.md +0 -0
  52. /package/{rules → qualia-design}/design-rubric.md +0 -0
  53. /package/{rules → qualia-design}/frontend.md +0 -0
@@ -0,0 +1,125 @@
1
+ # Architecture Rules
2
+
3
+ How Qualia code stays navigable for future agents (human and AI). Read on architectural-judgment tasks: refactors, new module decisions, deep-module work, `/qualia-optimize --deepen`.
4
+
5
+ ## 1. Deep modules over shallow ones (Ousterhout)
6
+
7
+ A **deep module** hides significant complexity behind a small, stable interface. A **shallow module** exposes most of its internals — every caller has to know how it works to use it.
8
+
9
+ | | Deep | Shallow |
10
+ |---|---|---|
11
+ | Interface size (params, exports) | Small | Wide |
12
+ | Internal logic | Substantial | Trivial |
13
+ | Cost to change implementation | Low (callers don't notice) | High (every caller breaks) |
14
+ | Cost to read a caller | Low | High (must know module internals) |
15
+
16
+ Deep modules are the primary defense against AI-generated entropy. AI is excellent at generating implementation; humans (and AI under guidance) must defend the **interface**.
17
+
18
+ ### Smell — shallow code
19
+
20
+ If you spot any of these, the module is shallow and is a refactor candidate:
21
+
22
+ - A wrapper function that does only argument shuffling and a single inner call.
23
+ - A type-only file that re-exports types from elsewhere.
24
+ - A "service" that has 8 public methods and one private one.
25
+ - A util module where every export is used in exactly one place.
26
+ - A class whose every method is a one-liner pass-through.
27
+
28
+ `/qualia-optimize --deepen` is the skill that scouts for these and proposes interface consolidations.
29
+
30
+ ## 2. Locality over cleverness
31
+
32
+ Code that changes together should live together. The cost of a "DRY" abstraction is paid every time a future caller has to mentally fork to the abstraction's definition. Three similar lines beats a premature `extractCommon()` that everyone has to read twice.
33
+
34
+ Apply DRY only when:
35
+ - The duplication is exact (not just similar shape).
36
+ - The thing duplicated is unlikely to diverge.
37
+ - The caller doesn't need to know "the rule" to read the call site.
38
+
39
+ If any of those three is uncertain, leave the duplication. Pocock's rule of thumb: **three is the threshold, but only if all three would change in lock-step.**
40
+
41
+ ## 3. Adapters at seams
42
+
43
+ Wherever the system meets an external dependency (database, third-party API, AI provider, payment gateway), introduce an adapter. The adapter:
44
+
45
+ - Owns the dependency's specific shape (auth headers, response envelopes, error formats).
46
+ - Translates to a project-internal type that the rest of the code uses.
47
+ - Is the only file that needs to change when the dependency is swapped or upgraded.
48
+
49
+ This is the seam where tests inject fakes and where future migrations live. A codebase without adapters is a codebase that fights every dependency upgrade.
50
+
51
+ **Example seams** in a typical Qualia project:
52
+ - `lib/supabase/server.ts` — adapter over `@supabase/supabase-js`.
53
+ - `lib/openrouter/client.ts` — adapter over OpenRouter REST API.
54
+ - `lib/retell/agent.ts` — adapter over Retell AI SDK.
55
+ - `lib/zoho/contacts.ts` — adapter over Zoho Books API.
56
+
57
+ Direct calls to vendor SDKs from feature code are a smell. Move them through an adapter.
58
+
59
+ ## 4. Progressive disclosure of complexity
60
+
61
+ A reader entering the codebase from a fresh clone should be able to follow this path:
62
+
63
+ ```
64
+ README.md → app/ or src/index → one feature folder → one route → one component → one util
65
+ ```
66
+
67
+ At each step the depth increases. The top is breadth (what does this app do?), the bottom is depth (how does this specific util compute X?). Skipping levels is a smell:
68
+
69
+ - An entry point that imports 30 modules from across the tree → the tree is shallow.
70
+ - A route handler that calls a database directly → no service layer; logic and IO are entangled.
71
+ - A component that owns its own data fetching, mutation logic, error handling, and rendering → no hook abstraction; the component will be impossible to test or replace.
72
+
73
+ The pattern that tells a fresh reader where to go next is **layered service boundaries**:
74
+ 1. **Routes / pages** — wiring only. No business logic.
75
+ 2. **Features / use cases** — business logic. Calls services.
76
+ 3. **Services** — orchestration. Calls adapters.
77
+ 4. **Adapters** — IO. The only layer that talks to vendors.
78
+ 5. **Domain types** — pure. No imports of the above.
79
+
80
+ Inversions of this order (domain types importing adapters, services calling components) are bugs in shape.
81
+
82
+ ## 5. Interface stability beats internal elegance
83
+
84
+ Once an interface has callers, changing it is expensive. Internal refactors are cheap. **Optimize for the cost of change.**
85
+
86
+ When in doubt:
87
+ - A new public function: write it conservatively. Defaults are a liability — every default is a future migration.
88
+ - An internal function: write it expressively. Internal callers can be fixed in one sweep.
89
+
90
+ Pocock's heuristic from de-slop: *the interface is the thing the AI shouldn't change without you. The implementation is the thing the AI can rewrite at will.*
91
+
92
+ ## 6. Test the seam, not the function
93
+
94
+ Unit tests that pin internal function signatures rot fast — every refactor breaks them. Tests against the **adapter** or **service interface** survive refactors.
95
+
96
+ Order of test value (high → low):
97
+ 1. **End-to-end / user-flow** — tests at the route level. Survive everything except feature changes.
98
+ 2. **Service-level** — tests at the use-case boundary. Survive most refactors.
99
+ 3. **Adapter-level** — tests with the vendor mocked. Survive vendor swaps.
100
+ 4. **Unit / function-level** — tests against a single internal function. Last resort. Only for genuinely tricky algorithms.
101
+
102
+ The pyramid in older textbooks (lots of unit, few e2e) inverted in the AI era. AI generates internal functions cheaply; the seam tests are the ones that survive AI-driven refactors.
103
+
104
+ ## 7. The codebase IS the documentation
105
+
106
+ Per Pocock's *"Never run /init"*: static documentation rots within weeks. The agents and humans should be able to **explore** to discover, not **memorize** to recall.
107
+
108
+ Practical rules:
109
+ - README.md: orientation only — what is this app, how do I run it, where is the source of truth for the rest. Not API docs, not architecture diagrams that will lie within a sprint.
110
+ - `.planning/CONTEXT.md`: domain glossary, append-only as terms emerge. Discovered, not maintained.
111
+ - ADRs in `.planning/decisions/`: hard-to-reverse calls, dated, immutable. Future archaeology, not current spec.
112
+ - Anything else: it lives in code or it doesn't exist. If you need a diagram, generate it from the code at read-time.
113
+
114
+ A skill or agent that needs context should `Read` the relevant code, not a synopsis of it written six months ago.
115
+
116
+ ## 8. When to apply this rule file
117
+
118
+ Read this file (auto-load via skill or `@rules/architecture.md`) when:
119
+
120
+ - Planning a new module or feature with multiple components.
121
+ - The user requests `/qualia-optimize --deepen` or `--alignment`.
122
+ - A verifier is scoring "Container depth & nesting" (per `rules/design-rubric.md` dimension 8).
123
+ - An ADR is being drafted for an architectural fork.
124
+
125
+ Do **not** auto-load this on quick fixes, copy edits, single-component touch-ups — that wastes instruction budget. Use judgment.
@@ -8,8 +8,7 @@ Standard services across all Qualia projects. Use these unless the project expli
8
8
 
9
9
  ## Database: Supabase (every project)
10
10
  - Every project uses Supabase for auth, database, and storage
11
- - **CLI:** `npx supabase` migrations, type generation, local dev
12
- - **MCP:** Supabase MCP server is available in Claude Code for direct database operations
11
+ - **CLI-first** — prefer `npx supabase` (migrations, type generation, local dev, SQL) over the Supabase MCP server. The MCP imposes a token tax on every turn; the CLI hits the same API at zero token cost. Use the MCP only when you need a feature the CLI doesn't expose (e.g., interactive branch management).
13
12
  - Always enable RLS on every table (see `rules/security.md`)
14
13
  - Use `lib/supabase/server.ts` for server-side, `lib/supabase/client.ts` for client-side
15
14
  - Run `npx supabase gen types` after schema changes
package/rules/speed.md ADDED
@@ -0,0 +1,55 @@
1
+ ---
2
+ alwaysApply: true
3
+ ---
4
+
5
+ # Speed Rules (MANDATORY)
6
+
7
+ ## Direct tools over subagents
8
+
9
+ **NEVER use Task(Explore) or Task(general-purpose) for simple file lookups or code searches.** Use direct tools instead:
10
+ - **Glob** for finding files by name/pattern
11
+ - **Grep** for searching code content
12
+ - **Read** for reading specific files
13
+ - Only use Task(Explore) when you genuinely need 5+ rounds of deep codebase archaeology.
14
+
15
+ **NEVER spawn subagents when direct tools work.** Subagents are slow — a direct Glob or Grep returns in seconds, a fresh agent burns 5-10 seconds of spawn overhead plus its own context budget.
16
+
17
+ **Bias toward action, not exploration.** If the user asks you to fix something and you know the project structure, just do it.
18
+
19
+ ## CLI-first, MCP only when CLI can't
20
+
21
+ MCP servers impose a **token tax**: their tool definitions consume context-window space on every turn, even when unused. CLIs that the model already knows from training data (git, gh, supabase, vercel, railway, npx, curl) impose zero token tax — the model recalls them from weights, not from the prompt.
22
+
23
+ **Default to CLI.** Reach for MCP only when:
24
+ - The CLI doesn't exist or doesn't expose the operation you need.
25
+ - The CLI requires interactive auth that MCP has already brokered (e.g., Stripe Dashboard).
26
+ - The MCP returns structured JSON that would be expensive to parse from CLI text output.
27
+ - The MCP enforces governance (RLS-aware queries, scoped DB credentials) that the CLI doesn't.
28
+
29
+ If a `/skill-name` exists that wraps a CLI, prefer the skill — it's been hardened. Canonical example: `/supabase` skill replaces 32 supabase MCP tools with `supabase` CLI calls and saves substantial token budget.
30
+
31
+ ### MCP tier-list (when each is justified)
32
+
33
+ | Server | Always-on? | Justification |
34
+ |---|---|---|
35
+ | `claude-in-chrome` | On-demand | Browser automation has no CLI equivalent; use for QA flows only |
36
+ | `supabase` MCP | **Off** in favor of `/supabase` skill | CLI covers 95% of operations; MCP only if you need branch management interactively |
37
+ | `context7` | On-demand | Library docs at runtime — no CLI alternative for Context7 itself |
38
+ | `notebooklm-mcp` | On-demand | NotebookLM has no CLI; only loaded when researching against existing notebooks |
39
+ | `firecrawl-mcp` | On-demand | Web scraping; only loaded when feature requires it |
40
+ | `next-devtools` | Always-on (dev) | Next.js 16 runtime errors not visible elsewhere |
41
+ | `mux`, `stitch`, `higgsfield` | On-demand | Specialized API surfaces; load only on relevant client work |
42
+ | `ZohoMCP`, `qualia-erp` | On-demand | Business ops only, not engineering-path |
43
+
44
+ The pattern: **on-demand by default; always-on only when the data is irreducibly remote AND there's no CLI.**
45
+
46
+ ## Use shortcuts (Qualia commands)
47
+
48
+ When a Qualia command exists for the situation, use it — don't reinvent:
49
+ - `/qualia` — what's my next step?
50
+ - `/qualia-quick` — small inline fix, no plan, no spawn
51
+ - `/qualia-task` — single focused task, fresh builder spawn, atomic commit
52
+ - `/qualia-ship` — full deploy pipeline (quality gates → commit → deploy → verify)
53
+ - `/qualia-review` — production audit
54
+ - `/qualia-pause` — save context before clearing the conversation
55
+ - `/qualia-learn` — save a lesson from a mistake
@@ -1,6 +1,6 @@
1
1
  ---
2
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'."
3
+ description: "Open the BROWSER HTML reference for the Qualia Framework themed page with all commands, rules, services, and the road. The default when a browser is available. For terminal-only output (SSH, headless), use /qualia-road. Triggers: 'help', 'how does this work', 'show me the commands', 'qualia help', 'reference', 'open the docs'."
4
4
  allowed-tools:
5
5
  - Bash
6
6
  - Read
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: qualia-hook-gen
3
+ description: "Take a project's CLAUDE.md or rules/*.md instruction and convert it deterministically into a Claude Code pre-tool-use hook. Generates block-{cmd}.sh + the settings.json patch + activation steps. Lets users actually shrink their CLAUDE.md instead of just hearing the instruction-budget advice. Trigger on 'qualia-hook-gen', 'turn this rule into a hook', 'enforce this deterministically', 'block npm', 'force pnpm', 'convert claude.md to hooks', 'shrink my instruction budget'. v5.3 from Matt Pocock's enforce-deterministically-not-instructionally pattern."
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Grep
10
+ - Glob
11
+ argument-hint: "[--rule \"text\"] [--from CLAUDE.md] [--name HOOK_NAME] [--scope global|project] [--dry-run]"
12
+ ---
13
+
14
+ # /qualia-hook-gen — Convert instructions → deterministic hooks
15
+
16
+ LLMs have a realistic instruction budget of ~300-500 instructions before quality degrades (Matt Pocock). A line in CLAUDE.md like "use pnpm not npm" burns budget on EVERY request — even when the task has nothing to do with package management. Worse, it's non-deterministic: the model can still run `npm install` if it forgets.
17
+
18
+ The fix: convert that instruction into a deterministic `pre-tool-use` hook. The hook blocks the wrong command (or rewrites it to the right one) at execution time, frees the instruction budget, and works regardless of context window state.
19
+
20
+ ## When to use
21
+
22
+ - Your CLAUDE.md has 50+ lines and you want to slim it
23
+ - A specific instruction is enforceable as a CLI rule (use X not Y, never run Z, redirect A to B)
24
+ - You want a hook for a specific failure mode (e.g., "always use --force-with-lease, never --force")
25
+
26
+ ## What it does NOT do
27
+
28
+ - Hooks for stylistic guidance (e.g., "prefer composition over inheritance") — that's not enforceable by command match. Stays in skills.
29
+ - Hooks for non-deterministic checks (e.g., "validate the design feel"). Use `/qualia-polish` instead.
30
+ - Hooks that need state across multiple commands. Use Qualia's existing state.js machinery.
31
+
32
+ ## Process
33
+
34
+ ### 1. Identify the rule
35
+
36
+ Three input modes:
37
+
38
+ | Mode | Source |
39
+ |---|---|
40
+ | `--rule "..."` | Direct argument (e.g. `--rule "use pnpm not npm"`) |
41
+ | `--from CLAUDE.md` | Pull instructions from the file, list them, let user pick |
42
+ | (no arg) | Read CLAUDE.md, scan for enforceable rules, propose top 3 candidates |
43
+
44
+ ### 2. Classify enforceability
45
+
46
+ For the chosen rule, classify into one of three patterns:
47
+
48
+ | Pattern | Example | Hook shape |
49
+ |---|---|---|
50
+ | **Block** | "never use `git push --force` to main" | exit 2 with message if pattern matches |
51
+ | **Rewrite** | "use pnpm not npm" | exit 2 with message guiding to alternative |
52
+ | **Warn** | "prefer next/image over <img>" | exit 0 but print warning to stderr |
53
+
54
+ If the rule isn't classifiable as any of these — i.e. it's stylistic or judgment-based — HALT with: "This rule isn't deterministically enforceable. Keep it in CLAUDE.md or move to a skill. Examples of enforceable rules: package-manager redirects, destructive-command blocks, file-path enforcement."
55
+
56
+ ### 3. Generate the hook script
57
+
58
+ Write to `hooks/block-{name}.js` (Node, cross-platform — same shape as existing hooks):
59
+
60
+ ```javascript
61
+ #!/usr/bin/env node
62
+ // hooks/block-{name}.js — auto-generated by /qualia-hook-gen
63
+ // Original instruction: "{rule text}"
64
+ // Pattern: {block | rewrite | warn}
65
+ // Generated: {ISO date}
66
+
67
+ const { readFileSync } = require("fs");
68
+ let payload;
69
+ try { payload = JSON.parse(readFileSync(0, "utf8")); } catch { process.exit(0); }
70
+ const cmd = (payload.tool_input && payload.tool_input.command) || "";
71
+
72
+ // Match condition (regex from rule classification)
73
+ if (!/{matcher}/i.test(cmd)) process.exit(0); // not our concern
74
+
75
+ // Action
76
+ console.error("⚠ Qualia hook ({name}): {message}");
77
+ console.error(" Suggested: {suggested_alt}");
78
+ process.exit(2); // 2 = BLOCK in Claude Code hook protocol
79
+ ```
80
+
81
+ The exact matcher + message + suggestion are filled by the synthesizer based on the rule classification.
82
+
83
+ ### 4. Generate the settings.json patch
84
+
85
+ ```json
86
+ {
87
+ "hooks": {
88
+ "PreToolUse": [
89
+ {
90
+ "matcher": "Bash",
91
+ "hooks": [
92
+ {
93
+ "type": "command",
94
+ "if": "Bash({if-condition})",
95
+ "command": "node \"${HOME}/.claude/hooks/block-{name}.js\"",
96
+ "timeout": 5,
97
+ "statusMessage": "⬢ Checking {what}..."
98
+ }
99
+ ]
100
+ }
101
+ ]
102
+ }
103
+ }
104
+ ```
105
+
106
+ The `if` condition narrows when the hook fires (e.g., `Bash(npm*)` to fire only on npm). Saves cycles by skipping the hook entirely on irrelevant commands.
107
+
108
+ ### 5. Test the hook
109
+
110
+ ```bash
111
+ # Simulate a triggering command
112
+ echo '{"tool_input":{"command":"{triggering_example}"}}' | \
113
+ node hooks/block-{name}.js
114
+ echo "Exit: $?" # should be 2
115
+
116
+ # Simulate a non-triggering command
117
+ echo '{"tool_input":{"command":"{safe_example}"}}' | \
118
+ node hooks/block-{name}.js
119
+ echo "Exit: $?" # should be 0
120
+ ```
121
+
122
+ If the test passes, proceed. If not, debug the matcher regex.
123
+
124
+ ### 6. Activate
125
+
126
+ Two scopes:
127
+
128
+ | Scope | Action |
129
+ |---|---|
130
+ | `--scope project` (default for project rules) | Add the patch to `.claude/settings.json` in the project root |
131
+ | `--scope global` | Add to `~/.claude/settings.json`. Use only if rule applies to ALL projects |
132
+
133
+ Use the existing settings-merge logic from `bin/install.js:756-778` (preserves user fields, atomic write, backup-before-overwrite).
134
+
135
+ ### 7. Suggest CLAUDE.md slim
136
+
137
+ After activating, scan CLAUDE.md / `rules/*.md` for the original instruction. If found, suggest the user remove it (don't auto-remove — let the user verify the hook works first):
138
+
139
+ ```
140
+ ✓ Hook installed: hooks/block-{name}.js
141
+ ✓ Settings patched: .claude/settings.json
142
+ ℹ You can now remove this line from CLAUDE.md (the hook enforces it deterministically):
143
+ > "{original instruction}"
144
+ ℹ Test with: echo '{"tool_input":{"command":"{triggering_example}"}}' | node hooks/block-{name}.js
145
+ ```
146
+
147
+ ### 8. Commit
148
+
149
+ ```bash
150
+ git add hooks/block-{name}.js .claude/settings.json
151
+ git -c user.name="Qualia Solutions" -c user.email="info@qualiasolutions.net" \
152
+ commit -m "feat(hook): block-{name} — enforces \"{rule}\" deterministically"
153
+ ```
154
+
155
+ ## Examples
156
+
157
+ **Block npm in favor of pnpm:**
158
+ ```
159
+ /qualia-hook-gen --rule "use pnpm not npm"
160
+ → hooks/block-npm.js (matches /^\s*npm\s+(install|i|run|exec)/, exit 2)
161
+ → .claude/settings.json (PreToolUse > Bash > if: Bash(npm*))
162
+ → "npm install" now blocks with: "Use pnpm not npm. Run: pnpm install"
163
+ ```
164
+
165
+ **Block destructive git on main:**
166
+ ```
167
+ /qualia-hook-gen --rule "never push --force to main"
168
+ → hooks/block-force-push-main.js (matches /git push.*--force.*main/)
169
+ → Already covered by hooks/git-guardrails.js — surface this overlap and skip
170
+ ```
171
+
172
+ **Force /server/ for service_role usage:**
173
+ ```
174
+ /qualia-hook-gen --rule "service_role only in lib/server/*"
175
+ → Not enforceable as a CLI hook (it's a code-level rule).
176
+ → HALT with recommendation: ESLint rule or pre-deploy-gate.js entry instead.
177
+ ```
178
+
179
+ ## Token discipline
180
+
181
+ This skill itself is short by design (~150 lines SKILL.md). REFERENCE.md (if added later) only carries verbatim hook templates. The whole point of `/qualia-hook-gen` is to REDUCE token cost across a project, not add to it.
182
+
183
+ Per-invocation: ~3K tokens for the rule-classification + hook-template synthesis. Net savings: every subsequent request saves the ~50-200 tokens that the moved CLAUDE.md instruction was costing.
184
+
185
+ ## Failure modes
186
+
187
+ | Symptom | Cause | Action |
188
+ |---|---|---|
189
+ | Rule isn't a CLI command | Stylistic / judgment-based | HALT with recommendation: skill or ESLint rule |
190
+ | Matcher would catch too much | Regex too greedy | Tighten with `--name` and explicit pattern; user-confirm before write |
191
+ | Hook conflicts with existing | Same command already hooked | Surface the conflict; refuse to overwrite without `--force` |
192
+ | Settings.json malformed | Pre-existing bad JSON | Refuse to patch; ask user to fix settings.json first |
193
+ | `node` not on hook PATH | Cross-platform issue | Use `process.execPath` resolution; framework's existing hooks handle this |
194
+
195
+ ## Rules
196
+
197
+ 1. **Hook is determinism, skill is guidance.** Hooks can only block/rewrite/warn on CLI patterns. Stylistic rules stay in skills.
198
+ 2. **Never overwrite an existing hook silently.** If `hooks/block-{name}.js` exists, surface and ask.
199
+ 3. **Test before committing.** The hook must pass the trigger + non-trigger smoke tests before commit.
200
+ 4. **Suggest CLAUDE.md cleanup.** After install, surface the now-redundant CLAUDE.md line. Don't auto-delete — user verifies the hook works first.
201
+ 5. **Match Qualia's hook shape.** All hooks are pure Node, cross-platform, exit 0/2. No `.sh` scripts (Windows compat).
202
+
203
+ ## Pairs with
204
+
205
+ - `/qualia-optimize --deepen` — runs sometimes after a hook-gen pass when CLAUDE.md gets short enough that the codebase architecture becomes the next bottleneck
206
+ - Existing hooks: `git-guardrails.js`, `pre-deploy-gate.js`, `vercel-account-guard.js`, `env-empty-guard.js`, `supabase-destructive-guard.js`. New hooks generated by this skill follow the same conventions.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: qualia-map
3
- description: "Map an existing codebase to infer architecture, stack, conventions, what's already built, AND adapt Qualia to the repo's existing tracker/labels/glossary conventions (onboarding). For brownfield projects — run BEFORE /qualia-new so Validated requirements get inferred from existing code and Qualia commands respect the repo's existing process."
3
+ description: "Map an existing codebase to infer architecture, stack, conventions, what's already built, AND adapt Qualia to the repo's existing tracker/labels/glossary conventions (onboarding). For brownfield projects — run BEFORE /qualia-new so Validated requirements get inferred from existing code and Qualia commands respect the repo's existing process. Triggers: 'map this codebase', 'onboard to existing project', 'brownfield setup', 'what's already built here', 'scan the repo', 'inherited a codebase', 'audit this project before planning'."
4
4
  allowed-tools:
5
5
  - Bash
6
6
  - Read
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: qualia-milestone
3
- description: "Close the current milestone and open the next one — loads the next milestone's scope from JOURNEY.md (no ad-hoc naming). Archives artifacts, marks requirements Complete, regenerates ROADMAP.md for the next milestone."
3
+ description: "Close the current milestone and open the next one — loads the next milestone's scope from JOURNEY.md (no ad-hoc naming). Archives artifacts, marks requirements Complete, regenerates ROADMAP.md for the next milestone. Triggers: 'close milestone', 'next milestone', 'milestone done', 'wrap up milestone', 'M1 done open M2', 'I want to advance to the next milestone', 'finish this milestone'."
4
4
  allowed-tools:
5
5
  - Bash
6
6
  - Read
@@ -183,7 +183,7 @@ git commit -m "docs: PRODUCT.md — register, users, voice, anti-references"
183
183
  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):
184
184
 
185
185
  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).
186
- 2. **Color strategy** — pick ONE: `Restrained · Committed · Full palette · Drenched`. See `rules/design-laws.md` §2.
186
+ 2. **Color strategy** — pick ONE: `Restrained · Committed · Full palette · Drenched`. See `qualia-design/design-laws.md` §2.
187
187
  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.
188
188
  4. **Differentiation** — one sentence: what someone remembers 24 hours later.
189
189
 
@@ -198,7 +198,7 @@ Then fill the rest of DESIGN.md:
198
198
  - §9 Responsive: mobile-first
199
199
  - §10 Anti-pattern checklist (the auto-runnable one)
200
200
 
201
- Cross-check the result against `rules/design-laws.md` §8 absolute bans BEFORE writing — the design must not propose any banned pattern.
201
+ Cross-check the result against `qualia-design/design-laws.md` §8 absolute bans BEFORE writing — the design must not propose any banned pattern.
202
202
 
203
203
  ```bash
204
204
  git add .planning/DESIGN.md .planning/config.json
@@ -15,7 +15,7 @@ Agent(
15
15
  </planning>
16
16
 
17
17
  <rules>
18
- {rules/frontend.md content}
18
+ {qualia-design/frontend.md content}
19
19
  </rules>
20
20
 
21
21
  <task>
@@ -30,7 +30,7 @@ Analyze frontend:
30
30
 
31
31
  2. **Design Alignment**
32
32
  - Components vs DESIGN.md (colors, typography, spacing)
33
- - rules/frontend.md compliance: distinctive fonts? sharp accents? transitions? No card grids / gradients?
33
+ - qualia-design/frontend.md compliance: distinctive fonts? sharp accents? transitions? No card grids / gradients?
34
34
  - Consistency across app (buttons, spacing, colors)
35
35
 
36
36
  3. **Frontend Perf**
@@ -200,3 +200,66 @@ Format: What/Where/Why/Fix/Severity.
200
200
  description="Architecture synthesis + deepening"
201
201
  )
202
202
  ```
203
+
204
+ ## Parallel interface design prompt (`--deepen` Wave 3, fan-out × 3)
205
+
206
+ Spawn 3 agents in the SAME response turn. Each gets the same candidate but a *different* design constraint so the alternatives differ structurally. Use this verbatim — the per-agent constraint is the only variable:
207
+
208
+ ```
209
+ Agent(
210
+ prompt="Interface designer (variant {1|2|3}/3). Produce ONE radically different
211
+ interface for this deep-module candidate. Other variants are running in parallel
212
+ with different constraints — yours is uniquely framed by your design lens.
213
+
214
+ <candidate>
215
+ {candidate block from arch strategist: files, problem, current shallow signature}
216
+ </candidate>
217
+
218
+ <context>
219
+ {INLINE .planning/CONTEXT.md (domain glossary — USE these terms verbatim)}
220
+ {INLINE .planning/decisions/*.md (ADRs constraining the design space)}
221
+ </context>
222
+
223
+ <your_lens>
224
+ Variant 1 → functional / data-oriented (no classes; pure functions; explicit data flow)
225
+ Variant 2 → OOP / encapsulated (class with private state; methods on a stable receiver)
226
+ Variant 3 → event-driven / message-based (subscriber model; commands and events)
227
+ [Use whichever lens is assigned to YOU above — fan-out call passes only ONE]
228
+ </your_lens>
229
+
230
+ <task>
231
+ Design the interface only. Do NOT implement. Output:
232
+
233
+ 1. **Interface sketch** (TypeScript signatures, 5-15 lines). Function/class/event
234
+ names use CONTEXT.md domain language. No invented synonyms.
235
+
236
+ 2. **Locality gain** (1 sentence): what concentrates in this module's seam that
237
+ was previously scattered across N files?
238
+
239
+ 3. **Testability** (1-3 lines): where do mocks / adapters live? What's a
240
+ 1-line test name that would be easy to write against this interface?
241
+
242
+ 4. **Migration cost** (1 line): rough count — how many callers need updating?
243
+ Are any breaking changes? Can it be staged incrementally?
244
+
245
+ 5. **Trade-off** (1 sentence): what does THIS shape sacrifice compared to the
246
+ other two variants?
247
+
248
+ Constraints:
249
+ - Interface should be DEEP (high leverage per surface area). Refuse a shallow
250
+ wrapper that just renames the existing functions.
251
+ - The deletion test must pass: deleting this module makes complexity vanish at
252
+ N callers, not just relocate it.
253
+ - Use CONTEXT.md terms. Do NOT invent new vocabulary.
254
+ - Output exactly the 5 numbered sections above. No prose preamble.
255
+ </task>",
256
+ subagent_type="general-purpose",
257
+ description="Interface variant {N}/3 — {functional|OOP|event-driven} lens"
258
+ )
259
+ ```
260
+
261
+ After all 3 return, present a comparison table to the user (see SKILL.md Step 5b). User picks 1, 2, 3, or hybrid. Then a single synthesizer agent writes the Refactor RFC to `.planning/REFACTOR-{slug}.md` honoring the user's pick.
262
+
263
+ **Token cost**: ~6K per variant × 3 variants = ~18K for the fan-out. Cached prefix (CONTEXT.md + ADRs + candidate block) is shared across the 3 spawns, so effective cost is closer to ~12K. The output rfc-pick stage adds ~3K. Total per-deepening-candidate: ~15K — well within Qualia's per-skill budget.
264
+
265
+ **Skip variants when one would obviously dominate**: if the codebase is heavily functional (e.g., Effect-based) the OOP variant adds zero value. Strategist may suggest 2 lenses instead of 3 in that case. Default is always 3 unless explicitly noted.
@@ -73,7 +73,7 @@ ls .planning/decisions/ 2>/dev/null && cat .planning/decisions/*.md 2>/dev/null
73
73
 
74
74
  Also read rules:
75
75
  ```bash
76
- cat ~/.claude/rules/frontend.md 2>/dev/null
76
+ cat ~/.claude/qualia-design/frontend.md 2>/dev/null
77
77
  cat ~/.claude/rules/security.md 2>/dev/null
78
78
  ```
79
79
 
@@ -127,6 +127,31 @@ Spawn **arch strategist** (@REFERENCE.md "Architecture strategist prompt (deepen
127
127
 
128
128
  **Skip Wave 2 for single-mode** (`--perf`, `--ui`, `--backend`, `--alignment`). Run for `full` and `deepen`.
129
129
 
130
+ ### Step 5b: Wave 3 -- Parallel Interface Design (`--deepen` only, after candidate selection)
131
+
132
+ After the strategist returns deepening candidates, present a numbered list to the user. User picks ONE candidate (or `--auto` mode picks the highest-severity).
133
+
134
+ For the chosen candidate, spawn **3 fan-out agents in parallel, in the same response turn**, each producing a *radically different* interface design for the proposed deep module. From Matt Pocock's improve-codebase-architecture skill: "spawn three sub-agents in parallel, each must produce a radically different interface for the deepened module."
135
+
136
+ Spawn 3 (@REFERENCE.md "Parallel interface design prompt"). Each receives:
137
+ - The candidate's files, problem, and current shallow signature
138
+ - CONTEXT.md domain glossary (use shared terms)
139
+ - A *different* design constraint (functional / OOP / event-driven / minimal-surface / hexagonal — assigned per agent so the variants differ in shape, not just naming)
140
+
141
+ Collect all 3 proposals. Present to the user as a side-by-side table:
142
+
143
+ | # | Interface shape | Locality gain | Testability | Migration cost |
144
+ |---|---|---|---|---|
145
+ | 1 | {sketch} | {what concentrates} | {seams} | {N callers updated} |
146
+ | 2 | ... | ... | ... | ... |
147
+ | 3 | ... | ... | ... | ... |
148
+
149
+ User picks `1`, `2`, `3`, or `hybrid` (with notes on which elements from which proposals to combine). The synthesizer then writes a "Refactor RFC" to `.planning/REFACTOR-{slug}.md` and optionally opens a GH issue (mirrors `/qualia-prd` flow).
150
+
151
+ **Why parallel + radically different**: a single deepening proposal anchors on the first idea the LLM has. Three parallel proposals with diverse design constraints surface trade-offs the user can see at a glance — and the human's "taste" dominates the choice rather than the agent's first instinct. Empirically (Matt Pocock + Qualia internal testing) this produces dramatically better refactor RFCs than a single-pass proposal.
152
+
153
+ **Skip Wave 3 for `full` mode** (too many candidates to fan out per-candidate). Run for `--deepen` only when a candidate is selected.
154
+
130
155
  ### Step 6: Alignment Check (`full` and `alignment` modes)
131
156
 
132
157
  `alignment`: sole analysis. `full`: alongside Wave 1.
@@ -37,7 +37,7 @@ Before any work — design or otherwise — pass these gates. Skipping them prod
37
37
 
38
38
  | Gate | Required check | If fail |
39
39
  |---|---|---|
40
- | Substrate | `rules/design-laws.md`, `design-brand.md`, `design-product.md`, `design-rubric.md` exist and have been read | Read them. |
40
+ | Substrate | `qualia-design/design-laws.md`, `design-brand.md`, `design-product.md`, `design-rubric.md` exist and have been read | Read them. |
41
41
  | PRODUCT | `PRODUCT.md` exists at project root, has `register:` field, and is not placeholder (`[TODO]` markers, &lt; 200 chars) | Run setup: ask 5 questions and generate it. Never synthesize from prompt alone. |
42
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
43
  | Slop-detect | `bin/slop-detect.mjs` is callable | Install or pull from framework. |
@@ -100,7 +100,7 @@ For App / Redesign / Section scope on multi-file work:
100
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.
101
101
 
102
102
  Each agent receives:
103
- - `rules/design-laws.md` + the matching register file
103
+ - `qualia-design/design-laws.md` + the matching register file
104
104
  - `PRODUCT.md` + `DESIGN.md` (inlined)
105
105
  - Its 5 files (paths + contents)
106
106
  - Instruction: apply the Design Quality Rubric per file. Fix every dimension scoring &lt; 3. Make literal edits. Do NOT change logic — only styling.
@@ -158,7 +158,7 @@ viewports: [
158
158
  For each iteration:
159
159
 
160
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
161
+ 2. Pass to a vision-model agent with `qualia-design/design-rubric.md` as the prompt anchor + DESIGN.md as the spec
162
162
  3. The agent scores 8 dimensions, anchored 1-5, with evidence per dimension
163
163
  4. Apply fixes ONLY to dimensions scored 1 or 2 (don't nitpick 3s; prevents oscillation)
164
164
  5. STOP if: all dimensions ≥ 3 (success), OR any dimension regressed from previous iteration (regression-stop), OR 2 iterations reached (hard cap)
@@ -58,7 +58,7 @@ Agent({
58
58
  Role: @~/.claude/agents/visual-evaluator.md
59
59
 
60
60
  <rubric>
61
- {INLINE rules/design-rubric.md §"The 8 dimensions" through §"Aggregate score"}
61
+ {INLINE qualia-design/design-rubric.md §"The 8 dimensions" through §"Aggregate score"}
62
62
  </rubric>
63
63
 
64
64
  <brief>
@@ -18,7 +18,7 @@ See its own work. Fix its own work. Stop only when correct.
18
18
 
19
19
  ## What it does
20
20
 
21
- Takes a URL + design brief. Screenshots at 3 viewports (mobile / tablet / desktop). Spawns a vision evaluator that scores 8 dimensions of `rules/design-rubric.md` against the brief with cited evidence. Spawns up to 3 fix-builders in parallel for the top issues. Re-screenshots. Loops until all dimensions ≥ 3 or the kill-switch trips (regression, budget, or max iterations).
21
+ Takes a URL + design brief. Screenshots at 3 viewports (mobile / tablet / desktop). Spawns a vision evaluator that scores 8 dimensions of `qualia-design/design-rubric.md` against the brief with cited evidence. Spawns up to 3 fix-builders in parallel for the top issues. Re-screenshots. Loops until all dimensions ≥ 3 or the kill-switch trips (regression, budget, or max iterations).
22
22
 
23
23
  Different from `/qualia-polish`: that one is read+edit+slop-detect, single pass. This one is **see+edit+verify+repeat** with a real loop and real screenshots.
24
24
 
@@ -39,7 +39,7 @@ Run these in order. Halt on the first failure.
39
39
 
40
40
  | Gate | Check | If fail |
41
41
  |---|---|---|
42
- | Substrate | `rules/design-rubric.md`, `rules/design-laws.md` exist | Run `npx qualia install` |
42
+ | Substrate | `qualia-design/design-rubric.md`, `qualia-design/design-laws.md` exist | Run `npx qualia install` |
43
43
  | Brief | `--brief` PATH if provided, else `.planning/DESIGN.md`, else PRODUCT.md | If none, HALT: "No design brief found. Pass --brief or run /qualia-new." |
44
44
  | Browser | `node ~/.claude/skills/qualia-polish-loop/scripts/playwright-capture.mjs --url about:blank --out /tmp/qpl-preflight` exits 0 | HALT with the script's setup hint |
45
45
  | URL reachable | `curl -fsS -o /dev/null -w '%{http_code}' "$URL"` returns 2xx/3xx | HALT — start the dev server first |
@@ -91,7 +91,7 @@ node ~/.claude/skills/qualia-polish-loop/scripts/loop.mjs record \
91
91
 
92
92
  Exit codes: `0` = SUCCESS (all dims ≥ 3), `1` = CONTINUE (more iterations), `3` = KILLED (regression / budget / max).
93
93
 
94
- The orchestrator computes the verdict per `rules/design-rubric.md`:
94
+ The orchestrator computes the verdict per `qualia-design/design-rubric.md`:
95
95
 
96
96
  - **all aggregate scores ≥ 3 AND no critical issues remain** → SUCCESS, exit loop
97
97
  - **same issue fingerprint recurred 3 consecutive iterations** → KILL, `LOOP_REGRESSION_DETECTED`
@@ -1,8 +1,8 @@
1
1
  <!doctype html>
2
2
  <!--
3
3
  Deliberately broken page used by /qualia-polish-loop self-test Scenario 2.
4
- Hits multiple absolute-ban patterns from rules/design-laws.md and
5
- rules/design-brand.md so the vision evaluator has to identify them all.
4
+ Hits multiple absolute-ban patterns from qualia-design/design-laws.md and
5
+ qualia-design/design-brand.md so the vision evaluator has to identify them all.
6
6
  Banned font (Inter), pure white + pure black, blue-purple gradient,
7
7
  gradient text, identical 3-column card grid, "Get Started" / "Learn More"
8
8
  generic CTAs, side-stripe border-left:4px decorative, max-width:1280