qualia-framework 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +50 -26
  2. package/agents/builder.md +8 -0
  3. package/agents/plan-checker.md +10 -1
  4. package/agents/planner.md +1 -1
  5. package/agents/qa-browser.md +10 -0
  6. package/agents/research-synthesizer.md +10 -0
  7. package/agents/researcher.md +38 -2
  8. package/agents/roadmapper.md +10 -0
  9. package/agents/verifier.md +15 -3
  10. package/agents/visual-evaluator.md +1 -1
  11. package/bin/install.js +42 -0
  12. package/bin/state.js +155 -133
  13. package/docs/archive/session-report-2026-04-18.md +199 -0
  14. package/docs/archive/v4.0.0-review.md +288 -0
  15. package/docs/instruction-budget-audit.md +113 -0
  16. package/guide.md +11 -4
  17. package/hooks/session-start.js +1 -1
  18. package/package.json +5 -2
  19. package/rules/architecture.md +125 -0
  20. package/rules/infrastructure.md +1 -2
  21. package/rules/speed.md +55 -0
  22. package/skills/qualia-help/SKILL.md +1 -1
  23. package/skills/qualia-map/SKILL.md +1 -1
  24. package/skills/qualia-milestone/SKILL.md +1 -1
  25. package/skills/qualia-new/SKILL.md +2 -2
  26. package/skills/qualia-optimize/REFERENCE.md +2 -2
  27. package/skills/qualia-optimize/SKILL.md +1 -1
  28. package/skills/qualia-polish/SKILL.md +3 -3
  29. package/skills/qualia-polish-loop/REFERENCE.md +1 -1
  30. package/skills/qualia-polish-loop/SKILL.md +3 -3
  31. package/skills/qualia-polish-loop/fixtures/broken.html +2 -2
  32. package/skills/qualia-polish-loop/scripts/score.mjs +1 -1
  33. package/skills/qualia-postmortem/SKILL.md +1 -1
  34. package/skills/qualia-quick/SKILL.md +1 -1
  35. package/skills/qualia-research/SKILL.md +5 -3
  36. package/skills/qualia-road/SKILL.md +15 -5
  37. package/skills/qualia-task/SKILL.md +1 -1
  38. package/templates/PRODUCT.md +1 -1
  39. package/tests/bin.test.sh +3 -3
  40. package/tests/skills.test.sh +143 -0
  41. package/tests/slop-detect.test.sh +160 -0
  42. /package/{rules → qualia-design}/design-brand.md +0 -0
  43. /package/{rules → qualia-design}/design-laws.md +0 -0
  44. /package/{rules → qualia-design}/design-product.md +0 -0
  45. /package/{rules → qualia-design}/design-reference.md +0 -0
  46. /package/{rules → qualia-design}/design-rubric.md +0 -0
  47. /package/{rules → qualia-design}/frontend.md +0 -0
