qualia-framework 5.5.0 → 5.9.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 (45) hide show
  1. package/README.md +17 -13
  2. package/agents/plan-checker.md +8 -0
  3. package/agents/qa-browser.md +7 -0
  4. package/agents/research-synthesizer.md +4 -1
  5. package/agents/researcher.md +6 -1
  6. package/agents/roadmapper.md +8 -0
  7. package/agents/verifier.md +14 -1
  8. package/agents/visual-evaluator.md +1 -1
  9. package/bin/cli.js +30 -1
  10. package/bin/erp-retry.js +289 -0
  11. package/bin/install.js +12 -6
  12. package/bin/slop-detect.mjs +1 -1
  13. package/bin/state.js +10 -1
  14. package/docs/onboarding.html +621 -0
  15. package/docs/playwright-loop-pilot-results.md +7 -5
  16. package/docs/research/2026-05-11-deep-research.md +189 -0
  17. package/guide.md +5 -6
  18. package/hooks/session-start.js +19 -1
  19. package/package.json +3 -2
  20. package/rules/speed.md +1 -2
  21. package/skills/qualia-discuss/SKILL.md +106 -6
  22. package/skills/qualia-feature/SKILL.md +216 -0
  23. package/skills/qualia-milestone/SKILL.md +73 -1
  24. package/skills/qualia-new/SKILL.md +52 -25
  25. package/skills/qualia-optimize/SKILL.md +1 -1
  26. package/skills/{qualia-polish-loop → qualia-polish}/REFERENCE.md +5 -5
  27. package/skills/qualia-polish/SKILL.md +13 -4
  28. package/skills/{qualia-polish-loop → qualia-polish}/scripts/loop.mjs +2 -2
  29. package/skills/{qualia-polish-loop → qualia-polish}/scripts/playwright-capture.mjs +1 -1
  30. package/skills/qualia-report/SKILL.md +64 -2
  31. package/skills/qualia-road/SKILL.md +10 -11
  32. package/skills/qualia-verify/SKILL.md +16 -0
  33. package/templates/help.html +2 -3
  34. package/templates/project-discovery.md +83 -0
  35. package/templates/project.md +7 -0
  36. package/tests/bin.test.sh +97 -67
  37. package/tests/refs.test.sh +146 -0
  38. package/tests/slop-detect.test.sh +2 -2
  39. package/skills/qualia-polish-loop/SKILL.md +0 -201
  40. package/skills/qualia-prd/SKILL.md +0 -199
  41. package/skills/qualia-quick/SKILL.md +0 -44
  42. package/skills/qualia-task/SKILL.md +0 -98
  43. /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/broken.html +0 -0
  44. /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/clean.html +0 -0
  45. /package/skills/{qualia-polish-loop → qualia-polish}/scripts/score.mjs +0 -0
@@ -45,23 +45,22 @@ Every road agent loads `PRODUCT.md + DESIGN.md + design-laws.md` substrate. Buil
45
45
  /qualia-polish --quick ~1m gates only
46
46
  ```
47
47
 
48
- ## /qualia-polish-loop -- autonomous visual QA (v5.1+, hardened in v5.2)
48
+ ## /qualia-polish --loop -- autonomous visual QA (v5.1+, consolidated into /qualia-polish in v5.8)
49
49
  ```
50
- /qualia-polish-loop http://localhost:3000 screenshot + eval + fix loop
51
- /qualia-polish-loop {url} --max 4 cap iterations
52
- /qualia-polish-loop {url} --ref design.png anchor to reference image
53
- /qualia-polish-loop {url} --reduced-motion force prefers-reduced-motion (v5.2+)
54
- /qualia-polish-loop --routes /a,/b,/c multi-route sweep (v5.2+)
50
+ /qualia-polish --loop http://localhost:3000 screenshot + eval + fix loop
51
+ /qualia-polish --loop {url} --max 4 cap iterations
52
+ /qualia-polish --loop {url} --ref design.png anchor to reference image
53
+ /qualia-polish --loop {url} --reduced-motion force prefers-reduced-motion
54
+ /qualia-polish --loop --routes /a,/b,/c multi-route sweep
55
55
  ```
56
56
  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.
57
57
 
58
- ## v5.3+ skills (Matt Pocock gaps closed)
58
+ ## v5.3+ skills
59
59
  ```
60
- /qualia-prd synthesize current conversation → .planning/PRD-{slug}.md (durable feature spec)
61
60
  /qualia-hook-gen convert a CLAUDE.md/rules instruction into a deterministic pre-tool-use hook
