qualia-framework 5.4.0 → 5.8.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 (50) hide show
  1. package/README.md +21 -17
  2. package/agents/builder.md +25 -8
  3. package/agents/plan-checker.md +50 -2
  4. package/agents/planner.md +25 -1
  5. package/agents/research-synthesizer.md +4 -1
  6. package/agents/researcher.md +6 -1
  7. package/agents/visual-evaluator.md +1 -1
  8. package/bin/install.js +8 -8
  9. package/bin/plan-contract.js +32 -1
  10. package/bin/slop-detect.mjs +1 -1
  11. package/docs/erp-contract.md +11 -0
  12. package/docs/onboarding.html +623 -0
  13. package/guide.md +8 -9
  14. package/hooks/session-start.js +1 -1
  15. package/package.json +1 -1
  16. package/skills/qualia-discuss/SKILL.md +123 -9
  17. package/skills/qualia-feature/SKILL.md +216 -0
  18. package/skills/qualia-milestone/SKILL.md +73 -1
  19. package/skills/qualia-new/SKILL.md +52 -25
  20. package/skills/qualia-optimize/SKILL.md +1 -1
  21. package/skills/{qualia-polish-loop → qualia-polish}/REFERENCE.md +5 -5
  22. package/skills/qualia-polish/SKILL.md +13 -4
  23. package/skills/{qualia-polish-loop → qualia-polish}/scripts/loop.mjs +2 -2
  24. package/skills/{qualia-polish-loop → qualia-polish}/scripts/playwright-capture.mjs +1 -1
  25. package/skills/qualia-report/SKILL.md +8 -6
  26. package/skills/qualia-road/SKILL.md +10 -11
  27. package/templates/CONTEXT.md +3 -2
  28. package/templates/help.html +1 -1
  29. package/templates/phase-context.md +5 -4
  30. package/templates/project-discovery.md +83 -0
  31. package/templates/project.md +7 -0
  32. package/tests/bin.test.sh +104 -62
  33. package/tests/lib.test.sh +21 -0
  34. package/tests/slop-detect.test.sh +2 -2
  35. package/docs/archive/session-report-2026-04-18.md +0 -199
  36. package/docs/install-redesign-builder-prompt.md +0 -290
  37. package/docs/install-redesign-pilot.md +0 -234
  38. package/docs/instruction-budget-audit.md +0 -113
  39. package/docs/journey-demo.html +0 -1008
  40. package/docs/playwright-loop-builder-prompt.md +0 -185
  41. package/docs/playwright-loop-design-notes.md +0 -108
  42. package/docs/playwright-loop-tester-prompt.md +0 -213
  43. package/docs/polish-loop-supervised-run.md +0 -111
  44. package/skills/qualia-polish-loop/SKILL.md +0 -201
  45. package/skills/qualia-prd/SKILL.md +0 -199
  46. package/skills/qualia-quick/SKILL.md +0 -44
  47. package/skills/qualia-task/SKILL.md +0 -98
  48. /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/broken.html +0 -0
  49. /package/skills/{qualia-polish-loop → qualia-polish}/fixtures/clean.html +0 -0
  50. /package/skills/{qualia-polish-loop → qualia-polish}/scripts/score.mjs +0 -0
package/tests/bin.test.sh CHANGED
@@ -1131,52 +1131,59 @@ fi
1131
1131
  echo ""
1132
1132
  echo "--- v5.0.0 (visual-polish loop addendum) ---"
1133
1133
 
1134
- # 99. qualia-polish-loop SKILL.md installs
1134
+ # 99. qualia-polish SKILL.md installs (v5.8: polish-loop consolidated into --loop flag)
1135
1135
  TMP=$(mktmp)
1136
1136
  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"
1137
+ if [ -f "$TMP/.claude/skills/qualia-polish/SKILL.md" ]; then
1138
+ pass "qualia-polish SKILL.md installs"
1139
1139
  else
1140
- fail_case "qualia-polish-loop SKILL.md missing after install"
1140
+ fail_case "qualia-polish SKILL.md missing after install"
1141
1141
  fi
1142
1142
 
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"
1143
+ # 100. qualia-polish REFERENCE.md installs (carries the loop spec)
1144
+ if [ -f "$TMP/.claude/skills/qualia-polish/REFERENCE.md" ]; then
1145
+ pass "qualia-polish REFERENCE.md installs"
1146
1146
  else
1147
- fail_case "qualia-polish-loop REFERENCE.md missing after install"
1147
+ fail_case "qualia-polish REFERENCE.md missing after install"
1148
1148
  fi
1149
1149
 
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"
1150
+ # 101. qualia-polish SKILL.md references the design rubric
1151
+ if grep -q "design-rubric.md" "$TMP/.claude/skills/qualia-polish/SKILL.md"; then
1152
+ pass "qualia-polish references design-rubric.md"
1153
1153
  else
