qualia-framework 6.2.9 → 6.2.10

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 (72) hide show
  1. package/README.md +14 -11
  2. package/agents/builder.md +7 -7
  3. package/agents/planner.md +39 -3
  4. package/agents/research-synthesizer.md +1 -1
  5. package/agents/researcher.md +3 -3
  6. package/agents/roadmapper.md +7 -7
  7. package/agents/verifier.md +18 -6
  8. package/agents/visual-evaluator.md +8 -7
  9. package/bin/cli.js +111 -14
  10. package/bin/contract-runner.js +219 -0
  11. package/bin/host-adapters.js +66 -0
  12. package/bin/install.js +99 -152
  13. package/bin/plan-contract.js +99 -2
  14. package/bin/planning-hygiene.js +262 -0
  15. package/bin/runtime-manifest.js +32 -0
  16. package/bin/state-ledger.js +184 -0
  17. package/bin/state.js +299 -20
  18. package/bin/trust-score.js +276 -0
  19. package/docs/onboarding.html +5 -4
  20. package/guide.md +3 -2
  21. package/package.json +1 -1
  22. package/qualia-design/design-rubric.md +17 -5
  23. package/qualia-design/frontend.md +5 -1
  24. package/qualia-design/graphics.md +47 -0
  25. package/rules/command-output.md +35 -0
  26. package/skills/qualia/SKILL.md +10 -10
  27. package/skills/qualia-build/SKILL.md +20 -14
  28. package/skills/qualia-debug/SKILL.md +16 -8
  29. package/skills/qualia-discuss/SKILL.md +10 -10
  30. package/skills/qualia-doctor/SKILL.md +140 -0
  31. package/skills/qualia-feature/SKILL.md +23 -21
  32. package/skills/qualia-fix/SKILL.md +216 -0
  33. package/skills/qualia-flush/SKILL.md +9 -9
  34. package/skills/qualia-handoff/SKILL.md +9 -9
  35. package/skills/qualia-help/SKILL.md +3 -3
  36. package/skills/qualia-hook-gen/SKILL.md +1 -1
  37. package/skills/qualia-idk/SKILL.md +4 -4
  38. package/skills/qualia-issues/SKILL.md +2 -2
  39. package/skills/qualia-learn/SKILL.md +10 -10
  40. package/skills/qualia-map/SKILL.md +2 -2
  41. package/skills/qualia-milestone/SKILL.md +15 -15
  42. package/skills/qualia-new/REFERENCE.md +9 -9
  43. package/skills/qualia-new/SKILL.md +14 -14
  44. package/skills/qualia-optimize/REFERENCE.md +1 -1
  45. package/skills/qualia-optimize/SKILL.md +23 -16
  46. package/skills/qualia-pause/SKILL.md +2 -2
  47. package/skills/qualia-plan/SKILL.md +23 -13
  48. package/skills/qualia-polish/REFERENCE.md +14 -14
  49. package/skills/qualia-polish/SKILL.md +64 -19
  50. package/skills/qualia-polish/scripts/loop.mjs +3 -3
  51. package/skills/qualia-polish/scripts/score.mjs +9 -3
  52. package/skills/qualia-postmortem/SKILL.md +9 -9
  53. package/skills/qualia-report/SKILL.md +23 -23
  54. package/skills/qualia-research/SKILL.md +5 -5
  55. package/skills/qualia-resume/SKILL.md +4 -4
  56. package/skills/qualia-review/SKILL.md +28 -12
  57. package/skills/qualia-road/SKILL.md +18 -5
  58. package/skills/qualia-ship/SKILL.md +22 -22
  59. package/skills/qualia-skill-new/SKILL.md +13 -13
  60. package/skills/qualia-test/SKILL.md +5 -5
  61. package/skills/qualia-triage/SKILL.md +1 -1
  62. package/skills/qualia-verify/SKILL.md +37 -23
  63. package/skills/qualia-vibe/SKILL.md +13 -10
  64. package/skills/qualia-vibe/scripts/extract.mjs +1 -1
  65. package/skills/zoho-workflow/SKILL.md +1 -1
  66. package/templates/help.html +12 -10
  67. package/tests/bin.test.sh +34 -4
  68. package/tests/install-smoke.test.sh +22 -2
  69. package/tests/lib.test.sh +290 -0
  70. package/tests/runner.js +3 -0
  71. package/tests/skills.test.sh +4 -4
  72. package/tests/state.test.sh +65 -3
@@ -24,11 +24,11 @@ This is not a task-completion ceremony. The report records what happened during
24
24
  ### Step 0 — Pre-flight (graceful)
25
25
 
26
26
  ```bash
27
- node ~/.claude/bin/qualia-ui.js banner report
27
+ node ${QUALIA_BIN}/qualia-ui.js banner report
28
28
 
29
29
  # Sanity checks — soft failures only, never block the report
30
- test -d .git || node ~/.claude/bin/qualia-ui.js warn "Not a git repo — local commit will be skipped, ERP upload will still try"
31
- test -f .planning/tracking.json || node ~/.claude/bin/qualia-ui.js warn "No tracking.json yet — ERP payload will use defaults"
30
+ test -d .git || node ${QUALIA_BIN}/qualia-ui.js warn "Not a git repo — local commit will be skipped, ERP upload will still try"
31
+ test -f .planning/tracking.json || node ${QUALIA_BIN}/qualia-ui.js warn "No tracking.json yet — ERP payload will use defaults"
32
32
 
33
33
  DRY_RUN="${DRY_RUN:-false}"
34
34
  echo "$ARGUMENTS" | grep -q -- '--dry-run' && DRY_RUN="true"
@@ -101,11 +101,11 @@ Per-project sequential ID (QS-REPORT-01, 02, ...). State.js owns the counter —
101
101
  ```bash
102
102
  PEEK=""
103
103
  [ "$DRY_RUN" = "true" ] && PEEK="--peek"