62
- /qualia-optimize --deepen now spawns 3 parallel interface-design variants per candidate (Step 5b)
61
+ /qualia-optimize --deepen spawns 3 parallel interface-design variants per candidate (Step 5b)
63
62
  ```
64
- `/qualia-prd` pairs with `/qualia-issues` to form the PRD → vertical-slice → execute loop. `/qualia-hook-gen` reduces lifetime token cost (each migrated rule frees ~50-200 tokens per request). `/qualia-optimize --deepen` produces dramatically better refactor RFCs because 3 radically-different interfaces are surfaced and the human picks/hybridizes.
63
+ `/qualia-hook-gen` reduces lifetime token cost (each migrated rule frees ~50-200 tokens per request). `/qualia-optimize --deepen` produces dramatically better refactor RFCs because 3 radically-different interfaces are surfaced and the human picks/hybridizes.
65
64
 
66
65
  ## Alignment substrate (v5.0+)
67
66
  Before high-stakes phases, run alignment skills against `.planning/CONTEXT.md` (domain glossary) and `.planning/decisions/` (ADRs):
@@ -80,7 +79,7 @@ Before high-stakes phases, run alignment skills against `.planning/CONTEXT.md` (
80
79
  ```
81
80
  Lost? → /qualia (state router — tells you the next command)
82
81
  Stuck/weird? → /qualia-idk (diagnostic — spawns plan-view + code-view agents in parallel)
83
- Quick fix? → /qualia-quick (skip planning for small tasks)
82
+ Single feature? → /qualia-feature (auto-scoped: inline for trivia, fresh spawn for 1-5 files)
84
83
  Paused? → /qualia-resume (restore from .continue-here.md or STATE.md)
85
84
  End of day? → /qualia-report (mandatory before clock-out; writes ERP payload)
86
85
  Debug bug? → /qualia-debug (feedback-loop-first investigation)
@@ -104,6 +104,22 @@ Append '## Adversarial Findings' to verification file. Empty section fine if not
104
104
 
105
105
  Findings merge into main report. Union PASS/FAIL: either pass found CRITICAL/HIGH → phase FAIL.
106
106
 
107
+ ### 2d. INSUFFICIENT EVIDENCE downgrade (mandatory)
108
+
109
+ The verifier marks criteria it could not check (budget exhaustion, missing context) as `INSUFFICIENT EVIDENCE`. The orchestrator treats those as silent PASS unless explicitly downgraded — that's the #1 false-pass vector. Grep the verification file before declaring PASS:
110
+
111
+ ```bash
112
+ IE_COUNT=$(grep -c "INSUFFICIENT EVIDENCE" .planning/phase-{N}-verification.md 2>/dev/null || echo 0)
113
+ if [ "$IE_COUNT" -gt 0 ]; then
114
+ node ~/.claude/bin/qualia-ui.js warn "${IE_COUNT} criteria marked INSUFFICIENT EVIDENCE — downgrading verdict to FAIL"
115
+ # Rewrite the verdict line in-place
116
+ sed -i 's/^result: PASS$/result: FAIL/' .planning/phase-{N}-verification.md
117
+ sed -i 's/^## Verdict$/## Verdict\n\n**Downgraded to FAIL:** '"${IE_COUNT}"' criteria left unchecked. Re-run with larger budget (`max(25, tasks*5)` already applied) or simplify the phase plan./' .planning/phase-{N}-verification.md
118
+ fi
119
+ ```
120
+
121
+ The same check runs after the adversarial pass if it executed.
122
+
107
123
  ### 3. Present Results
108
124
 
109
125
  Read verification report. Present:
@@ -374,9 +374,8 @@
374
374
  <h3>Quick Paths</h3>
375
375
  <p class="cmd-group-note">Lightweight alternatives when the full road is overkill.</p>
376
376
  <div class="commands">
377
- <div class="cmd"><span class="cmd-name">/qualia-quick</span><span class="cmd-desc">Fast path for small tasks &mdash; bug fixes, tweaks, hot fixes. Skips full phase planning.</span></div>
378
- <div class="cmd"><span class="cmd-name">/qualia-task</span><span class="cmd-desc">Build a single task &mdash; more structured than /qualia-quick, lighter than /qualia-build. Spawns a fresh builder agent for one focused task.</span></div>
379
- <div class="cmd"><span class="cmd-name">/qualia-design</span><span class="cmd-desc">One-shot design transformation &mdash; critiques, fixes, polishes, hardens, makes responsive. No reports, no choices, just makes it professional.</span></div>
377
+ <div class="cmd"><span class="cmd-name">/qualia-feature</span><span class="cmd-desc">Auto-scoped single-feature build. Inline for trivia (typo, config), fresh builder spawn for 1-5 file features. Refuses and routes to /qualia-plan for phase-sized work. Flags: --force-spawn, --force-inline.</span></div>
378
+ <div class="cmd"><span class="cmd-name">/qualia-polish</span><span class="cmd-desc">Design pass, scope-adaptive &mdash; component, route, full app, redesign, critique, quick. Add --loop for the autonomous screenshot &rarr; score &rarr; fix loop.</span></div>
380
379
  </div>