1154
- fail_case "qualia-polish-loop missing rubric reference"
1154
+ fail_case "qualia-polish missing rubric reference"
1155
1155
  fi
1156
1156
 
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"
1157
+ # 102. qualia-polish REFERENCE.md has the anchored vision eval prompt
1158
+ if grep -q "DEFAULT TO 3" "$TMP/.claude/skills/qualia-polish/REFERENCE.md"; then
1159
+ pass "qualia-polish REFERENCE.md has anchored rubric prompt"
1160
1160
  else
1161
- fail_case "qualia-polish-loop REFERENCE.md missing anchored rubric"
1161
+ fail_case "qualia-polish REFERENCE.md missing anchored rubric"
1162
1162
  fi
1163
1163
 
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"
1164
+ # 103. qualia-polish REFERENCE.md has regression detection (LOOP_REGRESSION_DETECTED)
1165
+ if grep -q "LOOP_REGRESSION_DETECTED" "$TMP/.claude/skills/qualia-polish/REFERENCE.md"; then
1166
+ pass "qualia-polish has regression kill-switch"
1167
1167
  else
1168
- fail_case "qualia-polish-loop missing regression kill-switch"
1168
+ fail_case "qualia-polish missing regression kill-switch"
1169
+ fi
1170
+
1171
+ # 103b. qualia-polish SKILL.md documents the --loop flag
1172
+ if grep -q -- "--loop" "$TMP/.claude/skills/qualia-polish/SKILL.md"; then
1173
+ pass "qualia-polish SKILL.md documents --loop flag"
1174
+ else
1175
+ fail_case "qualia-polish SKILL.md missing --loop documentation"
1169
1176
  fi
1170
1177
 
1171
1178
  # 104. score.mjs exists in the framework skill scripts
1172
- if [ -f "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/score.mjs" ]; then
1179
+ if [ -f "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" ]; then
1173
1180
  pass "score.mjs exists in skill scripts"
1174
1181
  else
1175
1182
  fail_case "score.mjs missing from skill scripts"
1176
1183
  fi
1177
1184
 
1178
1185
  # 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)
1186
+ 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
1187
  EXIT=$?
1181
1188
  if [ "$EXIT" -eq 0 ] && echo "$SCORE_OUT" | grep -q '"pass": true'; then
1182
1189
  pass "score.mjs pass on all-3 scores"
@@ -1185,7 +1192,7 @@ else
1185
1192
  fi
1186
1193
 
1187
1194
  # 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)
1195
+ 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
1196
  EXIT=$?
1190
1197
  if [ "$EXIT" -eq 1 ] && echo "$SCORE_OUT" | grep -q '"pass": false'; then
1191
1198
  pass "score.mjs fail on dim < 3"
@@ -1193,38 +1200,38 @@ else
1193
1200
  fail_case "score.mjs fail computation" "exit=$EXIT"
1194
1201
  fi
1195
1202
 
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"
1203
+ # 107. qualia-road references the polish loop (now via --loop flag)
1204
+ if grep -qE "qualia-polish --loop|/qualia-polish --loop" "$TMP/.claude/skills/qualia-road/SKILL.md"; then
1205
+ pass "qualia-road references /qualia-polish --loop"
1199
1206
  else
1200
- fail_case "qualia-road missing qualia-polish-loop reference"
1207
+ fail_case "qualia-road missing /qualia-polish --loop reference"
1201
1208
  fi
1202
1209
 
1203
1210
  # 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
1211
+ if grep -qE '"5\.([1-9]|[1-9][0-9])\.' "$FRAMEWORK_DIR/package.json"; then
1205
1212
  pass "package.json version is 5.x"
1206
1213
  else
1207
1214
  fail_case "package.json version not 5.x"
1208
1215
  fi
1209
1216
 
1210
1217
  # 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"
1218
+ if [ -f "$TMP/.claude/skills/qualia-polish/scripts/loop.mjs" ]; then
1219
+ pass "qualia-polish scripts/loop.mjs installs"
1213
1220
  else
1214
1221
  fail_case "scripts/loop.mjs missing — install.js scripts/ subfolder copy broken"
1215
1222
  fi
1216
1223
 
1217
1224
  # 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"
1225
+ if [ -f "$TMP/.claude/skills/qualia-polish/scripts/playwright-capture.mjs" ]; then
1226
+ pass "qualia-polish scripts/playwright-capture.mjs installs"
1220
1227
  else
1221
1228
  fail_case "scripts/playwright-capture.mjs missing"
1222
1229
  fi
1223
1230
 
1224
1231
  # 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)"