104
- CLIENT_REPORT_ID=$(node ~/.claude/bin/state.js next-report-id $PEEK 2>/dev/null \
104
+ CLIENT_REPORT_ID=$(node ${QUALIA_BIN}/state.js next-report-id $PEEK 2>/dev/null \
105
105
  | node -e "try{const j=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write(j.report_id||'')}catch{}")
106
106
 
107
107
  if [ -z "$CLIENT_REPORT_ID" ]; then
108
- node ~/.claude/bin/qualia-ui.js fail "Could not allocate report ID. Try: cat .planning/tracking.json (is it valid JSON?)"
108
+ node ${QUALIA_BIN}/qualia-ui.js fail "Could not allocate report ID. Try: cat .planning/tracking.json (is it valid JSON?)"
109
109
  exit 1
110
110
  fi
111
111
  ```
@@ -116,10 +116,10 @@ fi
116
116
  if [ "$DRY_RUN" != "true" ] && [ -d .git ]; then
117
117
  mkdir -p .planning/reports
118
118
  git add .planning/reports/report-{date}.md .planning/tracking.json
119
- git commit -m "report: $CLIENT_REPORT_ID session {YYYY-MM-DD}" || node ~/.claude/bin/qualia-ui.js warn "Nothing to commit (clean tree?)"
119
+ git commit -m "report: $CLIENT_REPORT_ID session {YYYY-MM-DD}" || node ${QUALIA_BIN}/qualia-ui.js warn "Nothing to commit (clean tree?)"
120
120
  git push 2>&1 | tail -3
121
121
  PUSH_EXIT=${PIPESTATUS[0]}
122
- [ "$PUSH_EXIT" != "0" ] && node ~/.claude/bin/qualia-ui.js warn "git push failed — report committed locally but not pushed. ERP upload will still try."
122
+ [ "$PUSH_EXIT" != "0" ] && node ${QUALIA_BIN}/qualia-ui.js warn "git push failed — report committed locally but not pushed. ERP upload will still try."
123
123
  fi
124
124
  ```
125
125
 
@@ -136,12 +136,12 @@ The full payload-builder + 3-attempt-retry logic lives unchanged from v4 — see
136
136
 
137
137
  ```bash
138
138
  if [ "$DRY_RUN" != "true" ]; then
139
- node ~/.claude/bin/state.js transition --to activity --notes "Session report $CLIENT_REPORT_ID generated" 2>/dev/null
139
+ node ${QUALIA_BIN}/state.js transition --to activity --notes "Session report $CLIENT_REPORT_ID generated" 2>/dev/null
140
140
  fi
141
141
 
142
- node ~/.claude/bin/qualia-ui.js divider
143
- node ~/.claude/bin/qualia-ui.js ok "Report $CLIENT_REPORT_ID complete."
144
- node ~/.claude/bin/qualia-ui.js info "Shift report submitted. You can clock out now."
142
+ node ${QUALIA_BIN}/qualia-ui.js divider
143
+ node ${QUALIA_BIN}/qualia-ui.js ok "Report $CLIENT_REPORT_ID complete."
144
+ node ${QUALIA_BIN}/qualia-ui.js info "Shift report submitted. You can clock out now."
145
145
  ```
146
146
 
147
147
  ## Common errors (read this when something goes wrong)
@@ -149,7 +149,7 @@ node ~/.claude/bin/qualia-ui.js info "Shift report submitted. You can clock out
149
149
  | Symptom | Likely cause | Self-service fix |
150
150
  |---|---|---|
151
151
  | "Could not allocate report ID" | tracking.json missing/corrupt | `cat .planning/tracking.json` to inspect, or restore from `git checkout HEAD -- .planning/tracking.json` |
152
- | "ERP API key missing" | `~/.claude/.erp-api-key` empty | `printf '%s' "$QUALIA_ERP_KEY" \| qualia-framework set-erp-key` (ask Fawzi for the key) |
152
+ | "ERP API key missing" | `${QUALIA_HOME}/.erp-api-key` empty | `printf '%s' "$QUALIA_ERP_KEY" \| qualia-framework set-erp-key` (ask Fawzi for the key) |
153
153
  | "ERP auth failed (401)" | Key revoked or wrong | Ask Fawzi for a fresh key |
154
154
  | "ERP upload failed after 3 attempts" | ERP down or network issue | Local commit is safe. Re-run `/qualia-report` later. |
155
155
  | "git push failed" | Auth or network or upstream issue | `git push` manually, see the error, fix, re-run |
@@ -163,7 +163,7 @@ The Step 6 payload + retry logic. Inlined to avoid a script-file fetch on every
163
163
  ERP_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.claude/.qualia-config.json','utf8'));console.log(c.erp?.url||'https://portal.qualiasolutions.net')}catch{console.log('https://portal.qualiasolutions.net')}")
164
164
  ERP_ENABLED=$(node -e "try{const c=JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.claude/.qualia-config.json','utf8'));console.log(c.erp?.enabled!==false)}catch{console.log('true')}")
165
165
 
166
- API_KEY=$(cat ~/.claude/.erp-api-key 2>/dev/null)
166
+ API_KEY=$(cat ${QUALIA_HOME}/.erp-api-key 2>/dev/null)
167
167
  REPORT_FILE=".planning/reports/report-{date}.md"
168
168
  SUBMITTED_BY=$(git config user.name || echo "unknown")
169
169
  SUBMITTED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
@@ -181,7 +181,7 @@ IDEMPOTENCY_KEY=$(node -e "
181
181
 
182
182
  # Guard: API key required for upload (otherwise curl posts an empty bearer)
183
183
  if [ "$ERP_ENABLED" = "true" ] && [ -z "$API_KEY" ] && [ "$DRY_RUN" != "true" ]; then
184
- node ~/.claude/bin/qualia-ui.js warn "ERP API key missing (~/.claude/.erp-api-key). Run: printf '%s' \"\$QUALIA_ERP_KEY\" | qualia-framework set-erp-key"
184
+ node ${QUALIA_BIN}/qualia-ui.js warn "ERP API key missing (${QUALIA_HOME}/.erp-api-key). Run: printf '%s' \"\$QUALIA_ERP_KEY\" | qualia-framework set-erp-key"
185
185
  ERP_ENABLED="false"
186
186
  fi
187
187
 
@@ -190,7 +190,7 @@ fi
190
190
  PAYLOAD=$(
191
191
  SUBMITTED_BY="$SUBMITTED_BY" SUBMITTED_AT="$SUBMITTED_AT" \
192
192
  CLIENT_REPORT_ID="$CLIENT_REPORT_ID" REPORT_FILE="$REPORT_FILE" \
193
- node ~/.claude/bin/report-payload.js
193
+ node ${QUALIA_BIN}/report-payload.js
194
194
  )
195
195
 
196
196
  # --dry-run: print and stop
@@ -216,19 +216,19 @@ if [ "$ERP_ENABLED" = "true" ]; then
216
216
 
217
217
  if [ "$HTTP_CODE" = "200" ]; then
218
218
  ERP_REPORT_ID=$(echo "$BODY" | node -e "try{process.stdout.write(JSON.parse(require('fs').readFileSync(0,'utf8')).report_id||'')}catch{}")
219
- node ~/.claude/bin/qualia-ui.js ok "Uploaded as $CLIENT_REPORT_ID (ERP: ${ERP_REPORT_ID:-none})"
219
+ node ${QUALIA_BIN}/qualia-ui.js ok "Uploaded as $CLIENT_REPORT_ID (ERP: ${ERP_REPORT_ID:-none})"
220
220
  break
221
221
  fi
222
222
  if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "422" ]; then
223
- node ~/.claude/bin/qualia-ui.js warn "ERP rejected ($HTTP_CODE) — $([ "$HTTP_CODE" = "401" ] && echo "API key invalid, ask Fawzi" || echo "schema mismatch:")"
223
+ node ${QUALIA_BIN}/qualia-ui.js warn "ERP rejected ($HTTP_CODE) — $([ "$HTTP_CODE" = "401" ] && echo "API key invalid, ask Fawzi" || echo "schema mismatch:")"
224
224
  [ "$HTTP_CODE" = "422" ] && echo "$BODY" | head -3
225
225
  break
226
226
  fi
227
- [ $ATTEMPT -lt 3 ] && { SLEEP=$((1 * 3 ** (ATTEMPT - 1))); node ~/.claude/bin/qualia-ui.js warn "Attempt $ATTEMPT failed (HTTP ${HTTP_CODE:-timeout}), retrying in ${SLEEP}s..."; sleep $SLEEP; }
227
+ [ $ATTEMPT -lt 3 ] && { SLEEP=$((1 * 3 ** (ATTEMPT - 1))); node ${QUALIA_BIN}/qualia-ui.js warn "Attempt $ATTEMPT failed (HTTP ${HTTP_CODE:-timeout}), retrying in ${SLEEP}s..."; sleep $SLEEP; }
228
228
  done
229
229
 
230
230
  # If all 3 in-process attempts failed, enqueue the report into the persistent
231
- # retry queue (~/.claude/.erp-retry-queue.json). session-start.js drains it on
231
+ # retry queue (${QUALIA_HOME}/.erp-retry-queue.json). session-start.js drains it on
232
232
  # the next Claude Code launch; `qualia-framework erp-flush` drains it on demand.
233
233
  # This replaces the prior "will appear after retry" message which was a lie —
234
234
  # no retry mechanism existed before v5.9.
@@ -256,13 +256,13 @@ if [ "$ERP_ENABLED" = "true" ]; then
256
256
  process.exit(1);
257
257
  }