381
380
  </div>
382
381
 
@@ -0,0 +1,83 @@
1
+ ---
2
+ project_type: {demo or full}
3
+ discovered_at: {YYYY-MM-DD}
4
+ discovery_mode: project
5
+ ---
6
+
7
+ # Project Discovery, {Project Name}
8
+
9
+ The non-technical kickoff interview output. `/qualia-discuss` writes this in PROJECT MODE before `/qualia-new` generates JOURNEY.md. Captures intent, audience, brand, and constraints in the user's own words.
10
+
11
+ Demo path: 8 questions. Full-project path: 14 questions.
12
+
13
+ ## 1. The one-line pitch
14
+
15
+ > {What is this thing, in one sentence a stranger would understand?}
16
+
17
+ ## 2. Who is it for
18
+
19
+ > {Name three real humans who will use this. Not personas, real names plus their scenario.}
20
+
21
+ ## 3. The "remember 24 hours later" sentence
22
+
23
+ > {What does someone remember 24 hours after first using this?}
24
+
25
+ ## 4. Three anti-references
26
+
27
+ > {Three sites or apps this should NOT look like, with one-line reasons each.}
28
+
29
+ ## 5. Brand voice
30
+
31
+ > {Three adjectives, then one paragraph of voice in motion — an error message, a confirmation, an empty state.}
32
+
33
+ ## 6. Success criterion
34
+
35
+ > {How does the client know this worked? One observable outcome.}
36
+
37
+ ## 7. Hard constraints
38
+
39
+ > {Anything that is non-negotiable: stack, deadline, compliance, integrations, budget.}
40
+
41
+ ## 8. Out of scope
42
+
43
+ > {What is intentionally NOT in this project, even if it would be obvious to add.}
44
+
45
+ ---
46
+
47
+ The remaining six questions only run for `project_type: full`. Demo mode stops here.
48
+
49
+ ## 9. Milestone arc, in the client's words
50
+
51
+ > {After the demo, what's the next chapter? After that, what's the chapter after? Stop at three to five chapters total. The last chapter is always Handoff.}
52
+
53
+ ## 10. Compliance and legal
54
+
55
+ > {Anything regulated: payments, medical, legal, finance, accessibility commitments, data residency.}
56
+
57
+ ## 11. Integrations
58
+
59
+ > {Third-party systems this must talk to, in priority order.}
60
+
61
+ ## 12. Content and copy
62
+
63
+ > {Who writes the copy and where does it live, today and after handoff?}
64
+
65
+ ## 13. Team and roles after handoff
66
+
67
+ > {Who maintains this after we ship? What can they do, what can't they do?}
68
+
69
+ ## 14. Budget and timeline shape
70
+
71
+ > {Fixed deadline, fixed scope, or fixed budget? Pick one — the other two flex.}
72
+
73
+ ---
74
+
75
+ ## How this feeds `/qualia-new`
76
+
77
+ - §1-§5 seed PROJECT.md (one-line pitch, what we're building) and PRODUCT.md (users, register, voice, anti-references).
78
+ - §6 becomes the first row of the success-criteria table in ROADMAP.md.
79
+ - §7-§8 populate PROJECT.md's "Out of Scope" and the constraints section.
80
+ - §9 (full only) seeds JOURNEY.md milestone names + "why now" lines.
81
+ - §10-§14 (full only) feed research scoping and the Handoff milestone checklist.
82
+
83
+ Demo projects skip §9-§14 because they ARE one milestone — the journey is just that milestone plus an implicit "client signs, we extend" branch handled by `/qualia-milestone`.
@@ -1,8 +1,15 @@
1
+ ---
2
+ project_type: full
3
+ ---
4
+
1
5
  # {Project Name}
2
6
 
3
7
  ## Client
4
8
  {client name}
5
9
 
10
+ ## Project Type
11
+ {demo or full — demo is a single shippable milestone for a sales conversation; full is the multi-milestone arc to Handoff}
12
+
6
13
  ## What We're Building
7
14
  {description}
8
15
 
package/tests/bin.test.sh CHANGED
@@ -719,18 +719,36 @@ else
719
719
  fail_case "research-synthesizer missing model frontmatter"
720
720
  fi
721
721
 
722
- # 64. Other agents do NOT have model frontmatter (conservative matrix)
723
- SAFE_AGENTS=("planner.md" "builder.md" "verifier.md" "plan-checker.md")
722
+ # 64. v5.9 model tiering: structured agents (verifier, plan-checker, roadmapper,
723
+ # qa-browser) use Sonnet. Real-reasoning agents (planner, builder, researcher,
724
+ # visual-evaluator) keep inherited Opus.
725
+ SONNET_AGENTS=("verifier.md" "plan-checker.md" "roadmapper.md" "qa-browser.md")
726
+ OPUS_AGENTS=("planner.md" "builder.md" "researcher.md" "visual-evaluator.md")
727
+
724
728
  ALL_OK=1
725
- for a in "${SAFE_AGENTS[@]}"; do
729
+ for a in "${SONNET_AGENTS[@]}"; do
730
+ if ! grep -q '^model: sonnet$' "$TMP/.claude/agents/$a" 2>/dev/null; then
731
+ ALL_OK=0
732
+ echo " missing 'model: sonnet' in $a"
733
+ fi
734
+ done
735
+ if [ "$ALL_OK" = "1" ]; then
736
+ pass "structured agents (verifier/plan-checker/roadmapper/qa-browser) use sonnet (v5.9 tiering)"
737
+ else
738
+ fail_case "v5.9 sonnet-tier agent has wrong model frontmatter"
739
+ fi
740
+
741
+ ALL_OK=1
742
+ for a in "${OPUS_AGENTS[@]}"; do
726
743
  if grep -q '^model: ' "$TMP/.claude/agents/$a" 2>/dev/null; then
727
744
  ALL_OK=0
745
+ echo " unexpected 'model:' in $a (should inherit Opus)"
728
746
  fi
729
747
  done
730
748
  if [ "$ALL_OK" = "1" ]; then
731
- pass "high-stakes agents (planner/builder/verifier/plan-checker) keep default model"
749
+ pass "reasoning agents (planner/builder/researcher/visual-evaluator) inherit Opus"
732
750
  else
733
- fail_case "high-stakes agent has unexpected model frontmatter"
751
+ fail_case "Opus-tier agent has unexpected model frontmatter"
734
752
  fi
735
753
 
736
754
  echo ""
@@ -1131,52 +1149,59 @@ fi
1131
1149
  echo ""
1132
1150
  echo "--- v5.0.0 (visual-polish loop addendum) ---"
1133
1151
 
1134
- # 99. qualia-polish-loop SKILL.md installs
1152
+ # 99. qualia-polish SKILL.md installs (v5.8: polish-loop consolidated into --loop flag)
1135
1153
  TMP=$(mktmp)
1136
1154
  echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1137
- if [ -f "$TMP/.claude/skills/qualia-polish-loop/SKILL.md" ]; then
1138
- pass "qualia-polish-loop SKILL.md installs"
1155
+ if [ -f "$TMP/.claude/skills/qualia-polish/SKILL.md" ]; then
1156
+ pass "qualia-polish SKILL.md installs"
1157
+ else
1158
+ fail_case "qualia-polish SKILL.md missing after install"
1159
+ fi
1160
+
1161
+ # 100. qualia-polish REFERENCE.md installs (carries the loop spec)
1162
+ if [ -f "$TMP/.claude/skills/qualia-polish/REFERENCE.md" ]; then
1163
+ pass "qualia-polish REFERENCE.md installs"
1139
1164
  else
1140
- fail_case "qualia-polish-loop SKILL.md missing after install"
1165
+ fail_case "qualia-polish REFERENCE.md missing after install"
1141
1166
  fi
1142
1167
 
1143
- # 100. qualia-polish-loop REFERENCE.md installs
1144
- if [ -f "$TMP/.claude/skills/qualia-polish-loop/REFERENCE.md" ]; then
1145
- pass "qualia-polish-loop REFERENCE.md installs"
1168
+ # 101. qualia-polish SKILL.md references the design rubric
1169
+ if grep -q "design-rubric.md" "$TMP/.claude/skills/qualia-polish/SKILL.md"; then
1170
+ pass "qualia-polish references design-rubric.md"
1146
1171
  else
1147
- fail_case "qualia-polish-loop REFERENCE.md missing after install"
1172
+ fail_case "qualia-polish missing rubric reference"
1148
1173
  fi
1149
1174
 
1150
- # 101. qualia-polish-loop SKILL.md references the design rubric
1151
- if grep -q "design-rubric.md" "$TMP/.claude/skills/qualia-polish-loop/SKILL.md"; then
1152
- pass "qualia-polish-loop references design-rubric.md"
1175
+ # 102. qualia-polish REFERENCE.md has the anchored vision eval prompt
1176
+ if grep -q "DEFAULT TO 3" "$TMP/.claude/skills/qualia-polish/REFERENCE.md"; then
1177
+ pass "qualia-polish REFERENCE.md has anchored rubric prompt"
1153
1178
  else
1154
- fail_case "qualia-polish-loop missing rubric reference"
1179
+ fail_case "qualia-polish REFERENCE.md missing anchored rubric"
1155
1180
  fi
1156
1181
 
1157
- # 102. qualia-polish-loop REFERENCE.md has the anchored vision eval prompt
1158
- if grep -q "DEFAULT TO 3" "$TMP/.claude/skills/qualia-polish-loop/REFERENCE.md"; then
1159
- pass "qualia-polish-loop REFERENCE.md has anchored rubric prompt"
1182
+ # 103. qualia-polish REFERENCE.md has regression detection (LOOP_REGRESSION_DETECTED)
1183
+ if grep -q "LOOP_REGRESSION_DETECTED" "$TMP/.claude/skills/qualia-polish/REFERENCE.md"; then
1184
+ pass "qualia-polish has regression kill-switch"
1160
1185
  else
1161
- fail_case "qualia-polish-loop REFERENCE.md missing anchored rubric"
1186
+ fail_case "qualia-polish missing regression kill-switch"
1162
1187
  fi
1163
1188
 
1164
- # 103. qualia-polish-loop SKILL.md has regression detection (LOOP_REGRESSION_DETECTED)
1165
- if grep -q "LOOP_REGRESSION_DETECTED" "$TMP/.claude/skills/qualia-polish-loop/SKILL.md"; then
1166
- pass "qualia-polish-loop has regression kill-switch"
1189
+ # 103b. qualia-polish SKILL.md documents the --loop flag
1190
+ if grep -q -- "--loop" "$TMP/.claude/skills/qualia-polish/SKILL.md"; then
1191
+ pass "qualia-polish SKILL.md documents --loop flag"
1167
1192
  else
1168
- fail_case "qualia-polish-loop missing regression kill-switch"
1193
+ fail_case "qualia-polish SKILL.md missing --loop documentation"
1169
1194
  fi
1170
1195
 
1171
1196
  # 104. score.mjs exists in the framework skill scripts
1172
- if [ -f "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/score.mjs" ]; then
1197
+ if [ -f "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" ]; then
1173
1198
  pass "score.mjs exists in skill scripts"
1174
1199
  else
1175
1200
  fail_case "score.mjs missing from skill scripts"
1176
1201
  fi
1177
1202
 
1178
1203
  # 105. score.mjs computes pass correctly (all dims >= 3)
1179
- SCORE_OUT=$(echo '{"typography":3,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/score.mjs" 2>&1)
1204
+ SCORE_OUT=$(echo '{"typography":3,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1180
1205
  EXIT=$?
1181
1206
  if [ "$EXIT" -eq 0 ] && echo "$SCORE_OUT" | grep -q '"pass": true'; then
1182
1207
  pass "score.mjs pass on all-3 scores"
@@ -1185,7 +1210,7 @@ else
1185
1210
  fi
1186
1211
 
1187
1212
  # 106. score.mjs computes fail correctly (one dim < 3)
1188
- SCORE_OUT=$(echo '{"typography":2,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/score.mjs" 2>&1)
1213
+ SCORE_OUT=$(echo '{"typography":2,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1189
1214
  EXIT=$?
1190
1215
  if [ "$EXIT" -eq 1 ] && echo "$SCORE_OUT" | grep -q '"pass": false'; then
1191
1216
  pass "score.mjs fail on dim < 3"
@@ -1193,38 +1218,38 @@ else
1193
1218
  fail_case "score.mjs fail computation" "exit=$EXIT"
1194
1219
  fi
1195
1220
 
1196
- # 107. qualia-road references qualia-polish-loop
1197
- if grep -q "qualia-polish-loop" "$TMP/.claude/skills/qualia-road/SKILL.md"; then
1198
- pass "qualia-road references qualia-polish-loop"
1221
+ # 107. qualia-road references the polish loop (now via --loop flag)
1222
+ if grep -qE "qualia-polish --loop|/qualia-polish --loop" "$TMP/.claude/skills/qualia-road/SKILL.md"; then
1223
+ pass "qualia-road references /qualia-polish --loop"
1199
1224
  else
1200
- fail_case "qualia-road missing qualia-polish-loop reference"
1225
+ fail_case "qualia-road missing /qualia-polish --loop reference"
1201
1226
  fi
1202
1227
 
1203
1228
  # 108. package.json version is 5.x (5.1+ accepted; v5.1 / v5.2 share the v5 line)
1204
- if grep -qE '"5\.[1234]\.' "$FRAMEWORK_DIR/package.json"; then
1229
+ if grep -qE '"5\.([1-9]|[1-9][0-9])\.' "$FRAMEWORK_DIR/package.json"; then
1205
1230
  pass "package.json version is 5.x"
1206
1231
  else
1207
1232
  fail_case "package.json version not 5.x"
1208
1233
  fi
1209
1234
 
1210
1235
  # 109. loop.mjs installs (orchestrator)
1211
- if [ -f "$TMP/.claude/skills/qualia-polish-loop/scripts/loop.mjs" ]; then
1212
- pass "qualia-polish-loop scripts/loop.mjs installs"
1236
+ if [ -f "$TMP/.claude/skills/qualia-polish/scripts/loop.mjs" ]; then
1237
+ pass "qualia-polish scripts/loop.mjs installs"
1213
1238
  else
1214
1239
  fail_case "scripts/loop.mjs missing — install.js scripts/ subfolder copy broken"
1215
1240
  fi
1216
1241
 
1217
1242
  # 110. playwright-capture.mjs installs (capture helper)
1218
- if [ -f "$TMP/.claude/skills/qualia-polish-loop/scripts/playwright-capture.mjs" ]; then
1219
- pass "qualia-polish-loop scripts/playwright-capture.mjs installs"
1243
+ if [ -f "$TMP/.claude/skills/qualia-polish/scripts/playwright-capture.mjs" ]; then
1244
+ pass "qualia-polish scripts/playwright-capture.mjs installs"
1220
1245
  else
1221
1246
  fail_case "scripts/playwright-capture.mjs missing"
1222
1247
  fi
1223
1248
 
1224
1249
  # 111. fixtures/ subfolder installs (self-test pages)
1225
- if [ -f "$TMP/.claude/skills/qualia-polish-loop/fixtures/clean.html" ] && \
1226
- [ -f "$TMP/.claude/skills/qualia-polish-loop/fixtures/broken.html" ]; then
1227
- pass "qualia-polish-loop fixtures/ installs (clean.html + broken.html)"
1250
+ if [ -f "$TMP/.claude/skills/qualia-polish/fixtures/clean.html" ] && \
1251
+ [ -f "$TMP/.claude/skills/qualia-polish/fixtures/broken.html" ]; then
1252
+ pass "qualia-polish fixtures/ installs (clean.html + broken.html)"
1228
1253
  else
1229
1254
  fail_case "fixtures/ subfolder not copied by install.js"
1230
1255
  fi
@@ -1237,7 +1262,7 @@ else
1237
1262
  fi
1238
1263
 
1239
1264
  # 113. loop.mjs parses as valid Node ESM
1240
- EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" 2>/dev/null || EXIT=$?
1265
+ EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" 2>/dev/null || EXIT=$?
1241
1266
  if [ "$EXIT" -eq 0 ]; then
1242
1267
  pass "loop.mjs parses as valid Node ESM"
1243
1268
  else
@@ -1245,7 +1270,7 @@ else
1245
1270
  fi
1246
1271
 
1247
1272
  # 114. playwright-capture.mjs parses as valid Node ESM
1248
- EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/playwright-capture.mjs" 2>/dev/null || EXIT=$?
1273
+ EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish/scripts/playwright-capture.mjs" 2>/dev/null || EXIT=$?
1249
1274
  if [ "$EXIT" -eq 0 ]; then
1250
1275
  pass "playwright-capture.mjs parses as valid Node ESM"
1251
1276
  else
@@ -1255,7 +1280,7 @@ fi
1255
1280
  # 115. loop.mjs init creates a valid state file
1256
1281
  TMP_STATE=$(mktmp)/qpl-state.json
1257
1282
  mkdir -p "$(dirname "$TMP_STATE")"
1258
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1283
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1259
1284
  --state "$TMP_STATE" --url "http://localhost:3000" --max 4 --budget 50000 >/dev/null 2>&1 || EXIT=$?
1260
1285
  if [ "$EXIT" -eq 0 ] && [ -f "$TMP_STATE" ] && grep -q '"verdict": "pending"' "$TMP_STATE"; then
1261
1286
  pass "loop.mjs init creates valid state.json"
@@ -1267,7 +1292,7 @@ fi
1267
1292
  TMP_STATE2=$(mktmp)/qpl-kill.json
1268
1293
  TMP_EVAL=$(mktmp)/qpl-eval.json
1269
1294
  mkdir -p "$(dirname "$TMP_STATE2")" "$(dirname "$TMP_EVAL")"
1270
- $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1295
+ $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1271
1296
  --state "$TMP_STATE2" --url "http://localhost:3000" --max 8 >/dev/null 2>&1
1272
1297
  # write 3 identical evals
1273
1298
  KILL_OK=true
@@ -1282,7 +1307,7 @@ for ITER in 1 2 3; do
1282
1307
  "pass": false
1283
1308
  }
1284
1309
  EOF
1285
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" record \
1310
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" record \
1286
1311
  --state "$TMP_STATE2" --eval "$TMP_EVAL" >/dev/null 2>&1 || EXIT=$?
1287
1312
  if [ "$ITER" -lt 3 ] && [ "$EXIT" -ne 1 ]; then KILL_OK=false; fi
1288
1313
  if [ "$ITER" -eq 3 ] && [ "$EXIT" -ne 3 ]; then KILL_OK=false; fi
@@ -1430,7 +1455,7 @@ fi
1430
1455
 
1431
1456
  # 128. package.json bumped to 5.x (5.1+ accepted; 5.2 is the v5.2 release)
1432
1457
  PKG_V=$($NODE -e 'console.log(require("'"$FRAMEWORK_DIR"'/package.json").version)')
1433
- if echo "$PKG_V" | grep -qE "^5\.[1234]\."; then
1458
+ if echo "$PKG_V" | grep -qE "^5\.([1-9]|[1-9][0-9])\."; then
1434
1459
  pass "package.json version bumped to 5.x ($PKG_V)"
1435
1460
  else
1436
1461
  fail_case "package.json version not 5.x" "got=$PKG_V"
@@ -1442,7 +1467,7 @@ echo "--- v5.2.0 (polish-loop reliability) ---"
1442
1467
  # 129. loop.mjs init accepts --routes and stores the URL list
1443
1468
  TMP_S=$(mktmp)/qpl-routes.json
1444
1469
  mkdir -p "$(dirname "$TMP_S")"
1445
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1470
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1446
1471
  --state "$TMP_S" \
1447
1472
  --routes "http://x.test/a,http://x.test/b,http://x.test/c" \
1448
1473
  --max 4 >/dev/null 2>&1 || EXIT=$?
@@ -1466,7 +1491,7 @@ fi
1466
1491
  # 131. loop.mjs init accepts --reduced-motion and records it in state
1467
1492
  TMP_S2=$(mktmp)/qpl-rm.json
1468
1493
  mkdir -p "$(dirname "$TMP_S2")"
1469
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1494
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1470
1495
  --state "$TMP_S2" --url "http://x.test/" --reduced-motion >/dev/null 2>&1 || EXIT=$?
1471
1496
  if [ "$EXIT" -eq 0 ] && grep -q '"reduced_motion": true' "$TMP_S2"; then
1472
1497
  pass "loop.mjs init --reduced-motion records state.reduced_motion=true"
@@ -1475,7 +1500,7 @@ else
1475
1500
  fi
1476
1501
 
1477
1502
  # 132. playwright-capture.mjs accepts --reduced-motion (parses without error)
1478
- EXIT=0; OUT=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/playwright-capture.mjs" --help 2>&1) || EXIT=$?
1503
+ EXIT=0; OUT=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/playwright-capture.mjs" --help 2>&1) || EXIT=$?
1479
1504
  if [ "$EXIT" -eq 0 ] && echo "$OUT" | grep -q -- "--reduced-motion"; then
1480
1505
  pass "playwright-capture.mjs --help documents --reduced-motion"
1481
1506
  else
@@ -1485,7 +1510,7 @@ fi
1485
1510
  # 133. loop.mjs init rejects when neither --url nor --routes given
1486
1511
  TMP_S3=$(mktmp)/qpl-nourl.json
1487
1512
  mkdir -p "$(dirname "$TMP_S3")"
1488
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1513
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1489
1514
  --state "$TMP_S3" --max 4 >/dev/null 2>&1 || EXIT=$?
1490
1515
  if [ "$EXIT" -eq 2 ]; then
1491
1516
  pass "loop.mjs init rejects missing --url/--routes (exit 2)"
@@ -1496,9 +1521,9 @@ fi
1496
1521
  # 134. loop.mjs report mentions multi-route when state.urls > 1
1497
1522
  TMP_S4=$(mktmp)/qpl-rep.json
1498
1523
  mkdir -p "$(dirname "$TMP_S4")"
1499
- $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1524
+ $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1500
1525
  --state "$TMP_S4" --routes "http://a/,http://b/" >/dev/null 2>&1
1501
- REP=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" report --state "$TMP_S4" 2>&1)
1526
+ REP=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" report --state "$TMP_S4" 2>&1)
1502
1527
  if echo "$REP" | grep -q "URLs (2)"; then
1503
1528
  pass "loop.mjs report renders multi-route header"
1504
1529
  else
@@ -1512,27 +1537,32 @@ echo "--- v5.3.0 (Matt Pocock gaps: prd, hook-gen, parallel-interface) ---"
1512
1537
  TMP=$(mktmp)
1513
1538
  echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1514
1539
 
1515
- # 135. qualia-prd skill installs
1516
- if [ -f "$TMP/.claude/skills/qualia-prd/SKILL.md" ]; then
1517
- pass "qualia-prd skill installs"
1540
+ # 135-137. /qualia-prd removed in v5.8.0 (was deprecated, overlapped /qualia-discuss).
1541
+ # Assert non-existence so the framework cannot accidentally re-ship it.
1542
+ if [ ! -f "$TMP/.claude/skills/qualia-prd/SKILL.md" ]; then
1543
+ pass "qualia-prd removed (v5.8.0 cleanup)"
1544
+ else
1545
+ fail_case "qualia-prd unexpectedly present after v5.8.0 removal"
1546
+ fi
1547
+
1548
+ # v5.8.0: assert /qualia-quick + /qualia-task also removed (were deprecated in v5.7).
1549
+ if [ ! -f "$TMP/.claude/skills/qualia-quick/SKILL.md" ]; then
1550
+ pass "qualia-quick removed (v5.8.0 cleanup)"
1518
1551
  else
1519
- fail_case "qualia-prd SKILL.md missing after install"
1552
+ fail_case "qualia-quick unexpectedly present after v5.8.0 removal"
1520
1553
  fi
1521
1554
 
1522
- # 136. qualia-prd description mentions PRD synthesis from conversation
1523
- if grep -q "synthesize\|Synthesize" "$TMP/.claude/skills/qualia-prd/SKILL.md" \
1524
- && grep -q "/qualia-issues" "$TMP/.claude/skills/qualia-prd/SKILL.md"; then
1525
- pass "qualia-prd describes synthesis flow + pairs with /qualia-issues"
1555
+ if [ ! -f "$TMP/.claude/skills/qualia-task/SKILL.md" ]; then
1556
+ pass "qualia-task removed (v5.8.0 cleanup)"
1526
1557
  else
1527
- fail_case "qualia-prd missing synthesis or /qualia-issues link"
1558
+ fail_case "qualia-task unexpectedly present after v5.8.0 removal"
1528
1559
  fi
1529
1560
 
1530
- # 137. qualia-prd documents fork-based token discipline
1531
- if grep -qE "[Ff]orked subagent|fork.*subagent" "$TMP/.claude/skills/qualia-prd/SKILL.md" \
1532
- && grep -q "Token discipline" "$TMP/.claude/skills/qualia-prd/SKILL.md"; then
1533
- pass "qualia-prd documents fork-based synthesis (token discipline)"
1561
+ # v5.8.0: assert /qualia-feature is the canonical single-feature surface.
1562
+ if [ -f "$TMP/.claude/skills/qualia-feature/SKILL.md" ]; then
1563
+ pass "qualia-feature installed (canonical single-feature surface)"
1534
1564
  else
1535
- fail_case "qualia-prd missing fork/token-discipline section"
1565
+ fail_case "qualia-feature missing after install"
1536
1566
  fi
1537
1567
 
1538
1568
  # 138. qualia-hook-gen skill installs
@@ -1577,7 +1607,7 @@ fi
1577
1607
 
1578
1608
  # 143. package.json version is 5.x (5.1+ accepted; v5.3 is the v5.3 release)
1579
1609
  PKG_V=$($NODE -e 'console.log(require("'"$FRAMEWORK_DIR"'/package.json").version)')
1580
- if echo "$PKG_V" | grep -qE "^5\.[1234]\."; then
1610
+ if echo "$PKG_V" | grep -qE "^5\.([1-9]|[1-9][0-9])\."; then
1581
1611
  pass "package.json version is 5.x ($PKG_V) — v5.3 accepted"
1582
1612
  else
1583
1613
  fail_case "package.json version not 5.x" "got=$PKG_V"