1232
+ if [ -f "$TMP/.claude/skills/qualia-polish/fixtures/clean.html" ] && \
1233
+ [ -f "$TMP/.claude/skills/qualia-polish/fixtures/broken.html" ]; then
1234
+ pass "qualia-polish fixtures/ installs (clean.html + broken.html)"
1228
1235
  else
1229
1236
  fail_case "fixtures/ subfolder not copied by install.js"
1230
1237
  fi
@@ -1237,7 +1244,7 @@ else
1237
1244
  fi
1238
1245
 
1239
1246
  # 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=$?
1247
+ EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" 2>/dev/null || EXIT=$?
1241
1248
  if [ "$EXIT" -eq 0 ]; then
1242
1249
  pass "loop.mjs parses as valid Node ESM"
1243
1250
  else
@@ -1245,7 +1252,7 @@ else
1245
1252
  fi
1246
1253
 
1247
1254
  # 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=$?
1255
+ EXIT=0; $NODE --check "$FRAMEWORK_DIR/skills/qualia-polish/scripts/playwright-capture.mjs" 2>/dev/null || EXIT=$?
1249
1256
  if [ "$EXIT" -eq 0 ]; then
1250
1257
  pass "playwright-capture.mjs parses as valid Node ESM"
1251
1258
  else
@@ -1255,7 +1262,7 @@ fi
1255
1262
  # 115. loop.mjs init creates a valid state file
1256
1263
  TMP_STATE=$(mktmp)/qpl-state.json
1257
1264
  mkdir -p "$(dirname "$TMP_STATE")"
1258
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1265
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1259
1266
  --state "$TMP_STATE" --url "http://localhost:3000" --max 4 --budget 50000 >/dev/null 2>&1 || EXIT=$?
1260
1267
  if [ "$EXIT" -eq 0 ] && [ -f "$TMP_STATE" ] && grep -q '"verdict": "pending"' "$TMP_STATE"; then
1261
1268
  pass "loop.mjs init creates valid state.json"
@@ -1267,7 +1274,7 @@ fi
1267
1274
  TMP_STATE2=$(mktmp)/qpl-kill.json
1268
1275
  TMP_EVAL=$(mktmp)/qpl-eval.json
1269
1276
  mkdir -p "$(dirname "$TMP_STATE2")" "$(dirname "$TMP_EVAL")"
1270
- $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1277
+ $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1271
1278
  --state "$TMP_STATE2" --url "http://localhost:3000" --max 8 >/dev/null 2>&1
1272
1279
  # write 3 identical evals
1273
1280
  KILL_OK=true
@@ -1282,7 +1289,7 @@ for ITER in 1 2 3; do
1282
1289
  "pass": false
1283
1290
  }
1284
1291
  EOF
1285
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" record \
1292
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" record \
1286
1293
  --state "$TMP_STATE2" --eval "$TMP_EVAL" >/dev/null 2>&1 || EXIT=$?
1287
1294
  if [ "$ITER" -lt 3 ] && [ "$EXIT" -ne 1 ]; then KILL_OK=false; fi
1288
1295
  if [ "$ITER" -eq 3 ] && [ "$EXIT" -ne 3 ]; then KILL_OK=false; fi
@@ -1430,7 +1437,7 @@ fi
1430
1437
 
1431
1438
  # 128. package.json bumped to 5.x (5.1+ accepted; 5.2 is the v5.2 release)
1432
1439
  PKG_V=$($NODE -e 'console.log(require("'"$FRAMEWORK_DIR"'/package.json").version)')
1433
- if echo "$PKG_V" | grep -qE "^5\.[1234]\."; then
1440
+ if echo "$PKG_V" | grep -qE "^5\.([1-9]|[1-9][0-9])\."; then
1434
1441
  pass "package.json version bumped to 5.x ($PKG_V)"
1435
1442
  else
1436
1443
  fail_case "package.json version not 5.x" "got=$PKG_V"
@@ -1442,7 +1449,7 @@ echo "--- v5.2.0 (polish-loop reliability) ---"
1442
1449
  # 129. loop.mjs init accepts --routes and stores the URL list
1443
1450
  TMP_S=$(mktmp)/qpl-routes.json
1444
1451
  mkdir -p "$(dirname "$TMP_S")"
1445
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1452
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1446
1453
  --state "$TMP_S" \
1447
1454
  --routes "http://x.test/a,http://x.test/b,http://x.test/c" \
1448
1455
  --max 4 >/dev/null 2>&1 || EXIT=$?
@@ -1466,7 +1473,7 @@ fi
1466
1473
  # 131. loop.mjs init accepts --reduced-motion and records it in state
1467
1474
  TMP_S2=$(mktmp)/qpl-rm.json
1468
1475
  mkdir -p "$(dirname "$TMP_S2")"
1469
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1476
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1470
1477
  --state "$TMP_S2" --url "http://x.test/" --reduced-motion >/dev/null 2>&1 || EXIT=$?
