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.
- package/README.md +50 -26
- package/agents/builder.md +8 -0
- package/agents/plan-checker.md +10 -1
- package/agents/planner.md +1 -1
- package/agents/qa-browser.md +10 -0
- package/agents/research-synthesizer.md +10 -0
- package/agents/researcher.md +38 -2
- package/agents/roadmapper.md +10 -0
- package/agents/verifier.md +15 -3
- package/agents/visual-evaluator.md +1 -1
- package/bin/install.js +42 -0
- package/bin/state.js +155 -133
- package/docs/archive/session-report-2026-04-18.md +199 -0
- package/docs/archive/v4.0.0-review.md +288 -0
- package/docs/instruction-budget-audit.md +113 -0
- package/guide.md +11 -4
- package/hooks/session-start.js +1 -1
- package/package.json +5 -2
- package/rules/architecture.md +125 -0
- package/rules/infrastructure.md +1 -2
- package/rules/speed.md +55 -0
- package/skills/qualia-help/SKILL.md +1 -1
- package/skills/qualia-map/SKILL.md +1 -1
- package/skills/qualia-milestone/SKILL.md +1 -1
- package/skills/qualia-new/SKILL.md +2 -2
- package/skills/qualia-optimize/REFERENCE.md +2 -2
- package/skills/qualia-optimize/SKILL.md +1 -1
- package/skills/qualia-polish/SKILL.md +3 -3
- package/skills/qualia-polish-loop/REFERENCE.md +1 -1
- package/skills/qualia-polish-loop/SKILL.md +3 -3
- package/skills/qualia-polish-loop/fixtures/broken.html +2 -2
- package/skills/qualia-polish-loop/scripts/score.mjs +1 -1
- package/skills/qualia-postmortem/SKILL.md +1 -1
- package/skills/qualia-quick/SKILL.md +1 -1
- package/skills/qualia-research/SKILL.md +5 -3
- package/skills/qualia-road/SKILL.md +15 -5
- package/skills/qualia-task/SKILL.md +1 -1
- package/templates/PRODUCT.md +1 -1
- package/tests/bin.test.sh +3 -3
- package/tests/skills.test.sh +143 -0
- package/tests/slop-detect.test.sh +160 -0
- /package/{rules → qualia-design}/design-brand.md +0 -0
- /package/{rules → qualia-design}/design-laws.md +0 -0
- /package/{rules → qualia-design}/design-product.md +0 -0
- /package/{rules → qualia-design}/design-reference.md +0 -0
- /package/{rules → qualia-design}/design-rubric.md +0 -0
- /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
|