258
258
  " 2>/dev/null && {
259
- node ~/.claude/bin/qualia-ui.js warn "ERP upload failed after 3 attempts — $CLIENT_REPORT_ID enqueued for auto-retry on next session"
260
- node ~/.claude/bin/qualia-ui.js info "Drain manually with: qualia-framework erp-flush"
259
+ node ${QUALIA_BIN}/qualia-ui.js warn "ERP upload failed after 3 attempts — $CLIENT_REPORT_ID enqueued for auto-retry on next session"
260
+ node ${QUALIA_BIN}/qualia-ui.js info "Drain manually with: qualia-framework erp-flush"
261
261
  } || {
262
- node ~/.claude/bin/qualia-ui.js warn "ERP upload failed after 3 attempts AND queue enqueue failed. $CLIENT_REPORT_ID is committed locally — re-run /qualia-report later to retry."
262
+ node ${QUALIA_BIN}/qualia-ui.js warn "ERP upload failed after 3 attempts AND queue enqueue failed. $CLIENT_REPORT_ID is committed locally — re-run /qualia-report later to retry."
263
263
  }
264
264
  fi
265
265
  fi
266
266
 
267
- [ "$ERP_ENABLED" != "true" ] && node ~/.claude/bin/qualia-ui.js info "ERP upload skipped (disabled). $CLIENT_REPORT_ID committed locally."
267
+ [ "$ERP_ENABLED" != "true" ] && node ${QUALIA_BIN}/qualia-ui.js info "ERP upload skipped (disabled). $CLIENT_REPORT_ID committed locally."
268
268
  ```
@@ -30,7 +30,7 @@ Targeted research on domain, library, or integration for a specific phase. Narro
30
30
  ### 1. Determine Phase
31
31
 
32
32
  ```bash
33
- node ~/.claude/bin/state.js check 2>/dev/null
33
+ node ${QUALIA_BIN}/state.js check 2>/dev/null
34
34
  ```
35
35
 
36
36
  Phase N from args, or current phase from STATE.md.
@@ -55,7 +55,7 @@ Wait for answer. Answer defines research question.
55
55
 
56
56
  ```