@@ -0,0 +1,160 @@
1
+ #!/bin/bash
2
+ # Qualia Framework — bin/slop-detect.mjs behavior tests
3
+ # Verifies the AI-tells gatekeeper actually catches what it claims to catch.
4
+ #
5
+ # Run: bash tests/slop-detect.test.sh
6
+
7
+ PASS=0
8
+ FAIL=0
9
+ SLOP_DETECT="$(cd "$(dirname "$0")/../bin" && pwd)/slop-detect.mjs"
10
+ NODE="${NODE:-node}"
11
+
12
+ TMP_DIRS=()
13
+ cleanup() {
14
+ for d in "${TMP_DIRS[@]}"; do
15
+ [ -d "$d" ] && rm -rf "$d"
16
+ done
17
+ }
18
+ trap cleanup EXIT
19
+
20
+ mktmp() {
21
+ local TMP
22
+ TMP=$(mktemp -d)
23
+ TMP_DIRS+=("$TMP")
24
+ echo "$TMP"
25
+ }
26
+
27
+ pass() {
28
+ echo " ✓ $1"
29
+ PASS=$((PASS + 1))
30
+ }
31
+
32
+ fail_case() {
33
+ echo " ✗ $1"
34
+ echo " $2"
35
+ FAIL=$((FAIL + 1))
36
+ }
37
+
38
+ echo "slop-detect.test.sh — bin/slop-detect.mjs behavioral tests"
39
+ echo ""
40
+
41
+ # ── Sanity: file exists and parses ────────────────────────────────────
42
+ if [ ! -f "$SLOP_DETECT" ]; then
43
+ fail_case "slop-detect exists" "$SLOP_DETECT not found"
44
+ echo "=== Results: $PASS passed, $FAIL failed ==="
45
+ exit 1
46
+ fi
47
+ pass "slop-detect.mjs exists at expected path"
48
+
49
+ if ! $NODE --check "$SLOP_DETECT" 2>&1 | head -1; then
50
+ pass "slop-detect.mjs parses as valid JS"
51
+ fi
52
+ # Above is a heredoc test — node --check succeeds silently on valid JS.
53
+ # Re-test explicitly so a parse error fails the suite.
54
+ if $NODE --check "$SLOP_DETECT" 2>/dev/null; then
55
+ pass "slop-detect.mjs syntax is valid"
56
+ else
57
+ fail_case "syntax check" "node --check failed on $SLOP_DETECT"
58
+ fi
59
+
60
+ # ── Clean file: should exit 0 ─────────────────────────────────────────
61
+ TMP=$(mktmp)
62
+ cat > "$TMP/clean.tsx" <<'EOF'
63
+ import { Button } from '@/components/ui/button';
64
+
65
+ export default function Page() {
66
+ return (
67
+ <div className="bg-surface text-foreground">
68
+ <h1 className="text-display">Welcome</h1>
69
+ <Button variant="primary">Continue setup</Button>
70
+ </div>
71
+ );
72
+ }
73
+ EOF
74
+ if $NODE "$SLOP_DETECT" "$TMP/clean.tsx" >/dev/null 2>&1; then
75
+ pass "exits 0 on a clean .tsx file"
76
+ else
77
+ fail_case "clean file" "exit non-zero on a deliberately clean file"
78
+ fi
79
+
80
+ # ── Em-dash detection (HIGH severity — reported, doesn't block) ──────
81
+ # Em-dash is HIGH not CRITICAL, so default exit is 0; we verify the
82
+ # FINDING is reported to stdout/stderr, not the exit code.
83
+ TMP2=$(mktmp)
84
+ cat > "$TMP2/emdash.tsx" <<'EOF'
85
+ export default function Page() {
86
+ return <p>Welcome — to our amazing platform</p>;
87
+ }
88
+ EOF
89
+ OUT=$($NODE "$SLOP_DETECT" "$TMP2/emdash.tsx" 2>&1 || true)
90
+ if echo "$OUT" | grep -qiE "em.?dash|—"; then
91
+ pass "reports em-dash finding (HIGH severity, non-blocking)"
92
+ else
93
+ fail_case "em-dash detection" "no em-dash mention in output: $(echo "$OUT" | head -c 120)"
94
+ fi
95
+
96
+ # ── Banned-font detection ─────────────────────────────────────────────
97
+ TMP3=$(mktmp)
98
+ cat > "$TMP3/font.css" <<'EOF'
99
+ body { font-family: "Inter", sans-serif; }
100
+ EOF
101
+ EXIT_CODE=0
102
+ $NODE "$SLOP_DETECT" "$TMP3/font.css" >/dev/null 2>&1 || EXIT_CODE=$?
103
+ if [ "$EXIT_CODE" = "1" ]; then
104
+ pass "exits 1 on banned font (Inter) in CSS"
105
+ else
106
+ fail_case "banned-font detection" "expected exit 1, got $EXIT_CODE"
107
+ fi
108
+
109
+ # ── Purple-blue gradient detection ────────────────────────────────────
110
+ TMP4=$(mktmp)
111
+ cat > "$TMP4/gradient.tsx" <<'EOF'
112
+ export default function Hero() {
113
+ return <div className="bg-gradient-to-r from-blue-500 to-purple-600">Hi</div>;
114
+ }
115
+ EOF
116
+ EXIT_CODE=0
117
+ $NODE "$SLOP_DETECT" "$TMP4/gradient.tsx" >/dev/null 2>&1 || EXIT_CODE=$?
118
+ if [ "$EXIT_CODE" = "1" ]; then
119
+ pass "exits 1 on purple-blue gradient (the #1 AI-design tell)"
120
+ else
121
+ fail_case "gradient detection" "expected exit 1, got $EXIT_CODE"
122
+ fi
123
+
124
+ # ── Existing fixture: skills/qualia-polish-loop/fixtures/broken.html ──
125
+ FIXTURE="$(cd "$(dirname "$0")/.." && pwd)/skills/qualia-polish-loop/fixtures/broken.html"
126
+ if [ -f "$FIXTURE" ]; then
127
+ EXIT_CODE=0
128
+ $NODE "$SLOP_DETECT" "$FIXTURE" >/dev/null 2>&1 || EXIT_CODE=$?
129
+ if [ "$EXIT_CODE" = "1" ]; then
130
+ pass "exits 1 on the broken.html fixture (designed to hit critical bans)"
131
+ else
132
+ fail_case "fixture detection" "broken.html fixture exited $EXIT_CODE; expected 1"
133
+ fi
134
+ else
135
+ echo " - broken.html fixture not present, skipping"
136
+ fi
137
+
138
+ # ── --json flag produces JSON output ─────────────────────────────────
139
+ TMP5=$(mktmp)
140
+ cp "$TMP3/font.css" "$TMP5/font.css"
141
+ JSON_OUT=$($NODE "$SLOP_DETECT" --json "$TMP5/font.css" 2>/dev/null || true)
142
+ if echo "$JSON_OUT" | head -1 | grep -qE "^[\{\[]"; then
143
+ pass "--json flag produces JSON-shaped output"
144
+ else
145
+ fail_case "--json output" "first line is not JSON-shaped: '$(echo "$JSON_OUT" | head -c 80)'"
146
+ fi
147
+
148
+ # ── Invocation error: no path provided AND no default repo ───────────
149
+ EXIT_CODE=0
150
+ $NODE "$SLOP_DETECT" /nonexistent/path/that/cannot/exist >/dev/null 2>&1 || EXIT_CODE=$?
151
+ if [ "$EXIT_CODE" = "2" ] || [ "$EXIT_CODE" = "0" ]; then
152
+ pass "handles missing path gracefully (exit=$EXIT_CODE — 0=skip, 2=invocation error)"
153
+ else
154
+ fail_case "missing path" "unexpected exit $EXIT_CODE on /nonexistent path"
155
+ fi
156
+
157
+ echo ""
158
+ echo "=== Results: $PASS passed, $FAIL failed ==="
159
+
160
+ [ "$FAIL" = "0" ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes