qualia-framework 6.2.10 → 6.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 (78) hide show
  1. package/AGENTS.md +8 -7
  2. package/CLAUDE.md +5 -4
  3. package/README.md +27 -56
  4. package/bin/cli.js +113 -18
  5. package/bin/command-surface.js +75 -0
  6. package/bin/harness-eval.js +296 -0
  7. package/bin/install.js +43 -31
  8. package/bin/knowledge-flush.js +21 -10
  9. package/bin/knowledge.js +1 -1
  10. package/bin/learning-candidates.js +217 -0
  11. package/bin/project-snapshot.js +20 -0
  12. package/bin/prune-deprecated.js +64 -0
  13. package/bin/report-payload.js +18 -0
  14. package/bin/runtime-manifest.js +7 -0
  15. package/bin/security-scan.js +409 -0
  16. package/bin/state.js +31 -0
  17. package/bin/status-snapshot.js +363 -0
  18. package/bin/trust-score.js +3 -11
  19. package/bin/work-packet.js +228 -0
  20. package/docs/erp-contract.md +81 -1
  21. package/docs/onboarding.html +0 -11
  22. package/guide.md +15 -38
  23. package/hooks/fawzi-approval-guard.js +143 -0
  24. package/hooks/pre-compact.js +232 -0
  25. package/hooks/pre-deploy-gate.js +74 -1
  26. package/hooks/session-start.js +29 -1
  27. package/package.json +1 -1
  28. package/qualia-design/frontend.md +2 -2
  29. package/rules/codex-goal.md +1 -1
  30. package/rules/one-opinion.md +2 -2
  31. package/rules/speed.md +0 -1
  32. package/skills/qualia/SKILL.md +4 -4
  33. package/skills/qualia-build/SKILL.md +1 -1
  34. package/skills/qualia-discuss/SKILL.md +1 -1
  35. package/skills/qualia-doctor/SKILL.md +1 -1
  36. package/skills/qualia-feature/SKILL.md +2 -2
  37. package/skills/qualia-fix/SKILL.md +4 -4
  38. package/skills/qualia-idk/SKILL.md +133 -54
  39. package/skills/qualia-learn/SKILL.md +2 -2
  40. package/skills/qualia-map/SKILL.md +1 -1
  41. package/skills/qualia-milestone/SKILL.md +1 -1
  42. package/skills/qualia-new/SKILL.md +1 -1
  43. package/skills/qualia-optimize/SKILL.md +1 -1
  44. package/skills/qualia-plan/SKILL.md +1 -1
  45. package/skills/qualia-polish/REFERENCE.md +1 -1
  46. package/skills/qualia-polish/SKILL.md +19 -4
  47. package/skills/{qualia-vibe/scripts/extract.mjs → qualia-polish/scripts/vibe-extract.mjs} +4 -4
  48. package/skills/{qualia-vibe/scripts/tokens.mjs → qualia-polish/scripts/vibe-tokens.mjs} +6 -6
  49. package/skills/qualia-postmortem/SKILL.md +1 -1
  50. package/skills/qualia-report/SKILL.md +1 -1
  51. package/skills/qualia-research/SKILL.md +1 -1
  52. package/skills/qualia-review/SKILL.md +1 -1
  53. package/skills/qualia-road/SKILL.md +15 -20
  54. package/skills/qualia-secure/SKILL.md +105 -0
  55. package/skills/qualia-ship/SKILL.md +12 -5
  56. package/skills/qualia-test/SKILL.md +1 -1
  57. package/skills/qualia-verify/SKILL.md +10 -2
  58. package/skills/zoho-workflow/SKILL.md +1 -1
  59. package/templates/help.html +1 -12
  60. package/tests/bin.test.sh +147 -75
  61. package/tests/hooks.test.sh +81 -1
  62. package/tests/install-smoke.test.sh +14 -4
  63. package/tests/lib.test.sh +145 -3
  64. package/tests/published-install-smoke.test.sh +5 -4
  65. package/tests/refs.test.sh +32 -20
  66. package/tests/runner.js +30 -29
  67. package/tests/state.test.sh +106 -7
  68. package/skills/qualia-debug/SKILL.md +0 -193
  69. package/skills/qualia-flush/SKILL.md +0 -198
  70. package/skills/qualia-help/SKILL.md +0 -74
  71. package/skills/qualia-hook-gen/SKILL.md +0 -206
  72. package/skills/qualia-issues/SKILL.md +0 -151
  73. package/skills/qualia-pause/SKILL.md +0 -68
  74. package/skills/qualia-resume/SKILL.md +0 -52
  75. package/skills/qualia-skill-new/SKILL.md +0 -173
  76. package/skills/qualia-triage/SKILL.md +0 -152
  77. package/skills/qualia-vibe/SKILL.md +0 -229
  78. package/skills/qualia-zoom/SKILL.md +0 -51