1471
1478
  if [ "$EXIT" -eq 0 ] && grep -q '"reduced_motion": true' "$TMP_S2"; then
1472
1479
  pass "loop.mjs init --reduced-motion records state.reduced_motion=true"
@@ -1475,7 +1482,7 @@ else
1475
1482
  fi
1476
1483
 
1477
1484
  # 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=$?
1485
+ EXIT=0; OUT=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/playwright-capture.mjs" --help 2>&1) || EXIT=$?
1479
1486
  if [ "$EXIT" -eq 0 ] && echo "$OUT" | grep -q -- "--reduced-motion"; then
1480
1487
  pass "playwright-capture.mjs --help documents --reduced-motion"
1481
1488
  else
@@ -1485,7 +1492,7 @@ fi
1485
1492
  # 133. loop.mjs init rejects when neither --url nor --routes given
1486
1493
  TMP_S3=$(mktmp)/qpl-nourl.json
1487
1494
  mkdir -p "$(dirname "$TMP_S3")"
1488
- EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1495
+ EXIT=0; $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1489
1496
  --state "$TMP_S3" --max 4 >/dev/null 2>&1 || EXIT=$?
1490
1497
  if [ "$EXIT" -eq 2 ]; then
1491
1498
  pass "loop.mjs init rejects missing --url/--routes (exit 2)"
@@ -1496,9 +1503,9 @@ fi
1496
1503
  # 134. loop.mjs report mentions multi-route when state.urls > 1
1497
1504
  TMP_S4=$(mktmp)/qpl-rep.json
1498
1505
  mkdir -p "$(dirname "$TMP_S4")"
1499
- $NODE "$FRAMEWORK_DIR/skills/qualia-polish-loop/scripts/loop.mjs" init \
1506
+ $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" init \
1500
1507
  --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)
1508
+ REP=$($NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/loop.mjs" report --state "$TMP_S4" 2>&1)
1502
1509
  if echo "$REP" | grep -q "URLs (2)"; then
1503
1510
  pass "loop.mjs report renders multi-route header"
1504
1511
  else
@@ -1512,27 +1519,32 @@ echo "--- v5.3.0 (Matt Pocock gaps: prd, hook-gen, parallel-interface) ---"
1512
1519
  TMP=$(mktmp)
1513
1520
  echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1514
1521
 
1515
- # 135. qualia-prd skill installs
1516
- if [ -f "$TMP/.claude/skills/qualia-prd/SKILL.md" ]; then
1517
- pass "qualia-prd skill installs"
1522
+ # 135-137. /qualia-prd removed in v5.8.0 (was deprecated, overlapped /qualia-discuss).
1523
+ # Assert non-existence so the framework cannot accidentally re-ship it.
1524
+ if [ ! -f "$TMP/.claude/skills/qualia-prd/SKILL.md" ]; then
1525
+ pass "qualia-prd removed (v5.8.0 cleanup)"
1518
1526
  else
1519
- fail_case "qualia-prd SKILL.md missing after install"
1527
+ fail_case "qualia-prd unexpectedly present after v5.8.0 removal"
1520
1528
  fi
1521
1529
 
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"
1530
+ # v5.8.0: assert /qualia-quick + /qualia-task also removed (were deprecated in v5.7).
1531
+ if [ ! -f "$TMP/.claude/skills/qualia-quick/SKILL.md" ]; then
1532
+ pass "qualia-quick removed (v5.8.0 cleanup)"
1526
1533
  else
1527
- fail_case "qualia-prd missing synthesis or /qualia-issues link"
1534
+ fail_case "qualia-quick unexpectedly present after v5.8.0 removal"
1528
1535
  fi
1529
1536
 
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)"
1537
+ if [ ! -f "$TMP/.claude/skills/qualia-task/SKILL.md" ]; then
1538
+ pass "qualia-task removed (v5.8.0 cleanup)"
1534
1539
  else
1535
- fail_case "qualia-prd missing fork/token-discipline section"
1540
+ fail_case "qualia-task unexpectedly present after v5.8.0 removal"
1541
+ fi
1542
+
1543
+ # v5.8.0: assert /qualia-feature is the canonical single-feature surface.
1544
+ if [ -f "$TMP/.claude/skills/qualia-feature/SKILL.md" ]; then
1545
+ pass "qualia-feature installed (canonical single-feature surface)"
1546
+ else
1547
+ fail_case "qualia-feature missing after install"
1536
1548
  fi
1537
1549
 
1538
1550
  # 138. qualia-hook-gen skill installs
@@ -1577,12 +1589,42 @@ fi
1577
1589
 
1578
1590
  # 143. package.json version is 5.x (5.1+ accepted; v5.3 is the v5.3 release)