57
57
  Agent(prompt="
58
- Role: @~/.claude/agents/researcher.md
58
+ Role: @${QUALIA_AGENTS}/researcher.md
59
59
 
60
60
  <dimension>phase-specific</dimension>
61
61
 
@@ -86,8 +86,8 @@ Include: recommendation, rationale, versions, code examples, alternatives, pitfa
86
86
  Read `.planning/phase-{N}-research.md`. Present findings:
87
87
 
88
88
  ```bash
89
- node ~/.claude/bin/qualia-ui.js divider
90
- node ~/.claude/bin/qualia-ui.js ok "Research complete"
89
+ node ${QUALIA_BIN}/qualia-ui.js divider
90
+ node ${QUALIA_BIN}/qualia-ui.js ok "Research complete"
91
91
  ```
92
92
 
93
93
  Show:
@@ -116,7 +116,7 @@ git commit -m "docs(phase-{N}): research findings"
116
116
  ### 8. Route
117
117
 
118
118
  ```bash
119
- node ~/.claude/bin/qualia-ui.js end "PHASE {N} RESEARCH DONE" "/qualia-plan {N}"
119
+ node ${QUALIA_BIN}/qualia-ui.js end "PHASE {N} RESEARCH DONE" "/qualia-plan {N}"
120
120
  ```
121
121
 
122
122
  ## Rules
@@ -35,18 +35,18 @@ Restore context and route to the right next action.
35
35
  ### 4. Present and Route
36
36
 
37
37
  ```bash
38
- node ~/.claude/bin/qualia-ui.js banner resume
39
- node ~/.claude/bin/qualia-ui.js info "Last session: {summary}"
38
+ node ${QUALIA_BIN}/qualia-ui.js banner resume
39
+ node ${QUALIA_BIN}/qualia-ui.js info "Last session: {summary}"
40
40
  ```
41
41
 
42
42
  If uncommitted changes:
43
43
  ```bash
44
- node ~/.claude/bin/qualia-ui.js warn "{N} uncommitted files"
44
+ node ${QUALIA_BIN}/qualia-ui.js warn "{N} uncommitted files"
45
45
  ```
46
46
 
47
47
  End with the next command:
48
48
  ```bash
49
- node ~/.claude/bin/qualia-ui.js next "{next command}"
49
+ node ${QUALIA_BIN}/qualia-ui.js next "{next command}"
50
50
  ```
51
51
 
52
52
  Clean up `.continue-here.md` after restoration (or offer to keep it).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: qualia-review
3
- description: "Production audit with scored diagnostics. Runs real commands, scores findings by severity. Trigger on 'review', 'audit', 'code review', 'security check', 'production check'."
3
+ description: "Read-only production audit with scored diagnostics. Runs real commands, scores findings by severity, writes REVIEW.md, and routes repair work to /qualia-fix, /qualia-polish, or /qualia-optimize. Trigger on 'review', 'audit', 'code review', 'security check', 'production check'."
4
4
  allowed-tools:
5
5
  - Bash
6
6
  - Read
@@ -14,6 +14,15 @@ allowed-tools:
14
14
 
15
15
  Runs real diagnostic commands and scores every finding. Not a checklist — an executable audit.
16
16
 
17
+ Review is detection only. It never patches code. If the user wants the findings repaired, route by finding type:
18
+
19
+ | Finding type | Next command |
20
+ |---|---|
21
+ | Broken existing behavior, failing test, security leak, config error | `/qualia-fix` |
22
+ | Visual design quality or responsive polish | `/qualia-polish` |
23
+ | Broad performance, architecture, or alignment opportunities | `/qualia-optimize` |
24
+ | New missing capability | `/qualia-feature` or `/qualia-plan` |
25
+
17
26
  ## Usage
18
27
 
19
28
  - `/qualia-review` — Full audit (security + quality + performance)
@@ -23,15 +32,15 @@ Runs real diagnostic commands and scores every finding. Not a checklist — an e
23
32
  ## Process
24
33
 
25
34
  ```bash
26
- node ~/.claude/bin/qualia-ui.js banner review
35
+ node ${QUALIA_BIN}/qualia-ui.js banner review
27
36
  ```
28
37
 
29
38
  ### 0. Load Context
30
39
 
31
40
  ```bash
32
- node ~/.claude/bin/knowledge.js
33
- node ~/.claude/bin/knowledge.js load fixes
34
- node ~/.claude/bin/knowledge.js load patterns
41
+ node ${QUALIA_BIN}/knowledge.js
42
+ node ${QUALIA_BIN}/knowledge.js load fixes
43
+ node ${QUALIA_BIN}/knowledge.js load patterns
35
44
  ```
36
45
 
37
46
  Detect project shape:
@@ -127,7 +136,11 @@ grep -rn "const.*=.*await" --include="*.tsx" --include="*.ts" app/ src/ 2>/dev/n
127
136
 
128
137
  ### 4. Score and Report
129
138
 
130
- Write to `.planning/REVIEW.md`:
139
+ Create the report directory and write to `.planning/reports/review/REVIEW.md`:
140
+
141
+ ```bash
142
+ mkdir -p .planning/reports/review
143
+ ```
131
144
 
132
145
  ```markdown
133
146
  # Production Review — {YYYY-MM-DD}
@@ -156,6 +169,9 @@ Write to `.planning/REVIEW.md`:
156
169
 
157
170
  ## Verdict
158
171
  {PASS: no critical/high | FAIL: N blockers — fix before /qualia-ship}
172
+
173
+ ## Recommended Next Command
174
+ {`/qualia-fix`, `/qualia-polish`, `/qualia-optimize`, `/qualia-feature`, or `none`} — {one-line reason}
159
175
  ```
160
176
 
161
177
  **Scoring (deterministic — see `rules/grounding.md` for full rubric):**
@@ -173,11 +189,11 @@ Quick reference (computed from the formula — verified):
173
189
  - 4+ CRITICAL → 1
174
190
 
175
191
  ```bash
176
- node ~/.claude/bin/qualia-ui.js divider
177
- node ~/.claude/bin/qualia-ui.js info "Security: {score}/5 ({n} findings)"
178
- node ~/.claude/bin/qualia-ui.js info "Quality: {score}/5 ({n} findings)"
179
- node ~/.claude/bin/qualia-ui.js info "Perf: {score}/5 ({n} findings)"
180
- node ~/.claude/bin/qualia-ui.js end "REVIEW: {PASS|FAIL}" "{next command}"
192
+ node ${QUALIA_BIN}/qualia-ui.js divider
193
+ node ${QUALIA_BIN}/qualia-ui.js info "Security: {score}/5 ({n} findings)"
194
+ node ${QUALIA_BIN}/qualia-ui.js info "Quality: {score}/5 ({n} findings)"
195
+ node ${QUALIA_BIN}/qualia-ui.js info "Perf: {score}/5 ({n} findings)"
196
+ node ${QUALIA_BIN}/qualia-ui.js end "REVIEW: {PASS|FAIL}" "{recommended next command}"
181
197
  ```
182
198
 
183
199
  ## Rules
@@ -185,5 +201,5 @@ node ~/.claude/bin/qualia-ui.js end "REVIEW: {PASS|FAIL}" "{next command}"
185
201
  1. **Run every command.** Don't skip scans because "the code looks clean."
186
202
  2. **Every finding gets a severity.** No prose — CRITICAL/HIGH/MEDIUM/LOW.
187
203
  3. **Every finding gets a fix suggestion.** Not just "this is bad" — say what to do.
188
- 4. **Review detects. It does NOT fix.** This is an audit, not a refactor. Tell the user what to fix.
204
+ 4. **Review detects. It does NOT fix.** This is an audit, not a refactor. Route repair to `/qualia-fix`, design repair to `/qualia-polish`, and broad improvement to `/qualia-optimize`.
189
205
  5. **CRITICAL or HIGH = deploy blocker.** `/qualia-ship` checks for these.
@@ -33,14 +33,14 @@ Done.
33
33
  ```
34
34
 
35
35
  ## Design as a thread
36
- Every road agent loads `PRODUCT.md + DESIGN.md + design-laws.md` substrate. Builders run `slop-detect` on every frontend commit. Verifiers score 8 design dimensions per phase.
36
+ Every road agent loads `PRODUCT.md + DESIGN.md + design-laws.md` substrate. Builders run `slop-detect` on every frontend commit. Verifiers score 9 design dimensions per phase, including visual system and graphics.
37
37
 
38
38
  ## /qualia-polish is scope-adaptive
39
39
  ```
40
40
  /qualia-polish src/components/Button.tsx ~30s component touch-up
41
41
  /qualia-polish app/dashboard ~3m section pass
42
42
  /qualia-polish ~12m whole app, fan-out
43
- /qualia-polish --redesign ~30m ground-up redesign
43
+ /qualia-polish --redesign ~30m ground-up redesign + complex visual concept
44
44
  /qualia-polish --critique read-only scored audit
45
45
  /qualia-polish --quick ~1m gates only
46
46
  ```
@@ -65,7 +65,7 @@ Every road agent loads `PRODUCT.md + DESIGN.md + design-laws.md` substrate. Buil
65
65
  /qualia-polish --loop {url} --reduced-motion force prefers-reduced-motion
66
66
  /qualia-polish --loop --routes /a,/b,/c multi-route sweep
67
67
  ```
68
- Screenshots at 3 viewports (375/768/1440), scores 8 design dimensions using vision, fixes issues, re-screenshots, loops until all dims >= 3 or kill-switch triggers. Per-iteration git commits for clean revert.
68
+ Screenshots at 3 viewports (375/768/1440), scores 9 design dimensions using vision, fixes issues, re-screenshots, loops until all dims >= 3 or kill-switch triggers. Per-iteration git commits for clean revert.
69
69
 
70
70
  ## Deterministic-enforcement skills
71
71
  ```
@@ -90,14 +90,27 @@ Before high-stakes phases, run alignment skills against `.planning/CONTEXT.md` (
90
90
  ## Auxiliary commands
91
91
  ```
92
92
  Lost? → /qualia (state router — tells you the next command)
93
+ Health? → /qualia-doctor (install, state, contracts, memory, ERP queue)
93
94
  Stuck/weird? → /qualia-idk (diagnostic — spawns plan-view + code-view agents in parallel)
94
- Single feature? → /qualia-feature (auto-scoped: inline for trivia, fresh spawn for 1-5 files)
95
+ Broken thing? → /qualia-fix (root cause, minimal patch, verify, report)
96
+ Single feature? → /qualia-feature (new capability: inline for trivia, fresh spawn for 1-5 files)
95
97
  Paused? → /qualia-resume (restore from .continue-here.md or STATE.md)
96
98
  End of day? → /qualia-report (mandatory before clock-out; writes ERP payload)
97
- Debug bug? → /qualia-debug (feedback-loop-first investigation)
99
+ Debug why? → /qualia-debug (feedback-loop-first investigation when evidence is unclear)
98
100
  Unsure plan? → /qualia-discuss (capture decisions before planning)
99
101
  ```
100
102
 
103
+ ## Outside-road command boundaries
104
+ ```
105
+ Need a repair? → /qualia-fix (mutates code, proves fix)
106
+ Need an investigation? → /qualia-debug (evidence first, no guessing)
107
+ Need an audit? → /qualia-review (detect-only, scored findings)
108
+ Need improvement map? → /qualia-optimize (report/RFC, broad opportunities)
109
+ Need visual quality? → /qualia-polish (style/layout/accessibility)
110
+ Need new aesthetic? → /qualia-vibe (tokens only, layout preserved)
111
+ Need new capability? → /qualia-feature (small net-new work)
112
+ ```
113
+
101
114
  ## Human gates
102
115
  Journey approval after `/qualia-new`, then one at each milestone boundary via `/qualia-milestone`. `--auto` runs everything between gates automatically.
103
116
 
@@ -16,7 +16,7 @@ Full deployment pipeline with quality gates.
16
16
  ## Process
17
17
 
18
18
  ```bash
19
- node ~/.claude/bin/qualia-ui.js banner ship
19
+ node ${QUALIA_BIN}/qualia-ui.js banner ship
20
20
  ```
21
21
 
22
22
  ### 0. State Guard — refuse to ship from an invalid state
@@ -24,9 +24,9 @@ node ~/.claude/bin/qualia-ui.js banner ship
24
24
  `/qualia-ship` is a terminal operation — it writes a deployed tag, bumps counters, and produces a verified URL. It must NEVER run on an unpolished, unverified, or malformed project.
25
25
 
26
26
  ```bash
27
- STATE=$(node ~/.claude/bin/state.js check 2>/dev/null)
27
+ STATE=$(node ${QUALIA_BIN}/state.js check 2>/dev/null)
28
28
  if [ -z "$STATE" ]; then
29
- node ~/.claude/bin/qualia-ui.js fail "No project loaded. Run /qualia-new first or cd to a Qualia-managed project."
29
+ node ${QUALIA_BIN}/qualia-ui.js fail "No project loaded. Run /qualia-new first or cd to a Qualia-managed project."
30
30
  exit 1
31
31
  fi
32
32
 
@@ -39,11 +39,11 @@ VERIFICATION=$(echo "$STATE" | node -e "try{const d=JSON.parse(require('fs').rea
39
39
  # Anything else (setup, planned, built, shipped, handed_off, verified+fail) is refused.
40
40
  if [ "$STATUS" != "polished" ] && ! { [ "$STATUS" = "verified" ] && [ "$VERIFICATION" = "pass" ]; }; then
41
41
  if [ "${QUALIA_SHIP_FORCE:-0}" = "1" ]; then
42
- node ~/.claude/bin/qualia-ui.js warn "Forced ship from state '$STATUS' (verification: ${VERIFICATION:-none}). Record the reason in the final report."
42
+ node ${QUALIA_BIN}/qualia-ui.js warn "Forced ship from state '$STATUS' (verification: ${VERIFICATION:-none}). Record the reason in the final report."
43
43
  else
44
- node ~/.claude/bin/qualia-ui.js fail "Cannot ship from state '$STATUS' (verification: ${VERIFICATION:-none})."
45
- node ~/.claude/bin/qualia-ui.js info "Run /qualia-polish first, or /qualia-verify {phase} if verification is still pending."
46
- node ~/.claude/bin/qualia-ui.js info "Hotfix override: set QUALIA_SHIP_FORCE=1 only when the user explicitly approved it."
44
+ node ${QUALIA_BIN}/qualia-ui.js fail "Cannot ship from state '$STATUS' (verification: ${VERIFICATION:-none})."
45
+ node ${QUALIA_BIN}/qualia-ui.js info "Run /qualia-polish first, or /qualia-verify {phase} if verification is still pending."
46
+ node ${QUALIA_BIN}/qualia-ui.js info "Hotfix override: set QUALIA_SHIP_FORCE=1 only when the user explicitly approved it."
47
47
  exit 1
48
48
  fi
49
49
  fi
@@ -76,7 +76,7 @@ SEC_FAIL=0
76
76
  # CRITICAL: service_role in client-facing code
77
77
  HITS=$(grep -rn "service_role" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | grep -v "\.server\.\|[\\/]server[\\/]\|[\\/]app[\\/]api[\\/]\|route\.\|middleware\.")
78
78
  if [ -n "$HITS" ]; then
79
- node ~/.claude/bin/qualia-ui.js fail "service_role leaked to client code:"
79
+ node ${QUALIA_BIN}/qualia-ui.js fail "service_role leaked to client code:"
80
80
  echo "$HITS" | head -5
81
81
  SEC_FAIL=1
82
82
  fi
@@ -84,7 +84,7 @@ fi
84
84
  # CRITICAL: hardcoded secrets
85
85
  HITS=$(grep -rn "sk_live\|sk_test\|SUPABASE_SERVICE_ROLE\|eyJhbGciOi" --include="*.ts" --include="*.tsx" --include="*.js" app/ components/ src/ lib/ 2>/dev/null | grep -v node_modules | grep -v "\.env")
86
86
  if [ -n "$HITS" ]; then
87
- node ~/.claude/bin/qualia-ui.js fail "Hardcoded secret found:"
87
+ node ${QUALIA_BIN}/qualia-ui.js fail "Hardcoded secret found:"
88
88
  echo "$HITS" | head -5
89
89
  SEC_FAIL=1
90
90
  fi
@@ -92,7 +92,7 @@ fi
92
92
  # CRITICAL: dangerouslySetInnerHTML / eval
93
93
  HITS=$(grep -rn "dangerouslySetInnerHTML\|eval(" --include="*.ts" --include="*.tsx" --include="*.js" app/ components/ src/ 2>/dev/null | grep -v node_modules)
94
94
  if [ -n "$HITS" ]; then
95
- node ~/.claude/bin/qualia-ui.js fail "Dangerous innerHTML/eval pattern:"
95
+ node ${QUALIA_BIN}/qualia-ui.js fail "Dangerous innerHTML/eval pattern:"
96
96
  echo "$HITS" | head -5
97
97
  SEC_FAIL=1
98
98
  fi
@@ -100,13 +100,13 @@ fi
100
100
  # CRITICAL: .env files tracked in git
101
101
  HITS=$(git ls-files | grep -i "\.env" | grep -v "\.example\|\.template\|\.sample")
102
102
  if [ -n "$HITS" ]; then
103
- node ~/.claude/bin/qualia-ui.js fail ".env files tracked in git:"
103
+ node ${QUALIA_BIN}/qualia-ui.js fail ".env files tracked in git:"
104
104
  echo "$HITS"
105
105
  SEC_FAIL=1
106
106
  fi
107
107
 
108
108
  if [ $SEC_FAIL -ne 0 ]; then
109
- node ~/.claude/bin/qualia-ui.js fail "Security check failed. Fix findings above or run /qualia-review for full audit."
109
+ node ${QUALIA_BIN}/qualia-ui.js fail "Security check failed. Fix findings above or run /qualia-review for full audit."
110
110
  exit 1
111
111
  fi
112
112
  ```
@@ -140,8 +140,8 @@ Read the deployed URL from `tracking.json.deployed_url` or from an explicit user
140
140
  # exact value before running this block. Otherwise use tracking.json.
141
141
  URL="${QUALIA_SHIP_URL:-$(node -e 'try{const t=JSON.parse(require("fs").readFileSync(".planning/tracking.json","utf8"));process.stdout.write(t.deployed_url||"")}catch{}')}"
142
142
  if [ -z "$URL" ]; then
143
- node ~/.claude/bin/qualia-ui.js warn "No deployed_url in tracking.json — parse it from the deploy command output (vercel/supabase/wrangler all print the URL on success)."
144
- node ~/.claude/bin/qualia-ui.js info "Re-run with: /qualia-ship --url https://your-site.com, then export that value as QUALIA_SHIP_URL for this check."
143
+ node ${QUALIA_BIN}/qualia-ui.js warn "No deployed_url in tracking.json — parse it from the deploy command output (vercel/supabase/wrangler all print the URL on success)."
144
+ node ${QUALIA_BIN}/qualia-ui.js info "Re-run with: /qualia-ship --url https://your-site.com, then export that value as QUALIA_SHIP_URL for this check."
145
145
  exit 1
146
146
  fi
147
147
 
@@ -151,7 +151,7 @@ HTTP_CODE=$(echo "$RESP" | awk '{print $1}')
151
151
  LATENCY=$(echo "$RESP" | awk '{print $2}')
152
152
 
153
153
  if [ "$HTTP_CODE" != "200" ]; then
154
- node ~/.claude/bin/qualia-ui.js fail "Post-deploy check failed: HTTP $HTTP_CODE at $URL"
154
+ node ${QUALIA_BIN}/qualia-ui.js fail "Post-deploy check failed: HTTP $HTTP_CODE at $URL"
155
155
  exit 1
156
156
  fi
157
157
 
@@ -162,18 +162,18 @@ AUTH_CODE=$(curl -sS -o /dev/null -w "%{http_code}" --max-time 10 "$URL/api/auth
162
162
  ### 6. Report
163
163
 
164
164
  ```bash
165
- node ~/.claude/bin/qualia-ui.js divider
166
- node ~/.claude/bin/qualia-ui.js ok "URL: $URL"
167
- node ~/.claude/bin/qualia-ui.js ok "Status: HTTP $HTTP_CODE"
168
- node ~/.claude/bin/qualia-ui.js ok "Latency: ${LATENCY}s"
169
- [ "$AUTH_CODE" = "200" ] || [ "$AUTH_CODE" = "401" ] && node ~/.claude/bin/qualia-ui.js ok "Auth endpoint responds (HTTP $AUTH_CODE)"
165
+ node ${QUALIA_BIN}/qualia-ui.js divider
166
+ node ${QUALIA_BIN}/qualia-ui.js ok "URL: $URL"
167
+ node ${QUALIA_BIN}/qualia-ui.js ok "Status: HTTP $HTTP_CODE"
168
+ node ${QUALIA_BIN}/qualia-ui.js ok "Latency: ${LATENCY}s"
169
+ [ "$AUTH_CODE" = "200" ] || [ "$AUTH_CODE" = "401" ] && node ${QUALIA_BIN}/qualia-ui.js ok "Auth endpoint responds (HTTP $AUTH_CODE)"
170
170
  ```
171
171
 
172
172
  ```bash
173
- node ~/.claude/bin/state.js transition --to shipped --deployed-url "$URL"
173
+ node ${QUALIA_BIN}/state.js transition --to shipped --deployed-url "$URL"
174
174
  ```
175
175
  Do NOT manually edit STATE.md or tracking.json — state.js handles both.
176
176
 
177
177
  ```bash
178
- node ~/.claude/bin/qualia-ui.js end "SHIPPED" "/qualia-handoff"
178
+ node ${QUALIA_BIN}/qualia-ui.js end "SHIPPED" "/qualia-handoff"
179
179
  ```
@@ -16,7 +16,7 @@ You are about to create a reusable slash command. Skills are the leverage of the
16
16
  ## Process
17
17
 
18
18
  ```bash
19
- node ~/.claude/bin/qualia-ui.js banner skill-new
19
+ node ${QUALIA_BIN}/qualia-ui.js banner skill-new
20
20
  ```
21
21
 
22
22
  ### 1. Scope Decision
@@ -30,7 +30,7 @@ options:
30
30
  - label: "Framework skill (ships to the team)"
31
31
  description: "Edit qualia-framework repo. Everyone gets it on next update."
32
32
  - label: "Local skill (just me)"
33
- description: "Lives only in ~/.claude/skills/. Not shared."
33
+ description: "Lives only in ${QUALIA_SKILLS}/. Not shared."
34
34
  - label: "Agent instead of a skill"
35
35
  description: "This is a subagent role, not a slash command. Creates agents/{name}.md."
36
36
  ```
@@ -51,11 +51,11 @@ fi
51
51
  echo "${FRAMEWORK_DIR:-UNRESOLVED}"
52
52
  ```
53
53
 
54
- If the command prints `UNRESOLVED`, ask the user: *"Where is your qualia-framework checkout? (absolute path, or type 'local' to save only to ~/.claude/)"*. If they type `local`, downgrade the scope to Local. Otherwise store the answer as `${FRAMEWORK_DIR}` for the rest of the session.
54
+ If the command prints `UNRESOLVED`, ask the user: *"Where is your qualia-framework checkout? (absolute path, or type 'local' to save only to ${QUALIA_HOME}/)"*. If they type `local`, downgrade the scope to Local. Otherwise store the answer as `${FRAMEWORK_DIR}` for the rest of the session.
55
55
 
56
56
  **Framework** → target: `${FRAMEWORK_DIR}/skills/{name}/SKILL.md`
57
- **Local** → target: `~/.claude/skills/{name}/SKILL.md`
58
- **Agent** → target: `${FRAMEWORK_DIR}/agents/{name}.md` (framework) or `~/.claude/agents/{name}.md` (local)
57
+ **Local** → target: `${QUALIA_SKILLS}/{name}/SKILL.md`
58
+ **Agent** → target: `${FRAMEWORK_DIR}/agents/{name}.md` (framework) or `${QUALIA_AGENTS}/{name}.md` (local)
59
59
 
60
60
  ### 2. Gather Requirements
61
61
 
@@ -73,13 +73,13 @@ Before writing, read two existing skills that are structurally similar:
73
73
 
74
74
  ```bash
75
75
  # Short direct-action skill reference:
76
- cat ~/.claude/skills/qualia-learn/SKILL.md
76
+ cat ${QUALIA_SKILLS}/qualia-learn/SKILL.md
77
77
 
78
78
  # Skill-that-spawns-an-agent reference:
79
- cat ~/.claude/skills/qualia-plan/SKILL.md
79
+ cat ${QUALIA_SKILLS}/qualia-plan/SKILL.md
80
80
 
81
81
  # Interactive wizard reference:
82
- cat ~/.claude/skills/qualia-new/SKILL.md
82
+ cat ${QUALIA_SKILLS}/qualia-new/SKILL.md
83
83
  ```
84
84
 
85
85
  Pick the closest pattern and copy its structure.
@@ -114,7 +114,7 @@ description: "{one sentence}. {trigger phrases}"
114
114
  ### N. Update State (only if this skill changes project state)
115
115
 
116
116
  ```bash
117
- node ~/.claude/bin/state.js transition --to {status} ...
117
+ node ${QUALIA_BIN}/state.js transition --to {status} ...
118
118
  ```
119
119
  Do NOT manually edit STATE.md or tracking.json.
120
120
  ```
@@ -131,7 +131,7 @@ Spawn a fresh subagent to simulate running the skill — does it make sense with
131
131
 
132
132
  ```
133
133
  Agent(prompt="
134
- Read this skill: @~/.claude/skills/{name}/SKILL.md
134
+ Read this skill: @${QUALIA_SKILLS}/{name}/SKILL.md
135
135
 
136
136
  Pretend the user just said '{one of the trigger phrases}'. Walk through what you would do, step by step. Flag anything ambiguous or missing.
137
137
  ", subagent_type="general-purpose", description="Test skill {name}")
@@ -143,8 +143,8 @@ Fix any ambiguity the test agent found.
143
143
 
144
144
  ```bash
145
145
  # Framework skill — copy to local .claude for immediate testing
146
- mkdir -p ~/.claude/skills/{name}
147
- cp "${FRAMEWORK_DIR}/skills/{name}/SKILL.md" ~/.claude/skills/{name}/SKILL.md
146
+ mkdir -p ${QUALIA_SKILLS}/{name}
147
+ cp "${FRAMEWORK_DIR}/skills/{name}/SKILL.md" ${QUALIA_SKILLS}/{name}/SKILL.md
148
148
 
149
149
  # Verify it parses
150
150
  node -e "const fs=require('fs');const os=require('os');const path=require('path');const c=fs.readFileSync(path.join(os.homedir(),'.claude/skills/{name}/SKILL.md'),'utf8');if(!c.includes('---'))throw new Error('missing frontmatter');if(!c.match(/^name:\s*\S/m))throw new Error('missing name');if(!c.match(/^description:\s*\S/m))throw new Error('missing description');console.log('OK')"
@@ -168,6 +168,6 @@ Remind the user to run `npx qualia-framework@latest update` on their other machi
168
168
  - ❌ **Description without triggers** — the skill won't fire
169
169
  - ❌ **Multiple commands in one skill** — split into two skills
170
170
  - ❌ **Direct file writes instead of state.js** — always use state.js for STATE.md/tracking.json
171
- - ❌ **Hardcoded project paths** — use `.planning/` relative or `~/.claude/` absolute, never `/home/specific-user/`
171
+ - ❌ **Hardcoded project paths** — use `.planning/` relative or `${QUALIA_HOME}/` absolute, never `/home/specific-user/`
172
172
  - ❌ **Skills that spawn agents without passing PROJECT.md and STATE.md context** — agents are blind by default
173
173
  - ❌ **Skills longer than ~150 lines** — split or move logic to an agent
@@ -25,7 +25,7 @@ Generate tests for client project code. Detect framework, classify targets, writ
25
25
  ## Process
26
26
 
27
27
  ```bash
28
- node ~/.claude/bin/qualia-ui.js banner test
28
+ node ${QUALIA_BIN}/qualia-ui.js banner test
29
29
  ```
30
30
 
31
31
  ### 1. Detect Test Framework
@@ -118,10 +118,10 @@ npx vitest run --coverage 2>&1 | tail -30
118
118
  ### 5. Report
119
119
 
120
120
  ```bash
121
- node ~/.claude/bin/qualia-ui.js divider
122
- node ~/.claude/bin/qualia-ui.js info "Files tested: {N}"
123
- node ~/.claude/bin/qualia-ui.js ok "Passing: {pass}/{total}"
124
- node ~/.claude/bin/qualia-ui.js end "TESTS DONE"
121
+ node ${QUALIA_BIN}/qualia-ui.js divider
122
+ node ${QUALIA_BIN}/qualia-ui.js info "Files tested: {N}"
123
+ node ${QUALIA_BIN}/qualia-ui.js ok "Passing: {pass}/{total}"
124
+ node ${QUALIA_BIN}/qualia-ui.js end "TESTS DONE"
125
125
  ```
126
126
 
127
127
  If any tests fail, show the failures and offer to fix them.
@@ -139,7 +139,7 @@ The loop continues until the queue empties or the user pauses.
139
139
  ### 7. Final report
140
140
 
141
141
  ```bash
142
- node ~/.claude/bin/qualia-ui.js end "QUEUE TRIAGED" "/qualia or /qualia-build {next}"
142
+ node ${QUALIA_BIN}/qualia-ui.js end "QUEUE TRIAGED" "/qualia or /qualia-build {next}"
143
143
  ```
144
144
 
145
145
  ## Rules