@@ -4,9 +4,40 @@
4
4
 
5
5
  PASS=0
6
6
  FAIL=0
7
- # Resolve STATE_JS to an ABSOLUTE path so `cd` inside subshells doesn't break it.
8
- STATE_JS="$(cd "$(dirname "$0")/../bin" && pwd)/state.js"
9
- FRAMEWORK_DIR="$(cd "$(dirname "$0")/.." && pwd)"
7
+ # Windows portability coerce shell-native MSYS paths (/d/a/..., /tmp/...) to
8
+ # Windows-native form (D:/a/..., C:/Users/.../Temp/...) before they get
9
+ # interpolated into Node `$NODE -e` snippets. Without coercion, Node receives
10
+ # the MSYS string literally and resolves it against the current drive, yielding
11
+ # non-existent paths like `D:\tmp\tmp.XXX\.planning\tracking.json`.
12
+ #
13
+ # Mechanism: `cygpath -m` is the canonical MSYS path converter and is present
14
+ # on Git Bash / MSYS2 (Windows GitHub runners use Git Bash for `shell: bash`).
15
+ # `pwd -W` doesn't work because bash's builtin pwd doesn't accept -W, and
16
+ # /usr/bin/pwd's -W support varies by MSYS distribution.
17
+ # On Linux/macOS, cygpath doesn't exist — fall through to plain pwd.
18
+ _pwd_native() {
19
+ local p
20
+ p=$(pwd)
21
+ if command -v cygpath >/dev/null 2>&1; then
22
+ cygpath -m "$p" 2>/dev/null || echo "$p"
23
+ else
24
+ echo "$p"
25
+ fi
26
+ }
27
+ _mktemp_native() {
28
+ local d
29
+ d=$(mktemp -d) || return 1
30
+ if command -v cygpath >/dev/null 2>&1; then
31
+ cygpath -m "$d" 2>/dev/null || echo "$d"
32
+ else
33
+ echo "$d"
34
+ fi
35
+ }
36
+
37
+ # Resolve STATE_JS to an ABSOLUTE Windows-native path so `cd` inside subshells
38
+ # doesn't break it.
39
+ STATE_JS="$(cd "$(dirname "$0")/../bin" && _pwd_native)/state.js"
40
+ FRAMEWORK_DIR="$(cd "$(dirname "$0")/.." && _pwd_native)"
10
41
  STATE_LEDGER_JS="$FRAMEWORK_DIR/bin/state-ledger.js"
11
42
  NODE="${NODE:-node}"
12
43
 
@@ -23,7 +54,7 @@ trap cleanup EXIT
23
54
  # Prints the absolute path to the new tmp dir (does NOT cd).
24
55
  make_project() {
25
56
  local TMP
26
- TMP=$(mktemp -d)
57
+ TMP=$(_mktemp_native)
27
58
  TMP_DIRS+=("$TMP")
28
59
  (
29
60
  cd "$TMP" || exit 1
@@ -75,6 +106,47 @@ Goal: Test goal
75
106
  PLAN
76
107
  }
77
108
 
109
+ make_valid_contract() {
110
+ local dir="$1"
111
+ local phase="${2:-1}"
112
+ cat > "$dir/.planning/phase-${phase}-contract.json" <<'JSON'
113
+ {
114
+ "version": 1,
115
+ "phase": 1,
116
+ "goal": "Test goal",
117
+ "why": "Exercise machine evidence",
118
+ "generated_at": "2026-05-23T00:00:00.000Z",
119
+ "generated_by": "manual",
120
+ "source_plan_hash": "",
121
+ "success_criteria": ["Machine check passes"],
122
+ "tasks": [
123
+ {
124
+ "id": "T1",
125
+ "title": "Machine check",
126
+ "wave": 1,
127
+ "depends_on": [],
128
+ "persona": "none",
129
+ "files_modify": [],
130
+ "files_create": [],
131
+ "files_delete": [],
132
+ "acceptance_criteria": ["Node command exits 0"],
133
+ "action": "Run deterministic evidence check",
134
+ "context_files": [],
135
+ "verification": [
136
+ {
137
+ "type": "command-exit",
138
+ "command": "node",
139
+ "args": ["-e", "process.exit(0)"],
140
+ "expected_exit": 0,
141
+ "timeout_ms": 5000
142
+ }
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ JSON
148
+ }
149
+
78
150
  echo "=== state.js Behavioral Tests ==="
79
151
  echo ""
80
152
 
@@ -88,7 +160,7 @@ fi
88
160
  echo "basic I/O:"
89
161
 
90
162
  # 1. cmdInit produces valid tracking.json + STATE.md
91
- TMP=$(mktemp -d); TMP_DIRS+=("$TMP")
163
+ TMP=$(_mktemp_native); TMP_DIRS+=("$TMP")
92
164
  (
93
165
  cd "$TMP" || exit 1
94
166
  $NODE "$STATE_JS" init \
@@ -149,7 +221,7 @@ else
149
221
  fi
150
222
 
151
223
  # 3. cmdCheck with no project → ok:false NO_PROJECT, exit 1
152
- TMP2=$(mktemp -d); TMP_DIRS+=("$TMP2")
224
+ TMP2=$(_mktemp_native); TMP_DIRS+=("$TMP2")
153
225
  OUT=$(cd "$TMP2" && $NODE "$STATE_JS" check 2>&1)
154
226
  CHECK_EXIT=$?
155
227
  if [ "$CHECK_EXIT" -eq 1 ] \
@@ -213,6 +285,33 @@ else
213
285
  fail_case "built → verified(pass) auto-advance" "exit=$EXIT out=$OUT"
214
286
  fi
215
287
 
288
+ # 6b. verified(pass) refuses when a contract exists but machine evidence is missing
289
+ TMP=$(make_project)
290
+ make_valid_plan "$TMP" 1
291
+ make_valid_contract "$TMP" 1
292
+ (cd "$TMP" && $NODE "$STATE_JS" transition --to planned >/dev/null 2>&1)
293
+ (cd "$TMP" && $NODE "$STATE_JS" transition --to built --tasks-done 1 --tasks-total 1 >/dev/null 2>&1)
294
+ echo "result: PASS" > "$TMP/.planning/phase-1-verification.md"
295
+ OUT=$(cd "$TMP" && $NODE "$STATE_JS" transition --to verified --verification pass 2>&1)
296
+ EXIT=$?
297
+ if [ "$EXIT" -ne 0 ] && echo "$OUT" | grep -q '"error": "MISSING_EVIDENCE"'; then
298
+ pass "verified(pass) refuses missing machine evidence when contract exists"
299
+ else
300
+ fail_case "verified(pass) missing evidence guard" "exit=$EXIT out=$OUT"
301
+ fi
302
+
303
+ # 6c. verified(pass) succeeds after contract-runner writes passing evidence
304
+ (cd "$TMP" && $NODE "$FRAMEWORK_DIR/bin/contract-runner.js" .planning/phase-1-contract.json >/dev/null 2>&1)
305
+ OUT=$(cd "$TMP" && $NODE "$STATE_JS" transition --to verified --verification pass 2>&1)
306
+ EXIT=$?
307
+ if [ "$EXIT" -eq 0 ] \
308
+ && echo "$OUT" | grep -q '"ok": true' \
309
+ && echo "$OUT" | grep -q '"phase": 2'; then
310
+ pass "verified(pass) accepts passing machine evidence"
311
+ else
312
+ fail_case "verified(pass) with machine evidence" "exit=$EXIT out=$OUT"
313
+ fi
314
+
216
315
  # 7. built → verified(fail) stays on phase 1, records verification=fail
217
316
  TMP=$(make_project)
218
317
  make_valid_plan "$TMP" 1
@@ -946,7 +1045,7 @@ else
946
1045
  fi
947
1046
 
948
1047
  # 49. First-time init (no existing tracking.json) sets lifetime to zeros
949
- TMP=$(mktemp -d); TMP_DIRS+=("$TMP")
1048
+ TMP=$(_mktemp_native); TMP_DIRS+=("$TMP")
950
1049
  (cd "$TMP" && $NODE "$STATE_JS" init \
951
1050
  --project "FreshProject" \
952
1051
  --phases '[{"name":"P1","goal":"G1"}]' \
@@ -1,193 +0,0 @@
1
- ---
2
- name: qualia-debug
3
- description: "Investigation lane for unclear bugs and weird behavior. Parses symptoms, runs diagnostic scans, identifies root cause, and either reports insufficient evidence or routes actionable repair work to /qualia-fix. Trigger on 'debug', 'find bug', 'why is this broken', 'something is weird', 'investigate', 'root cause', 'not sure what's failing', 'CSS issue', 'slow page', 'performance'."
4
- allowed-tools:
5
- - Bash
6
- - Read
7
- - Edit
8
- - Write
9
- - Grep
10
- - Glob
11
- - Agent
12
- ---
13
-
14
- # /qualia-debug — Investigative Debugging (one-shot)
15
-
16
- Parse the symptom. Run diagnostics. Find root cause. Write report, or route to `/qualia-fix` when the repair is actionable. **One-shot — no mandatory user questions.**
17
-
18
- ## Usage
19
-
20
- - `/qualia-debug {symptom}` — investigate a specific symptom
21
- - `/qualia-debug` — no symptom given: investigate recently-changed files for obvious bugs
22
- - `/qualia-debug --frontend {symptom}` — layout/z-index/overflow bias
23
- - `/qualia-debug --perf {symptom}` — performance bias
24
-
25
- If the user says "fix it" and the expected behavior is known, prefer `/qualia-fix`. Debug is for uncertainty; fix is for repair.
26
-
27
- ## Tool Budget
28
-
29
- Max 10 Read/Grep/Bash calls for investigation. If you haven't narrowed to root cause in 10, return `INSUFFICIENT EVIDENCE after 10 steps. Narrowed to: {files}. Recommend: {next diagnostic}.` Do not keep guessing.
30
-
31
- ## Process
32
-
33
- ```bash
34
- node ${QUALIA_BIN}/qualia-ui.js banner debug
35
- ```
36
-
37
- ### 1. Parse Symptom from $ARGUMENTS
38
-
39
- - If arguments provided → that's the symptom. Extract: what's broken, where (file/page/feature), when (on click? on load? after change?).
40
- - If arguments empty → run `git diff HEAD~3 --stat` to find recently-touched files. Treat those as the suspect set. Symptom = "something in recent changes".
41
-
42
- ### 2. Check Known Fixes First (cheap)
43
-
44
- ```bash
45
- node ${QUALIA_BIN}/knowledge.js search "{symptom_keywords}"
46
- ```
47
-
48
- If a known fix matches, apply it and jump to step 5 (verify). Known fixes are pre-verified patterns — no need to re-investigate.
49
-
50
- ### 3. Diagnostic Scan
51
-
52
- Run the scan matching the symptom type. All commands in a scan block run as parallel Bash calls in a single response turn.
53
-
54
- **General mode (default):**
55
- ```bash
56
- # Compile errors
57
- npx tsc --noEmit 2>&1 | grep "error TS" | head -20
58
-
59
- # Empty catch / swallowed errors
60
- grep -rn "catch\s*{}\|catch\s*(.*)\s*{\s*}" --include="*.ts" --include="*.tsx" app/ components/ src/ lib/ 2>/dev/null | head -10
61
-
62
- # Recent console.error or thrown errors
63
- grep -rn "console\.error\|throw new" --include="*.ts" --include="*.tsx" app/ components/ src/ lib/ 2>/dev/null | head -10
64
-
65
- # Broken imports
66
- npx tsc --noEmit 2>&1 | grep -i "Cannot find module\|has no exported"
67
- ```
68
-
69
- **Frontend mode (`--frontend`):**
70
- ```bash
71
- # Stacking context audit (z-index issues)
72
- grep -rn "z-index\|z-\[" --include="*.tsx" --include="*.css" app/ components/ src/ 2>/dev/null | head -20
73
-
74
- # Overflow candidates (horizontal scroll, clipping)
75
- grep -rn "100vw\|overflow.*hidden\|overflow-x\|position.*fixed" --include="*.tsx" --include="*.css" app/ components/ src/ 2>/dev/null | head -15
76
-
77
- # Fixed dimensions breaking mobile
78
- grep -rn "width:.*[0-9]\+px\|height:.*[0-9]\+px\|w-\[[0-9]\+px\|h-\[[0-9]\+px" --include="*.tsx" --include="*.css" app/ components/ src/ 2>/dev/null | grep -v "min-\|max-" | head -10
79
-
80
- # Flex/grid blowout candidates
81
- grep -rn "flex\|grid" --include="*.tsx" app/ components/ src/ 2>/dev/null | grep -v "min-w-0\|minmax(0" | wc -l
82
- ```
83
-
84
- **Perf mode (`--perf`):**
85
- ```bash
86
- # Sequential awaits that should be Promise.all
87
- grep -rn "const.*=.*await" --include="*.tsx" --include="*.ts" app/ src/ 2>/dev/null | grep -v "Promise.all\|Promise.allSettled" | head -15
88
-
89
- # Large files
90
- find app/ components/ src/ -name "*.tsx" -o -name "*.ts" 2>/dev/null | xargs wc -l 2>/dev/null | sort -rn | head -10
91
-
92
- # Missing next/image
93
- grep -rn "<img " --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | grep -v "next/image" | wc -l
94
-
95
- # No dynamic imports (possible big bundles)
96
- grep -rn "import(\|next/dynamic" --include="*.tsx" --include="*.ts" app/ src/ 2>/dev/null | wc -l
97
-
98
- # Client-boundary usage
99
- grep -rln "'use client'" --include="*.tsx" app/ components/ src/ 2>/dev/null | wc -l
100
- ```
101
-
102
- ### 4. Form Hypothesis + Route or Apply Minimal Fix
103
-
104
- From the diagnostic output, state the root cause in one sentence with `file:line` citation. No hedging — either you have evidence or you write `INSUFFICIENT EVIDENCE` and return (step 6).
105
-
106
- If the user explicitly asked for repair and the fix is <= 3 files, route to `/qualia-fix {symptom}` with the root cause summary. If this debug invocation is already mid-repair, apply the minimal fix here for backward compatibility.
107
-
108
- Apply the minimal fix:
109
- - Only edit files whose contents caused the symptom
110
- - One concept per commit — don't fold in cleanup
111
- - Don't refactor adjacent code
112
- - If the fix touches > 3 files, stop and ask the user first (major refactor disguised as a debug)
113
-
114
- ### 5. Verify Fix
115
-
116
- ```bash
117
- # TypeScript still compiles?
118
- npx tsc --noEmit 2>&1 | grep -c "error TS" # Expect 0
119
-
120
- # Symptom reproduction — ideally a grep that would have matched the bug
121
- # and now returns empty:
122
- grep -rn "{pattern that represented the bug}" {scope} 2>/dev/null
123
- ```
124
-
125
- If the verification fails, revert and return to step 3 with narrower hypothesis.
126
-
127
- ### 6. Write DEBUG Report
128
-
129
- Create the report directory and write to `.planning/reports/debug/DEBUG-{YYYY-MM-DD-HHMM}.md`:
130
-
131
- ```bash
132
- mkdir -p .planning/reports/debug
133
- ```
134
-
135
- ```markdown
136
- # Debug Report — {YYYY-MM-DD HH:MM}
137
-
138
- **Symptom:** {user description or "recent changes" if no args}
139
- **Mode:** general | frontend | perf
140
- **Tool calls used:** {N}/10
141
-
142
- ## Investigation
143
- - Diagnostic scans run: {list}
144
- - Files examined: {list}
145
- - Patterns searched: {list}
146
-
147
- ## Root Cause
148
- {file:line} — "{quoted problematic code}" — {explanation of why it caused the symptom}
149
-
150
- ## Fix Applied
151
- - Files: {list}
152
- - Diff summary: {one paragraph}
153
- - Verification: {commands run + results}
154
-
155
- ## Related Observations
156
- - {any adjacent issues noticed but NOT fixed in this debug pass}
157
- ```
158
-
159
- ### 7. Commit
160
-
161
- ```bash
162
- git add {specific files you changed}
163
- git commit -m "fix: {what was broken and why}"
164
- ```
165
-
166
- ## INSUFFICIENT EVIDENCE Return
167
-
168
- If you exhaust the 10-call budget without a confident root cause:
169
-
170
- ```markdown
171
- # Debug Report — {YYYY-MM-DD HH:MM}
172
-
173
- **Symptom:** {description}
174
- **Outcome:** INSUFFICIENT EVIDENCE after 10 inspection steps
175
-
176
- ## Narrowed To
177
- - Files examined: {list}
178
- - Ruled out: {list}
179
- - Remaining suspects: {list}
180
-
181
- ## Recommended Next Diagnostic
182
- - {specific next step for the user — e.g., "run `npm run dev` and watch browser console for the specific error", or "add console.log at file:line and reproduce"}
183
- ```
184
-
185
- Do NOT apply a speculative fix. Return the report and stop.
186
-
187
- ## Rules
188
-
189
- - **No mandatory questions.** This is one-shot. If symptom args are missing, investigate recent changes.
190
- - **Root cause or INSUFFICIENT EVIDENCE** — no "probably" fixes.
191
- - **Minimal fix only.** One concept, one commit. No refactors dressed as debug. Prefer `/qualia-fix` for explicit repair requests.
192
- - **Tool budget is hard.** 10 calls, then stop.
193
- - **Every investigation gets a DEBUG report in `.planning/reports/debug/`** — creates a searchable record without cluttering the root.
@@ -1,198 +0,0 @@
1
- ---
2
- name: qualia-flush
3
- description: "Promote daily-log raw entries to the curated knowledge tier — Karpathy-style raw→wiki flush. Reads ${QUALIA_KNOWLEDGE}/daily-log/*.md, identifies recurring patterns and decisions, writes them to ${QUALIA_KNOWLEDGE}/concepts/{topic}.md, updates index.md. Trigger on 'flush memory', 'promote learnings', 'consolidate logs', 'qualia-flush', 'process daily logs', or run weekly."
4
- allowed-tools:
5
- - Bash
6
- - Read
7
- - Write
8
- - Edit
9
- - Grep
10
- - Glob
11
- ---
12
-
13
- # /qualia-flush — Promote Raw Daily Logs to Curated Concepts
14
-
15
- Closes the **raw → wiki** loop in the Qualia memory layer. The Stop hook
16
- (`hooks/stop-session-log.js`) appends mechanical session checkpoints to
17
- `${QUALIA_KNOWLEDGE}/daily-log/{date}.md`.
18
- Those entries accumulate but stay raw — they describe what happened, not
19
- what to do about it. This skill reads the recent daily-log entries with an
20
- LLM (you) and writes durable concepts that the builder, planner, and
21
- debug skills will surface later via `node ${QUALIA_BIN}/knowledge.js`.
22
-
23
- Inspired by Karpathy's LLM knowledge bases and Cole Medin's self-evolving
24
- Claude memory pattern (NotebookLM, 2026-04-25). Both run a daily/weekly
25
- flush that promotes raw observations into structured wiki articles. We do
26
- the same — manually-triggered, internal-data only, no vector DB.
27
-
28
- ## When to run
29
-
30
- - **Manually:** `/qualia-flush` whenever the daily-log feels rich. Once a week
31
- is the recommended cadence. More than once a day is wasteful — the
32
- signal-to-noise ratio is too low at single-day windows.
33
- - **CLI runner:** `qualia-framework flush` wraps the cron-friendly
34
- `bin/knowledge-flush.js` non-interactive runner.
35
-
36
- ## Inputs
37
-
38
- - `--days N` (optional, default 14) — how many days of daily-log to consider
39
- - `--project NAME` (optional) — only flush entries for one project
40
- - `--dry-run` (optional) — print the proposed writes, don't touch disk
41
-
42
- If the user invokes the skill bare (no args), default to `--days 14` and
43
- all projects. Show a one-line preview before writing anything destructive.
44
-
45
- ## Process
46
-
47
- ### 1. Banner + check the floor
48
-
49
- ```bash
50
- node ${QUALIA_BIN}/qualia-ui.js banner flush 2>/dev/null || true
51
-
52
- # Resolve the knowledge dir. Fail loud if it doesn't exist — flush is
53
- # meaningless without a daily-log to read.
54
- KNOWLEDGE_DIR="$HOME/.claude/knowledge"
55
- DAILY_DIR="$KNOWLEDGE_DIR/daily-log"
56
- if [ ! -d "$DAILY_DIR" ]; then
57
- echo "QUALIA: No daily-log at $DAILY_DIR — Stop hook hasn't run yet, or knowledge layer wasn't initialized."
58
- echo "Run: npx qualia-framework@latest install"
59
- exit 1
60
- fi
61
-
62
- # Default 14-day window. Date math is cross-platform-safe with Node.
63
- WINDOW_DAYS="${WINDOW_DAYS:-14}"
64
- node -e "
65
- const d = new Date();
66
- d.setDate(d.getDate() - $WINDOW_DAYS);
67
- console.log(d.toISOString().split('T')[0]);
68
- " > /tmp/qualia-flush-cutoff
69
- CUTOFF=$(cat /tmp/qualia-flush-cutoff)
70
- ```
71
-
72
- ### 2. Collect the daily-log entries in window
73
-
74
- ```bash
75
- # Iterate every file in daily-log/ whose name (YYYY-MM-DD.md) is >= CUTOFF.
76
- # Concatenate them into one stream so the LLM (you) can scan as one corpus.
77
- ls "$DAILY_DIR"/*.md 2>/dev/null | while read -r f; do
78
- base=$(basename "$f" .md)
79
- if [ "$base" \> "$CUTOFF" ] || [ "$base" = "$CUTOFF" ]; then
80
- echo "=== $base ==="
81
- cat "$f"
82
- echo ""
83
- fi
84
- done
85
- ```
86
-
87
- You now have the raw stream. Read it.
88
-
89
- ### 3. Identify what's worth promoting
90
-
91
- Read every entry. Group by project. Look for these signals — these are
92
- the things that promote into the wiki:
93
-
94
- | Signal in raw entry | What to extract | Goes to |
95
- |---|---|---|
96
- | Same fix appears in 2+ sessions | A common fix recipe | `common-fixes.md` (via `knowledge.js append --type fix`) |
97
- | A pattern shows up in 3+ projects | A reusable pattern | `learned-patterns.md` (via `knowledge.js append --type pattern`) |
98
- | A client-name or project preference recurs | A client preference | `client-prefs.md` (via `knowledge.js append --type client`) |
99
- | A new technology/library used successfully | A stack note | `concepts/{tech}.md` (new file, Write directly) |
100
- | A recurring failure mode (verify-fail, regression) | A pitfall | `learned-patterns.md` framed as "anti-pattern: …" |
101
-
102
- Things to **NOT** promote:
103
- - Single-occurrence quirks (they're noise until they recur).
104
- - Bare commit/branch info — that's already in git, no value duplicating.
105
- - Anything containing secrets, tokens, customer PII. The knowledge layer
106
- is plain markdown, never put secrets here.
107
- - Entries from `--dry-run` runs of other skills (they'll show as activity
108
- but didn't actually do anything).
109
-
110
- ### 4. Write the promotions
111
-
112
- For each thing worth promoting, use the loader's `append`:
113
-
114
- ```bash
115
- node ${QUALIA_BIN}/knowledge.js append \
116
- --type {pattern|fix|client} \
117
- --title "{Concise title — what's the recurring thing?}" \
118
- --body "{The promoted lesson. Be specific. Include the project name(s) and dates where this pattern was observed so future you can verify.}" \
119
- --project "{specific project, or 'general' if cross-project}" \
120
- --context "Promoted by /qualia-flush from daily-log entries on {dates}"
121
- ```
122
-
123
- For a brand-new topic that doesn't fit pattern/fix/client (e.g. a Stripe
124
- integration approach worth its own file), Write to
125
- `${QUALIA_KNOWLEDGE}/concepts/{topic}.md`. Then **update `index.md`** so the
126
- new file is reachable — list it under "What's where" with one line:
127
-
128
- ```bash
129
- # After writing concepts/stripe-checkout.md:
130
- node ${QUALIA_BIN}/knowledge.js path stripe-checkout
131
- # Returned path = ${QUALIA_KNOWLEDGE}/stripe-checkout.md (NOTE: top-level, not concepts/)
132
- ```
133
-
134
- > **Loader behavior:** `knowledge.js load <name>` resolves bare names by walking
135
- > top-level + subdirectories (`concepts/`, `daily-log/`) for an exact match.
136
- > Write durable entries to `concepts/{topic}.md`; the loader will find them.
137
-
138
- ### 5. Mark the window as flushed
139
-
140
- Write a stamp file so subsequent flushes can default to "since the last
141
- flush" instead of "last 14 days":
142
-
143
- ```bash
144
- date -u +%Y-%m-%dT%H:%M:%SZ > "$HOME/.claude/.qualia-last-flush"
145
- ```
146
-
147
- ### 6. Summarize
148
-
149
- Print to the user, in plain language:
150
-
151
- - N daily-log files scanned (date range)
152
- - M promotions written (with file:title for each)
153
- - K things considered but not promoted (single-occurrence — wait for them to recur)
154
-
155
- Format:
156
-
157
- ```
158
- ⬢ Flushed daily-log {start} → {end} ({N} files, {total entries} entries)
159
- Promoted to wiki:
160
- + learned-patterns.md "Supabase RLS in same migration" (3 sessions, 2 projects)
161
- + common-fixes.md "next/font crash on Vercel" (2 sessions)
162
- + concepts/voice-agent-call-state.md (new file)
163
- Skipped {K} single-occurrence entries — will revisit if they recur.
164
- ```
165
-
166
- ## Style
167
-
168
- - **Be conservative.** False-positive promotions (writing noise as if it's a
169
- pattern) pollute the wiki and erode trust. Better to skip a candidate and
170
- let it recur next week than to inflate the curated tier.
171
- - **Cite your sources.** Every promoted entry should reference the
172
- daily-log dates that sourced it, in the `--context` field. If a future
173
- flush wants to update it, the trail is there.
174
- - **Keep titles short.** `--title "Supabase RLS same migration"` not `"You should always remember that when working with Supabase you need to..."`. The body is for nuance.
175
- - **Don't promote private projects across boundaries.** A pattern from
176
- Project A is fine to promote as cross-project ONLY if it generalizes.
177
- Client-specific things stay client-specific (`--type client --project X`).
178
-
179
- ## Anti-patterns
180
-
181
- - **Mass-promoting everything:** if you found "promotions" for 90% of
182
- daily-log entries, you're labeling, not promoting. Be selective.
183
- - **Re-promoting on every flush:** before appending, run
184
- `node ${QUALIA_BIN}/knowledge.js search "{title keywords}"` to check if
185
- the pattern already exists. If it does, either update it (find by `**ID:**`
186
- line) or skip — never duplicate.
187
- - **Hand-writing to `learned-patterns.md` etc. directly:** always go
188
- through `knowledge.js append` so the canonical entry format and ID
189
- generation stay consistent. This skill is the only sanctioned promoter,
190
- but even it uses the loader for writes.
191
-
192
- ## Output contract
193
-
194
- If invoked with `--dry-run`, print the proposed writes and exit without
195
- touching disk. Otherwise, after step 6 returns the summary, the skill is
196
- done — no follow-up prompts. The user sees the summary and the wiki tier
197
- has new entries that are immediately reachable to every other skill via
198
- the loader.
@@ -1,74 +0,0 @@
1
- ---
2
- name: qualia-help
3
- description: "Open the BROWSER HTML reference for the Qualia Framework — themed page with all commands, rules, services, and the road. The default when a browser is available. For terminal-only output (SSH, headless), use /qualia-road. Triggers: 'help', 'how does this work', 'show me the commands', 'qualia help', 'reference', 'open the docs'."
4
- allowed-tools:
5
- - Bash
6
- - Read
7
- ---
8
-
9
- # /qualia-help — Framework Reference
10
-
11
- Opens a Qualia-themed HTML reference guide in your default browser.
12
-
13
- ## Process
14
-
15
- ### 1. Generate the HTML
16
-
17
- ```bash
18
- # Read the template and inject the current version.
19
- # Prefer .qualia-config.json; fall back to the framework package.json; last resort is the
20
- # literal string "latest" so the UI never lies about a specific version.
21
- VERSION=$(node -e "
22
- const fs = require('fs'), path = require('path'), os = require('os');
23
- const cfg = path.join(os.homedir(), '.claude', '.qualia-config.json');
24
- const pkg = path.join(os.homedir(), '.claude', 'qualia-framework', 'package.json');
25
- try { const v = JSON.parse(fs.readFileSync(cfg,'utf8')).version; if (v) { console.log(v); process.exit(0); } } catch {}
26
- try { const v = JSON.parse(fs.readFileSync(pkg,'utf8')).version; if (v) { console.log('v'+v); process.exit(0); } } catch {}
27
- console.log('latest');
28
- " 2>/dev/null || echo "latest")
29
- TEMPLATE="$HOME/.claude/qualia-templates/help.html"
30
- OUTPUT="/tmp/qualia-help.html"
31
-
32
- # If template doesn't exist in the user home, check the installed framework copy.
33
- if [ ! -f "$TEMPLATE" ]; then
34
- for CANDIDATE in "$HOME/.claude/qualia-framework/templates/help.html"; do
35
- if [ -f "$CANDIDATE" ]; then TEMPLATE="$CANDIDATE"; break; fi
36
- done
37
- fi
38
- ```
39
-
40
- ### 2. Inject version and open
41
-
42
- ```bash
43
- # Replace {{VERSION}} placeholder with actual version
44
- sed "s/{{VERSION}}/$VERSION/g" "$TEMPLATE" > "$OUTPUT"
45
-
46
- # Open in default browser (cross-platform)
47
- if command -v xdg-open &>/dev/null; then
48
- xdg-open "$OUTPUT" # Linux
49
- elif command -v open &>/dev/null; then
50
- open "$OUTPUT" # macOS
51
- elif command -v start &>/dev/null; then
52
- start "$OUTPUT" # Windows (Git Bash)
53
- else
54
- echo "Open this file in your browser: $OUTPUT"
55
- fi
56
- ```
57
-
58
- ### 3. Confirm
59
-
60
- ```bash
61
- node ${QUALIA_BIN}/qualia-ui.js banner router
62
- node ${QUALIA_BIN}/qualia-ui.js ok "Reference guide opened in browser"
63
- node ${QUALIA_BIN}/qualia-ui.js info "File: /tmp/qualia-help.html"
64
- ```
65
-
66
- If the browser does not open automatically, tell the user the file path so they can open it manually.
67
-
68
- ## Notes
69
-
70
- - The HTML file is self-contained — no external dependencies except Google Fonts
71
- - Works offline after first load (fonts cache)
72
- - Qualia-themed: dark background, teal accents, Outfit + Inter fonts
73
- - Shows: The Road, all commands grouped, verification scoring, rules, stack, GitHub orgs
74
- - Version is injected dynamically from .qualia-config.json