1579
1591
  PKG_V=$($NODE -e 'console.log(require("'"$FRAMEWORK_DIR"'/package.json").version)')
1580
- if echo "$PKG_V" | grep -qE "^5\.[1234]\."; then
1592
+ if echo "$PKG_V" | grep -qE "^5\.([1-9]|[1-9][0-9])\."; then
1581
1593
  pass "package.json version is 5.x ($PKG_V) — v5.3 accepted"
1582
1594
  else
1583
1595
  fail_case "package.json version not 5.x" "got=$PKG_V"
1584
1596
  fi
1585
1597
 
1598
+ echo ""
1599
+ echo "--- ERP shift-report contract ---"
1600
+
1601
+ # 144. qualia-report describes clock-out as truthful shift submission, not task completion
1602
+ if grep -qi "daily shift report" "$TMP/.claude/skills/qualia-report/SKILL.md" \
1603
+ && grep -qi "not a task-completion ceremony" "$TMP/.claude/skills/qualia-report/SKILL.md" \
1604
+ && grep -qi "What happened during your shift" "$TMP/.claude/skills/qualia-report/SKILL.md"; then
1605
+ pass "qualia-report frames clock-out as shift submission, not task completion"
1606
+ else
1607
+ fail_case "qualia-report missing shift-submission contract"
1608
+ fi
1609
+
1610
+ # 145. ERP contract documents the date model: project, milestone, employee submission
1611
+ if grep -q "Project deadline" "$FRAMEWORK_DIR/docs/erp-contract.md" \
1612
+ && grep -q "Milestone deadline" "$FRAMEWORK_DIR/docs/erp-contract.md" \
1613
+ && grep -q "Employee submission date" "$FRAMEWORK_DIR/docs/erp-contract.md" \
1614
+ && grep -q "Phase and task counters remain framework telemetry" "$FRAMEWORK_DIR/docs/erp-contract.md"; then
1615
+ pass "ERP contract documents project/milestone/submission date model"
1616
+ else
1617
+ fail_case "ERP contract missing date-model clarification"
1618
+ fi
1619
+
1620
+ # 146. Project glossary keeps framework tasks internal to agent execution
1621
+ if grep -q "framework-internal execution unit" "$FRAMEWORK_DIR/templates/CONTEXT.md" \
1622
+ && grep -q "ERP tracks project deadlines, milestone deadlines, and employee shift submissions" "$FRAMEWORK_DIR/templates/CONTEXT.md"; then
1623
+ pass "CONTEXT template distinguishes internal tasks from ERP workflow"
1624
+ else
1625
+ fail_case "CONTEXT template missing framework-task vs ERP-workflow distinction"
1626
+ fi
1627
+
1586
1628
  echo ""
1587
1629
  echo "=== Results: $PASS passed, $FAIL failed ==="
1588
1630
  [ "$FAIL" -eq 0 ] && exit 0 || exit 1
package/tests/lib.test.sh CHANGED
@@ -57,6 +57,27 @@ console.log(errs.length > 0 ? "REJECTED" : "ACCEPTED");
57
57
  ')
58
58
  [ "$OUT" = "REJECTED" ] && ok "rejects malformed contract" || fail "malformed accepted"
59
59
 
60
+ OUT=$($NODE -e '
61
+ const pc = require("'"$PC"'");
62
+ const slop = {
63
+ version: 1, phase: 1, goal: "x", why: "y",
64
+ generated_at: "t", generated_by: "planner", source_plan_hash: "h",
65
+ success_criteria: ["sc"],
66
+ tasks: [{
67
+ id: "T1", title: "t", wave: 1, depends_on: [],
68
+ files_modify: [], files_create: [], files_delete: [],
69
+ acceptance_criteria: ["minimal implementation of login"],
70
+ action: "Add hardcoded for now placeholder, will be wired later",
71
+ context_files: [],
72
+ verification: [{ type: "file-exists", path: "a.ts" }]
73
+ }]
74
+ };
75
+ const errs = pc.validate(slop);
76
+ const hits = errs.filter(e => /scope-reduction/.test(e));
77
+ console.log(hits.length >= 2 ? "DETECTED" : "MISSED:" + errs.join(";"));
78
+ ')
79
+ [ "$OUT" = "DETECTED" ] && ok "detects scope-reduction phrases in action + acceptance_criteria" || fail "scope-reduction missed: $OUT"
80
+
60
81
  OUT=$($NODE -e '
61
82
  const pc = require("'"$PC"'");
62
83
  const c = {
@@ -121,8 +121,8 @@ else
121
121
  fail_case "gradient detection" "expected exit 1, got $EXIT_CODE"
122
122
  fi
123
123
 
124
- # ── Existing fixture: skills/qualia-polish-loop/fixtures/broken.html ──
125
- FIXTURE="$(cd "$(dirname "$0")/.." && pwd)/skills/qualia-polish-loop/fixtures/broken.html"
124
+ # ── Existing fixture: skills/qualia-polish/fixtures/broken.html ──
125
+ FIXTURE="$(cd "$(dirname "$0")/.." && pwd)/skills/qualia-polish/fixtures/broken.html"
126
126
  if [ -f "$FIXTURE" ]; then
127
127
  EXIT_CODE=0
128
128
  $NODE "$SLOP_DETECT" "$FIXTURE" >/dev/null 2>&1 || EXIT_CODE=$?
@@ -1,199 +0,0 @@
1
- # Session Report — 2026-04-18
2
-
3
- **Project:** qualia-framework
4
- **Branch:** feature/full-journey (local, not pushed)
5
- **Released:** v3.7.0 (staged on feature/story-file-plans) and **v4.0.0** (staged on feature/full-journey)
6
- **Owner:** Fawzi Goussous
7
- **Duration:** ~4 hours
8
-
9
- ## What this session shipped
10
-
11
- Two releases staged on separate feature branches, ready for push + merge + `npm publish`.
12
-
13
- | Tag | Branch | Commits | Theme |
14
- |---|---|---|---|
15
- | **v3.7.0** | feature/story-file-plans | 1 commit (8ae5b0e) | Story-file plan format — every phase plan task carries inline Why, Acceptance Criteria, Validation, explicit Depends on |
16
- | **v4.0.0** | feature/full-journey | 8 commits total (includes v3.7.0) | Full Journey release — /qualia-new maps the entire arc to handoff, --auto chains the Road end-to-end, milestone hierarchy locked, /qualia-idk rebuilt as diagnostician |
17
-
18
- **Test suite:** 150 → 156 green (+6 v4 coverage, 0 regressions).
19
- **Package:** version bumped 3.6.0 → 4.0.0.
20
- **Release candidate:** v4.0.0 commit is `f790554` on feature/full-journey.
21
-
22
- ## Background & trigger
23
-
24
- Fawzi came in with three pain points from Sakani's ERP view:
25
- 1. "Unphased Tasks" and "Phase 0: Central Bank Demo" rendering at the same tree level as "Milestone 1", "Milestone 2", etc. — milestones collapsed into single phases, numbering skipped (missing M5).
26
- 2. `/qualia-new` stops at v1 — team improvises subsequent milestones, no clear path to handoff.
27
- 3. Team members don't understand the framework's dev cycle. Need something a non-technical person can follow without getting lost.
28
-
29
- Plus: "make it sexier," personalize the Qualia experience, enhance every command for best practices, ship a stable v4.0.
30
-
31
- ## The approach
32
-
33
- Split the work into labeled phases on a feature branch so commits tell the story:
34
-
35
- ### v3.7.0 prerequisite — story-file plans
36
- - `templates/plan.md` rewritten to 7-field story-file format (Wave, Files, Depends on, Why, Acceptance Criteria, Action, Validation, Context + optional Persona)
37
- - `agents/planner.md` generates the new format
38
- - `agents/plan-checker.md` validates the 7 fields and cross-checks wave↔deps consistency
39
- - `agents/builder.md` reads rationale, respects Depends on, runs Validation before commit
40
- - `agents/verifier.md` adds 3-layer check (phase Success Criteria + per-task AC + Verification Contract)
41
- - `bin/qualia-ui.js` adds `plan-summary` command — terminal dashboard with colored persona chips, dependency arrows, AC/check counts per task
42
- - `bin/state.js` accepts both legacy `Done when:` and new `Acceptance Criteria:` anchors (backward-compatible)
43
-
44
- Committed on `feature/story-file-plans` as v3.7.0 (`8ae5b0e`). Standalone useful release; branched v4 off of it.
45
-
46
- ### v4.0.0 — Full Journey, phased
47
-
48
- **Phase A — Model foundation** (`2e371c2`)
49
- - `templates/journey.md` — new JOURNEY.md schema (hard ceiling 5 milestones, hard floor 2, final milestone always Handoff with 4 fixed phases)
50
- - `tracking.json` gains `milestone_name`, `milestones[]` (array of closed milestone summaries)
51
- - `state.js close-milestone` readiness guards: MILESTONE_NOT_READY, MILESTONE_TOO_SMALL (both bypassable with --force)
52
- - `state.js init` accepts `--milestone_name` and preserves milestones[] across re-init
53
- - Tests: +4
54
-
55
- **Phase B — Roadmapper + /qualia-new full-journey output** (`87af253`)
56
- - `agents/roadmapper.md` rewritten: now produces JOURNEY.md (all milestones) + REQUIREMENTS.md (grouped by milestone) + ROADMAP.md (Milestone 1's phase detail only)
57
- - **Dropped** the old "no review/deploy/handoff phases" rule. **Replaced** with: final milestone is always literally named "Handoff" with fixed 4 phases.
58
- - `skills/qualia-new/SKILL.md` rewritten: always runs research (no more `workflow.research` gate), single approval on the whole journey, new `--auto` flag
59
- - `agents/research-synthesizer.md` thinks across all milestones
60
- - `skills/qualia-milestone/SKILL.md` reads next milestone from JOURNEY.md (no longer asks user)
61
- - `templates/requirements.md` multi-milestone format with standard Handoff section (HAND-01..HAND-15)
62
- - `templates/roadmap.md` scoped to current milestone only
63
-
64
- **Phase C — Auto-chain wiring** (`400cd17`)
65
- - `--auto` flag added to `/qualia-plan`, `/qualia-build`, `/qualia-verify`, `/qualia-milestone`
66
- - Auto-chain decision table in `/qualia-verify`: PASS → next phase OR milestone close OR ship+handoff; FAIL → gap closure OR halt at limit
67
- - Two human gates total per project: journey approval + each milestone boundary
68
-
69
- **Phase D+E — Builder pre-inline + journey visualization** (`74dd26e`)
70
- - Builder pre-inlines PROJECT.md + DESIGN.md + Context files into agent prompt BEFORE spawning (GSD-pattern borrowing, saves 3-5 Read calls per task)
71
- - `qualia-ui.js journey-tree` renders JOURNEY.md as ASCII ladder (green shipped, teal current, dim future, [FINAL] tag for Handoff)
72
- - `qualia-ui.js milestone-complete` celebration banner
73
- - 5 new banner actions: milestone ◆, journey ◯, auto ⚡, research ◱, roadmap ◐
74
- - `/qualia` router renders journey-tree for "you are here" orientation
75
- - `/qualia-milestone` renders journey-tree + milestone-complete
76
-
77
- **Phase F — Ship-side fields + handoff deliverables** (`b41a52d`)
78
- - `state.js` bumps `build_count` on each 'built' transition, `deploy_count` on each 'shipped' (previously never incremented)
79
- - `qualia-report` ERP payload now includes all v4 fields (project_id, team_id, git_remote, milestone_name, milestones[], build_count, deploy_count, session_started_at, last_pushed_at)
80
- - `/qualia-handoff` rewritten: explicit 4 mandatory deliverables — production URL verified (HTTP + latency + auth), docs updated, `.planning/archive/` check, final ERP report
81
-
82
- **Phase G — Smoke test fix + coverage** (`f62e753`)
83
- - Bug fix: close-milestone summary was recording current phase's tasks, not cumulative milestone total. Fixed via `lifetime.tasks_completed − sum(prior milestones[].tasks_completed)`
84
- - Tests: +2 (cumulative task count, build_count bump)
85
-
86
- **Release (`f790554`)**
87
- - Single unified v4.0.0 release commit
88
- - Package bumped 3.7.0 → 4.0.0
89
- - CHANGELOG.md v4.0.0 entry with full feature list + migration notes
90
- - `/qualia-idk` rebuilt as real diagnostician (was briefly v4.0.1 in the branch history, folded into v4.0.0 per owner request)
91
-
92
- ### The `/qualia-idk` rebuild (folded into v4.0.0)
93
-
94
- Before: thin one-line alias to `/qualia`.
95
-
96
- Now: interpretive diagnostic. When user says "I don't know what's going on" / "something feels off":
97
- 1. Spawns **Plan view** Explore subagent — reads only `.planning/*`, reports what plan says
98
- 2. Spawns **Code view** Explore subagent in parallel — reads only source code, reports what's actually built, cites file:line
99
- 3. Synthesizes: structured "What I see / The mismatch / What I think is happening / What to do next" in plain language
100
- 4. Maps recommendations to existing commands where applicable
101
-
102
- `/qualia` description scoped back to mechanical state routing — no longer claims "idk/stuck/lost/confused" triggers (those route to `/qualia-idk` now).
103
-
104
- ## Competitive research completed
105
-
106
- During the session, ran deep research on competing Claude Code frameworks:
107
- - **Superpowers** (Jesse Vincent) — 93K stars — rigid 5-phase gates, Visual Companion, cross-agent portability
108
- - **BMAD-METHOD** — 43K stars — 12-19 named role agents, story files, expansion packs
109
- - **gstack** (Garry Tan) — 74K stars — 23-role team, persistent browser daemon, /codex cross-model review
110
- - **GSD** (Get Shit Done, v1+v2) — 54K + 6K stars — state-machine auto-advance, pre-inlined dispatch, adaptive replanning
111
- - **SuperClaude, Agent OS, Context Engineering/PRP, Claude-Flow, Cursor 2.0, Windsurf** — broader landscape
112
-
113
- Patterns borrowed in v4.0.0:
114
- - **Story-file plan format** (BMAD) — inline rationale + acceptance criteria
115
- - **State-machine auto-advance** (GSD v2) — the --auto chain
116
- - **Pre-inline context at dispatch** (GSD v2) — builder's <pre-loaded-context> block
117
- - **Journey-as-first-class-artifact** (NotebookLM synthesis of Qualia's own docs)
118
-
119
- Patterns deferred to v4.1+:
120
- - Visual/mockup generation (gstack design-shotgun, Superpowers Visual Companion)
121
- - Cross-model review (gstack /codex)
122
- - Cross-project vector memory (claude-mem, Claude-Flow)
123
- - IDE integration
124
- - Token-budget compression
125
-
126
- ## Verification at checkpoint
127
-
128
- ```
129
- ✅ Git 8 commits clean on feature/full-journey
130
- ✅ Tests 156/156 pass
131
- ✅ Smoke state transitions + close-milestone + milestones[] summary verified on scratch project
132
- ✅ UI journey-tree + milestone-complete render correctly with real fixtures
133
- ✅ Backward compat older tracking.json without milestones[]/milestone_name still passes state.js check
134
- ✅ No regressions Vs v3.6 baseline — all 150 existing tests still pass
135
- ✅ Package version 4.0.0, ready for `npm publish`
136
- ✅ Handoff V4_REVIEW.md written for next agent
137
- ```
138
-
139
- ## Pending (not done by this session)
140
-
141
- - **Git push** — both branches are local only
142
- - **Merge to main** — owner decides merge strategy (recommend v3.7.0 tag then v4.0.0 tag)
143
- - **`npm publish`** — requires owner auth
144
- - **Tag creation** — after merge
145
- - **Live auto-chain verification** — smoke tests covered state machine; the --auto chain (which spawns planner→builder→verifier subagents in sequence) wasn't exercised end-to-end. Recommended first real test is on a throwaway project post-publish.
146
- - **ERP-side updates** — v4 tracking.json fields are additive; ERP should accept them via its existing Zod strip-unknowns pattern, but worth verifying on deploy.
147
-
148
- ## Files the next reviewer should eyeball
149
-
150
- Priority order (highest leverage first):
151
-
152
- 1. `V4_REVIEW.md` — this file lives in repo root, written as the handoff doc
153
- 2. `CHANGELOG.md` [4.0.0] section — full feature list
154
- 3. `templates/journey.md` — new artifact schema
155
- 4. `agents/roadmapper.md` — biggest agent rewrite
156
- 5. `skills/qualia-new/SKILL.md` — core flow, 14 steps
157
- 6. `skills/qualia-idk/SKILL.md` — new diagnostic
158
- 7. `skills/qualia-verify/SKILL.md` — auto-chain decision table
159
- 8. `skills/qualia-handoff/SKILL.md` — 4 deliverables enforcement
160
- 9. `bin/state.js` close-milestone (~975-1050) — readiness guards + summary append
161
- 10. `bin/qualia-ui.js` journey-tree + milestone-complete functions
162
-
163
- ## Recommended publish sequence
164
-
165
- ```bash
166
- # Push both branches
167
- git push -u origin feature/story-file-plans
168
- git push -u origin feature/full-journey
169
-
170
- # Merge v3.7.0 to main, tag, push
171
- git checkout main
172
- git merge --ff-only feature/story-file-plans
173
- git tag v3.7.0
174
- git push origin main --tags
175
-
176
- # Merge v4.0.0 to main, tag, push
177
- git merge --ff-only feature/full-journey
178
- git tag v4.0.0
179
- git push origin main --tags
180
-
181
- # Publish
182
- npm publish
183
- npm view qualia-framework version # should return 4.0.0
184
- ```
185
-
186
- ## Known limitations / open questions
187
-
188
- 1. **Auto-chain not live-tested.** Unit tests cover state transitions; subagent chaining is covered by the skill prompt text but not exercised. First real project run will reveal edge cases.
189
- 2. **Milestone-summary `tasks_completed` accuracy** depends on lifetime counter deltas. Works if close-milestone is the only consumer — verified in test suite.
190
- 3. **/qualia-idk two-pass isolation** depends on Explore subagent respecting the "do not read .planning/" and "do not read source code" instructions. Prompt-level enforcement, not hard boundary.
191
- 4. **Builder pre-inline** inflates prompt size for monorepos with large DESIGN.md + multiple context files. Acceptable for most projects; could be optimized in v4.1.
192
-
193
- ## For questions
194
-
195
- Contact: Fawzi Goussous — fawzi@qualiasolutions.net
196
-
197
- ---
198
-
199
- *Written 2026-04-18 at release-candidate time. Supersedes the 2026-04-17 session report covering v3.4.2 / v3.5.0 / v3.6.0.*