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.
- package/README.md +17 -13
- package/agents/plan-checker.md +8 -0
- package/agents/qa-browser.md +7 -0
- package/agents/research-synthesizer.md +4 -1
- package/agents/researcher.md +6 -1
- package/agents/roadmapper.md +8 -0
- package/agents/verifier.md +14 -1
- package/agents/visual-evaluator.md +1 -1
- package/bin/cli.js +30 -1
- package/bin/erp-retry.js +289 -0
- package/bin/install.js +12 -6
- package/bin/slop-detect.mjs +1 -1
- package/bin/state.js +10 -1
- package/docs/onboarding.html +621 -0
- package/docs/playwright-loop-pilot-results.md +7 -5
- package/docs/research/2026-05-11-deep-research.md +189 -0
- package/guide.md +5 -6
- package/hooks/session-start.js +19 -1
- package/package.json +3 -2
- package/rules/speed.md +1 -2
- package/skills/qualia-discuss/SKILL.md +106 -6
- package/skills/qualia-feature/SKILL.md +216 -0
- package/skills/qualia-milestone/SKILL.md +73 -1
- package/skills/qualia-new/SKILL.md +52 -25
- package/skills/qualia-optimize/SKILL.md +1 -1
- package/skills/{qualia-polish-loop → qualia-polish}/REFERENCE.md +5 -5
- package/skills/qualia-polish/SKILL.md +13 -4
- package/skills/{qualia-polish-loop → qualia-polish}/scripts/loop.mjs +2 -2
- package/skills/{qualia-polish-loop → qualia-polish}/scripts/playwright-capture.mjs +1 -1
- package/skills/qualia-report/SKILL.md +64 -2
- package/skills/qualia-road/SKILL.md +10 -11
- package/skills/qualia-verify/SKILL.md +16 -0
- package/templates/help.html +2 -3
- package/templates/project-discovery.md +83 -0
- package/templates/project.md +7 -0
- package/tests/bin.test.sh +97 -67
- package/tests/refs.test.sh +146 -0
- package/tests/slop-detect.test.sh +2 -2
- package/skills/qualia-polish-loop/SKILL.md +0 -201
- package/skills/qualia-prd/SKILL.md +0 -199
- package/skills/qualia-quick/SKILL.md +0 -44
- package/skills/qualia-task/SKILL.md +0 -98
- /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/broken.html +0 -0
- /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/clean.html +0 -0
- /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
|
|
48
|
+
## /qualia-polish --loop -- autonomous visual QA (v5.1+, consolidated into /qualia-polish in v5.8)
|
|
49
49
|
```
|
|
50
|
-
/qualia-polish
|
|
51
|
-
/qualia-polish
|
|
52
|
-
/qualia-polish
|
|
53
|
-
/qualia-polish
|
|
54
|
-
/qualia-polish
|
|
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
|
|
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
|
|
61
|
+
/qualia-optimize --deepen spawns 3 parallel interface-design variants per candidate (Step 5b)
|
|
63
62
|
```
|
|
64
|
-
`/qualia-
|
|
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
|
-
|
|
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:
|
package/templates/help.html
CHANGED
|
@@ -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-
|
|
378
|
-
<div class="cmd"><span class="cmd-name">/qualia-
|
|
379
|
-
<div class="cmd"><span class="cmd-name">/qualia-design</span><span class="cmd-desc">One-shot design transformation — 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 — component, route, full app, redesign, critique, quick. Add --loop for the autonomous screenshot → score → 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`.
|
package/templates/project.md
CHANGED
|
@@ -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.
|
|
723
|
-
|
|
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 "${
|
|
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 "
|
|
749
|
+
pass "reasoning agents (planner/builder/researcher/visual-evaluator) inherit Opus"
|
|
732
750
|
else
|
|
733
|
-
fail_case "
|
|
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
|
|
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
|
|
1138
|
-
pass "qualia-polish
|
|
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
|
|
1165
|
+
fail_case "qualia-polish REFERENCE.md missing after install"
|
|
1141
1166
|
fi
|
|
1142
1167
|
|
|
1143
|
-
#
|
|
1144
|
-
if
|
|
1145
|
-
pass "qualia-polish-
|
|
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
|
|
1172
|
+
fail_case "qualia-polish missing rubric reference"
|
|
1148
1173
|
fi
|
|
1149
1174
|
|
|
1150
|
-
#
|
|
1151
|
-
if grep -q "
|
|
1152
|
-
pass "qualia-polish
|
|
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
|
|
1179
|
+
fail_case "qualia-polish REFERENCE.md missing anchored rubric"
|
|
1155
1180
|
fi
|
|
1156
1181
|
|
|
1157
|
-
#
|
|
1158
|
-
if grep -q "
|
|
1159
|
-
pass "qualia-polish
|
|
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
|
|
1186
|
+
fail_case "qualia-polish missing regression kill-switch"
|
|
1162
1187
|
fi
|
|
1163
1188
|
|
|
1164
|
-
#
|
|
1165
|
-
if grep -q "
|
|
1166
|
-
pass "qualia-polish
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1197
|
-
if grep -
|
|
1198
|
-
pass "qualia-road references qualia-polish
|
|
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
|
|
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\.[
|
|
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
|
|
1212
|
-
pass "qualia-polish
|
|
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
|
|
1219
|
-
pass "qualia-polish
|
|
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
|
|
1226
|
-
[ -f "$TMP/.claude/skills/qualia-polish
|
|
1227
|
-
pass "qualia-polish
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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\.[
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1516
|
-
|
|
1517
|
-
|
|
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-
|
|
1552
|
+
fail_case "qualia-quick unexpectedly present after v5.8.0 removal"
|
|
1520
1553
|
fi
|
|
1521
1554
|
|
|
1522
|
-
|
|
1523
|
-
|
|
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-
|
|
1558
|
+
fail_case "qualia-task unexpectedly present after v5.8.0 removal"
|
|
1528
1559
|
fi
|
|
1529
1560
|
|
|
1530
|
-
#
|
|
1531
|
-
if
|
|
1532
|
-
|
|
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-
|
|
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\.[
|
|
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"
|