qualia-framework 4.1.1 → 4.3.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/agents/builder.md +28 -0
- package/agents/research-synthesizer.md +7 -0
- package/bin/cli.js +142 -2
- package/bin/install.js +68 -1
- package/bin/knowledge-flush.js +164 -0
- package/bin/knowledge.js +317 -0
- package/docs/journey-demo.html +1008 -0
- package/docs/reviews/v4.1.0-audit.html +1488 -0
- package/docs/reviews/v4.1.0-audit.md +263 -0
- package/hooks/git-guardrails.js +167 -0
- package/hooks/stop-session-log.js +180 -0
- package/package.json +1 -1
- package/skills/qualia-debug/SKILL.md +1 -1
- package/skills/qualia-design/SKILL.md +15 -0
- package/skills/qualia-flush/SKILL.md +200 -0
- package/skills/qualia-learn/SKILL.md +47 -37
- package/skills/qualia-new/SKILL.md +1 -1
- package/skills/qualia-plan/SKILL.md +3 -2
- package/skills/qualia-postmortem/SKILL.md +238 -0
- package/skills/qualia-review/SKILL.md +3 -2
- package/skills/qualia-verify/SKILL.md +60 -0
- package/templates/knowledge/agents.md +71 -0
- package/templates/knowledge/index.md +47 -0
- package/tests/bin.test.sh +316 -9
- package/tests/hooks.test.sh +122 -0
- package/tests/runner.js +7 -2
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qualia-flush
|
|
3
|
+
description: "Promote daily-log raw entries to the curated knowledge tier — Karpathy-style raw→wiki flush. Reads ~/.claude/knowledge/daily-log/*.md, identifies recurring patterns and decisions, writes them to ~/.claude/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`, shipped in v4.2.0 foundation) appends
|
|
17
|
+
mechanical session checkpoints to `~/.claude/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 ~/.claude/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
|
+
- **Automatically:** not yet wired. v4.3.0 will add a 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 ~/.claude/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 ~/.claude/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
|
+
`~/.claude/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 ~/.claude/bin/knowledge.js path stripe-checkout
|
|
131
|
+
# Returned path = ~/.claude/knowledge/stripe-checkout.md (NOTE: top-level, not concepts/)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> **Subdirectory caveat:** the v4.2.0 loader resolves bare filenames at
|
|
135
|
+
> `~/.claude/knowledge/{name}.md`. Subdirectory `concepts/` files are not
|
|
136
|
+
> reachable via `knowledge.js load <name>` yet (deferred to v4.3.0). For
|
|
137
|
+
> now, write durable concept files at the top level — flat structure is
|
|
138
|
+
> fine, the index keeps it organized.
|
|
139
|
+
|
|
140
|
+
### 5. Mark the window as flushed
|
|
141
|
+
|
|
142
|
+
Write a stamp file so subsequent flushes can default to "since the last
|
|
143
|
+
flush" instead of "last 14 days":
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
date -u +%Y-%m-%dT%H:%M:%SZ > "$HOME/.claude/.qualia-last-flush"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 6. Summarize
|
|
150
|
+
|
|
151
|
+
Print to the user, in plain language:
|
|
152
|
+
|
|
153
|
+
- N daily-log files scanned (date range)
|
|
154
|
+
- M promotions written (with file:title for each)
|
|
155
|
+
- K things considered but not promoted (single-occurrence — wait for them to recur)
|
|
156
|
+
|
|
157
|
+
Format:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
⬢ Flushed daily-log {start} → {end} ({N} files, {total entries} entries)
|
|
161
|
+
Promoted to wiki:
|
|
162
|
+
+ learned-patterns.md "Supabase RLS in same migration" (3 sessions, 2 projects)
|
|
163
|
+
+ common-fixes.md "next/font crash on Vercel" (2 sessions)
|
|
164
|
+
+ concepts/voice-agent-call-state.md (new file)
|
|
165
|
+
Skipped {K} single-occurrence entries — will revisit if they recur.
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Style
|
|
169
|
+
|
|
170
|
+
- **Be conservative.** False-positive promotions (writing noise as if it's a
|
|
171
|
+
pattern) pollute the wiki and erode trust. Better to skip a candidate and
|
|
172
|
+
let it recur next week than to inflate the curated tier.
|
|
173
|
+
- **Cite your sources.** Every promoted entry should reference the
|
|
174
|
+
daily-log dates that sourced it, in the `--context` field. If a future
|
|
175
|
+
flush wants to update it, the trail is there.
|
|
176
|
+
- **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.
|
|
177
|
+
- **Don't promote private projects across boundaries.** A pattern from
|
|
178
|
+
Project A is fine to promote as cross-project ONLY if it generalizes.
|
|
179
|
+
Client-specific things stay client-specific (`--type client --project X`).
|
|
180
|
+
|
|
181
|
+
## Anti-patterns
|
|
182
|
+
|
|
183
|
+
- **Mass-promoting everything:** if you found "promotions" for 90% of
|
|
184
|
+
daily-log entries, you're labeling, not promoting. Be selective.
|
|
185
|
+
- **Re-promoting on every flush:** before appending, run
|
|
186
|
+
`node ~/.claude/bin/knowledge.js search "{title keywords}"` to check if
|
|
187
|
+
the pattern already exists. If it does, either update it (find by `**ID:**`
|
|
188
|
+
line) or skip — never duplicate.
|
|
189
|
+
- **Hand-writing to `learned-patterns.md` etc. directly:** always go
|
|
190
|
+
through `knowledge.js append` so the canonical entry format and ID
|
|
191
|
+
generation stay consistent. This skill is the only sanctioned promoter,
|
|
192
|
+
but even it uses the loader for writes.
|
|
193
|
+
|
|
194
|
+
## Output contract
|
|
195
|
+
|
|
196
|
+
If invoked with `--dry-run`, print the proposed writes and exit without
|
|
197
|
+
touching disk. Otherwise, after step 6 returns the summary, the skill is
|
|
198
|
+
done — no follow-up prompts. The user sees the summary and the wiki tier
|
|
199
|
+
has new entries that are immediately reachable to every other skill via
|
|
200
|
+
the loader.
|
|
@@ -54,49 +54,45 @@ What did you learn?
|
|
|
54
54
|
|
|
55
55
|
### 2. Check for Duplicates
|
|
56
56
|
|
|
57
|
-
Before saving,
|
|
57
|
+
Before saving, search the existing knowledge for a similar entry. Use the
|
|
58
|
+
unified loader, **never** raw `cat` or `grep` directly — the loader handles
|
|
59
|
+
missing-file edge cases and stays consistent across skills.
|
|
58
60
|
|
|
59
61
|
```bash
|
|
60
|
-
|
|
61
|
-
grep -i "{title keywords}" ~/.claude/knowledge/{type}.md 2>/dev/null
|
|
62
|
+
node ~/.claude/bin/knowledge.js search "{title keywords}"
|
|
62
63
|
```
|
|
63
64
|
|
|
64
|
-
If a near-match exists
|
|
65
|
+
If a near-match exists:
|
|
65
66
|
- Show the existing entry to the user
|
|
66
67
|
- Ask: "A similar entry exists. Update it, create a new one, or skip?"
|
|
67
|
-
- If update:
|
|
68
|
+
- If update: edit the file directly (find the entry by `**ID:**` line). If
|
|
69
|
+
new: continue to step 3. If skip: done.
|
|
68
70
|
|
|
69
|
-
### 3.
|
|
71
|
+
### 3. Append the Entry
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
### {Title}
|
|
78
|
-
**ID:** {random 8-char hex, e.g. a3f7c1e9}
|
|
79
|
-
**Date:** {ISO 8601, e.g. 2026-04-11}
|
|
80
|
-
**Project:** {current project name or "general"}
|
|
81
|
-
**Context:** {brief context — what you were building when you learned this}
|
|
82
|
-
|
|
83
|
-
{The learning — be specific enough that future-you understands without context}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### 4. Append to Knowledge File
|
|
87
|
-
|
|
88
|
-
Append-only — never overwrite the file, always add at the end:
|
|
73
|
+
The loader's `append` subcommand handles ID generation, ISO date, project
|
|
74
|
+
detection, and the canonical entry format — one call, no shell escaping
|
|
75
|
+
concerns:
|
|
89
76
|
|
|
90
77
|
```bash
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
node ~/.claude/bin/knowledge.js append \
|
|
79
|
+
--type {pattern|fix|client} \
|
|
80
|
+
--title "{Title}" \
|
|
81
|
+
--body "{The learning — be specific enough that future-you understands without context}" \
|
|
82
|
+
--project "{current project name or 'general'}" \
|
|
83
|
+
--context "{brief context — what you were building when you learned this}"
|
|
93
84
|
```
|
|
94
85
|
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
86
|
+
Type → file mapping (handled by the loader):
|
|
87
|
+
- `pattern` → `learned-patterns.md`
|
|
88
|
+
- `fix` → `common-fixes.md`
|
|
89
|
+
- `client` → `client-prefs.md`
|
|
90
|
+
|
|
91
|
+
The loader prints `appended {id} to {file}` on success. If the destination
|
|
92
|
+
file does not exist, the loader creates it with a header — you do not need
|
|
93
|
+
to bootstrap it.
|
|
98
94
|
|
|
99
|
-
###
|
|
95
|
+
### 4. Confirm
|
|
100
96
|
|
|
101
97
|
```
|
|
102
98
|
⬢ Saved to {file}
|
|
@@ -105,13 +101,27 @@ echo "{formatted entry}" >> ~/.claude/knowledge/{type}.md
|
|
|
105
101
|
|
|
106
102
|
## Reading Knowledge
|
|
107
103
|
|
|
108
|
-
|
|
104
|
+
**Always use the loader.** Hardcoded `cat ~/.claude/knowledge/X.md` is an
|
|
105
|
+
anti-pattern — it makes new files invisible (this was v4.1.0 audit finding
|
|
106
|
+
#3). The loader, by contrast, lets agents discover available knowledge via
|
|
107
|
+
the index.
|
|
108
|
+
|
|
109
109
|
```bash
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
# Print the index (entry point — read this first)
|
|
111
|
+
node ~/.claude/bin/knowledge.js
|
|
112
|
+
|
|
113
|
+
# Print a specific file (accepts aliases: patterns, fixes, client)
|
|
114
|
+
node ~/.claude/bin/knowledge.js load patterns
|
|
115
|
+
node ~/.claude/bin/knowledge.js load common-fixes.md
|
|
116
|
+
|
|
117
|
+
# List everything available
|
|
118
|
+
node ~/.claude/bin/knowledge.js list
|
|
119
|
+
|
|
120
|
+
# Search across all files
|
|
121
|
+
node ~/.claude/bin/knowledge.js search "RLS"
|
|
113
122
|
```
|
|
114
123
|
|
|
115
|
-
The `/qualia-debug` skill should check `common-fixes.md` before
|
|
116
|
-
The `/qualia-new` skill should check `client-prefs.md`
|
|
117
|
-
|
|
124
|
+
The `/qualia-debug` skill should check `common-fixes.md` (`load fixes`) before
|
|
125
|
+
investigating. The `/qualia-new` skill should check `client-prefs.md`
|
|
126
|
+
(`load client`) when setting up client projects. The `/qualia-plan` skill
|
|
127
|
+
should check `learned-patterns.md` (`load patterns`) when planning phases.
|
|
@@ -94,7 +94,7 @@ Plus free-text: "Any brand colors or reference sites I should look at?"
|
|
|
94
94
|
|
|
95
95
|
If client, ask name. Check saved prefs:
|
|
96
96
|
```bash
|
|
97
|
-
|
|
97
|
+
node ~/.claude/bin/knowledge.js search "{client name}"
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
### Step 5. Write PROJECT.md
|
|
@@ -33,8 +33,9 @@ Spawn a planner agent to break the current phase into executable tasks, then val
|
|
|
33
33
|
cat .planning/STATE.md 2>/dev/null
|
|
34
34
|
cat .planning/ROADMAP.md 2>/dev/null
|
|
35
35
|
cat .planning/PROJECT.md 2>/dev/null
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
node ~/.claude/bin/knowledge.js
|
|
37
|
+
node ~/.claude/bin/knowledge.js load patterns
|
|
38
|
+
node ~/.claude/bin/knowledge.js load client
|
|
38
39
|
```
|
|
39
40
|
|
|
40
41
|
If no phase number given, use the current phase from STATE.md.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qualia-postmortem
|
|
3
|
+
description: "Self-healing AI layer — when /qualia-verify returns FAIL, identify which agent/rule/skill should have caught the failure and propose a delta to that file so the same class of bug never recurs. Trigger on 'postmortem', 'why did the framework miss this', 'self-heal', 'qualia-postmortem', or auto-invoked by /qualia-verify on FAIL with --auto."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Grep
|
|
10
|
+
- Glob
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# /qualia-postmortem — Self-Healing AI Layer
|
|
14
|
+
|
|
15
|
+
When the verifier finds a gap, fixing the **code** alone is not enough.
|
|
16
|
+
The framework let the bug through — that means a rule, agent prompt,
|
|
17
|
+
plan-checker check, or skill instruction was insufficient. This skill
|
|
18
|
+
runs after a verify FAIL and asks: *which file in the AI layer should
|
|
19
|
+
have caught this, and what delta would catch the next one like it?*
|
|
20
|
+
|
|
21
|
+
This is Cole Medin's **pillar 5** from the parallel-worktrees playbook
|
|
22
|
+
(NotebookLM 2026-04-25): "anytime we encounter a bug in a pull request,
|
|
23
|
+
we don't just fix the bug and move on, we fix the underlying system that
|
|
24
|
+
allowed for the bug." Without this loop, the same class of bug ships in
|
|
25
|
+
PR-3, PR-7, PR-11 of every project.
|
|
26
|
+
|
|
27
|
+
## When to run
|
|
28
|
+
|
|
29
|
+
- **Manually:** `/qualia-postmortem` after any verify FAIL where the gap
|
|
30
|
+
feels preventable — i.e. a rule could have flagged it, a builder
|
|
31
|
+
instruction could have steered around it, a plan-checker rule could
|
|
32
|
+
have rejected the plan that produced it.
|
|
33
|
+
- **Auto:** `/qualia-verify --auto` will invoke this skill on every FAIL
|
|
34
|
+
before the gap-closure loop fires. The postmortem write happens before
|
|
35
|
+
the user re-plans, so the next planner spawn benefits from the
|
|
36
|
+
updated AI layer immediately.
|
|
37
|
+
|
|
38
|
+
## Inputs
|
|
39
|
+
|
|
40
|
+
- `--phase N` (default: current phase from STATE.md)
|
|
41
|
+
- `--apply` (optional) — apply the proposed delta to disk. Without
|
|
42
|
+
`--apply`, the skill writes `.planning/phase-{N}-postmortem.md` for
|
|
43
|
+
human review and stops there.
|
|
44
|
+
- `--report-only` (optional) — just emit the analysis, write nothing.
|
|
45
|
+
|
|
46
|
+
If invoked from `/qualia-verify --auto`, default to writing the
|
|
47
|
+
postmortem report but **not** applying — applying touches the AI layer
|
|
48
|
+
itself, which is high-stakes. The user reviews and types `/qualia-learn`
|
|
49
|
+
or applies manually.
|
|
50
|
+
|
|
51
|
+
## Process
|
|
52
|
+
|
|
53
|
+
### 1. Load the failure
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
node ~/.claude/bin/qualia-ui.js banner postmortem 2>/dev/null || true
|
|
57
|
+
|
|
58
|
+
PHASE="${PHASE:-$(node ~/.claude/bin/state.js check 2>/dev/null | node -e 'let s=""; process.stdin.on("data",d=>s+=d).on("end",()=>{try{console.log(JSON.parse(s).phase)}catch{console.log("")}})')}"
|
|
59
|
+
[ -z "$PHASE" ] && { echo "QUALIA: Could not resolve current phase. Pass --phase N explicitly."; exit 1; }
|
|
60
|
+
|
|
61
|
+
VERIFY_FILE=".planning/phase-${PHASE}-verification.md"
|
|
62
|
+
PLAN_FILE=".planning/phase-${PHASE}-plan.md"
|
|
63
|
+
|
|
64
|
+
[ -f "$VERIFY_FILE" ] || { echo "QUALIA: $VERIFY_FILE missing — nothing to post-mortem."; exit 1; }
|
|
65
|
+
[ -f "$PLAN_FILE" ] || echo "QUALIA: $PLAN_FILE missing — analysis will be partial."
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Read both files. The verification report tells you *what failed*. The
|
|
69
|
+
plan tells you *what was supposed to happen*. The gap between them is
|
|
70
|
+
where the AI layer fell short.
|
|
71
|
+
|
|
72
|
+
### 2. Read the AI layer
|
|
73
|
+
|
|
74
|
+
The framework's prompts live in three places. Load all three so you can
|
|
75
|
+
match a finding to the file most likely responsible:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Agent prompts (planner, builder, plan-checker, verifier, etc.)
|
|
79
|
+
ls ~/.claude/agents/
|
|
80
|
+
# Skill descriptions (qualia-plan, qualia-build, qualia-verify, etc.)
|
|
81
|
+
ls ~/.claude/skills/
|
|
82
|
+
# Project rules + grounding
|
|
83
|
+
ls ~/.claude/rules/
|
|
84
|
+
# Already-curated knowledge
|
|
85
|
+
node ~/.claude/bin/knowledge.js
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
You don't read all of them — you read the ones whose job description
|
|
89
|
+
matches the failure. Use this lookup:
|
|
90
|
+
|
|
91
|
+
| Failure shape | Likely AI-layer owner |
|
|
92
|
+
|---|---|
|
|
93
|
+
| Builder produced a stub / placeholder | `agents/builder.md` (Read Before Write, no-stub rule) |
|
|
94
|
+
| Plan listed Validation: `test -f file.ts` only — missed behavior check | `agents/plan-checker.md` (Rule 8: at least one grep-match or command-exit per task) |
|
|
95
|
+
| Wave 2 task ran before wave 1 committed | `agents/planner.md` (dependency graph) |
|
|
96
|
+
| Build passed locally, broke in CI | `rules/deployment.md` or a missing pre-deploy-gate scan |
|
|
97
|
+
| RLS missing on new table | `rules/security.md` + `agents/builder.md` (security persona handling) |
|
|
98
|
+
| Design regression — fonts off, contrast fail | `rules/frontend.md` + `skills/qualia-design/SKILL.md` |
|
|
99
|
+
| Migration unsafe (DROP without IF EXISTS, etc.) | `hooks/migration-guard.js` |
|
|
100
|
+
| Verifier missed it | `agents/verifier.md` — most embarrassing case, address with extra care |
|
|
101
|
+
|
|
102
|
+
### 3. Diagnose
|
|
103
|
+
|
|
104
|
+
For **each** gap in the verification report (process them one at a time
|
|
105
|
+
when there are multiple), produce a four-field analysis:
|
|
106
|
+
|
|
107
|
+
```markdown
|
|
108
|
+
## Gap: {gap title from verification report}
|
|
109
|
+
|
|
110
|
+
**Severity:** {CRITICAL | HIGH | MEDIUM | LOW} (from verifier's rubric)
|
|
111
|
+
**Owner file:** `agents/builder.md` (or rules/X.md, skills/Y/SKILL.md, etc.)
|
|
112
|
+
**Why it slipped:**
|
|
113
|
+
Quote the relevant section of the owner file. Show the gap. The owner
|
|
114
|
+
file SHOULD have prevented this — either the rule wasn't there, or it
|
|
115
|
+
was there but not enforceable, or a rule was there but the agent was
|
|
116
|
+
free to ignore it.
|
|
117
|
+
|
|
118
|
+
**Proposed delta:**
|
|
119
|
+
Concrete diff for the owner file. New line, edited section, or rule
|
|
120
|
+
addition. Keep it minimal — one new sentence is better than a new
|
|
121
|
+
paragraph. The goal is "the next planner/builder spawn catches this
|
|
122
|
+
class of bug."
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. Write the postmortem report
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
cat > .planning/phase-${PHASE}-postmortem.md <<'EOF'
|
|
129
|
+
# Phase {N} Postmortem
|
|
130
|
+
|
|
131
|
+
**Phase:** {N}
|
|
132
|
+
**Verify result:** FAIL ({gap_count} gaps)
|
|
133
|
+
**Date:** {ISO date}
|
|
134
|
+
**Run ID:** {short uid}
|
|
135
|
+
|
|
136
|
+
## Findings
|
|
137
|
+
|
|
138
|
+
{one ## Gap section per gap, format from step 3}
|
|
139
|
+
|
|
140
|
+
## Cumulative AI-layer drift
|
|
141
|
+
|
|
142
|
+
{If multiple postmortems exist for this project, group recurring owner
|
|
143
|
+
files: "agents/builder.md has been flagged 3 times this milestone — its
|
|
144
|
+
no-stub rule may need reinforcement or wave-2 stubs need a hard hook."}
|
|
145
|
+
|
|
146
|
+
## Apply?
|
|
147
|
+
|
|
148
|
+
To apply all proposed deltas:
|
|
149
|
+
/qualia-postmortem --apply --phase {N}
|
|
150
|
+
|
|
151
|
+
To save the recurring patterns to knowledge instead (recommended for
|
|
152
|
+
project-spanning lessons):
|
|
153
|
+
/qualia-learn (pick the relevant entries from this report)
|
|
154
|
+
|
|
155
|
+
EOF
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 5. (Optional) Apply
|
|
159
|
+
|
|
160
|
+
If invoked with `--apply`, walk each "Proposed delta" and use the Edit
|
|
161
|
+
tool to make the literal change to the owner file. After every edit, run
|
|
162
|
+
the framework's own type/test gates (`node --test tests/runner.js` if you
|
|
163
|
+
modified anything in `bin/`, `agents/`, or `rules/`) to confirm no
|
|
164
|
+
regression.
|
|
165
|
+
|
|
166
|
+
If a proposed delta is to a `~/.claude/agents/X.md` file (the installed
|
|
167
|
+
copy), edit that copy directly — the user re-running the installer will
|
|
168
|
+
overwrite it next release, so also flag a TODO in the postmortem report
|
|
169
|
+
saying "this delta should be PR'd back to the framework repo at
|
|
170
|
+
`agents/X.md`" so it survives reinstall.
|
|
171
|
+
|
|
172
|
+
### 6. Promote durable lessons to the knowledge layer
|
|
173
|
+
|
|
174
|
+
For lessons that apply across projects (e.g. "Supabase RLS must be in
|
|
175
|
+
the same migration as the table — applying it later creates a window
|
|
176
|
+
where data is unprotected"), append to the curated tier so future
|
|
177
|
+
builders pick it up:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
node ~/.claude/bin/knowledge.js append \
|
|
181
|
+
--type pattern \
|
|
182
|
+
--title "{lesson title}" \
|
|
183
|
+
--body "{lesson body}" \
|
|
184
|
+
--project "{project name from .planning/PROJECT.md or 'general' if cross-project}" \
|
|
185
|
+
--context "Postmortem from phase ${PHASE}, verify FAIL on {date}"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 7. Summarize
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
⬢ Postmortem complete — phase {N}
|
|
192
|
+
{G} gaps analyzed
|
|
193
|
+
Owner files implicated:
|
|
194
|
+
- agents/builder.md (gap 1, gap 3)
|
|
195
|
+
- rules/security.md (gap 2)
|
|
196
|
+
Report: .planning/phase-${PHASE}-postmortem.md
|
|
197
|
+
{if --apply: deltas applied; framework reinstall TODO'd}
|
|
198
|
+
{if no --apply: review and run --apply OR /qualia-learn the patterns}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Style
|
|
202
|
+
|
|
203
|
+
- **Be charitable.** The framework didn't fail because someone was
|
|
204
|
+
careless. It failed because a contract wasn't tight enough. Frame
|
|
205
|
+
every finding as "the contract was X; it should have been Y."
|
|
206
|
+
- **Keep deltas surgical.** A 2-line addition to a rule is durable; a
|
|
207
|
+
paragraph rewrite is brittle. Smaller deltas survive future framework
|
|
208
|
+
updates.
|
|
209
|
+
- **Don't reach.** If a gap genuinely doesn't map to an AI-layer file
|
|
210
|
+
(e.g. it's an external service outage), say so explicitly — don't
|
|
211
|
+
invent a rule to retroactively own it.
|
|
212
|
+
- **Rate limit yourself.** Don't propose more than 3 deltas per
|
|
213
|
+
postmortem. If there are 8 gaps, the top 3 by severity get deltas; the
|
|
214
|
+
rest get noted but not deltad. Otherwise the AI layer becomes a museum
|
|
215
|
+
of edge cases.
|
|
216
|
+
|
|
217
|
+
## Anti-patterns
|
|
218
|
+
|
|
219
|
+
- **Re-fixing the same code as the verifier.** This skill is about the
|
|
220
|
+
AI layer, not the codebase. The gap-closure loop (`/qualia-plan
|
|
221
|
+
{N} --gaps`) handles the code. Postmortem only touches `agents/`,
|
|
222
|
+
`rules/`, `skills/`, and the knowledge layer.
|
|
223
|
+
- **Auto-applying deltas to `~/.claude/agents/X.md` without flagging a
|
|
224
|
+
framework PR TODO.** That edit lasts until the next reinstall. Always
|
|
225
|
+
note the TODO so the lesson reaches the framework repo.
|
|
226
|
+
- **Promoting every postmortem finding to knowledge.** Most are
|
|
227
|
+
project-specific contract tightening — they belong in the project's
|
|
228
|
+
AI-layer files, not in cross-project knowledge. Only generalizable
|
|
229
|
+
patterns get appended via `knowledge.js`.
|
|
230
|
+
|
|
231
|
+
## Output contract
|
|
232
|
+
|
|
233
|
+
The skill writes `.planning/phase-{N}-postmortem.md` and either applies
|
|
234
|
+
deltas (with `--apply`) or stops with a summary that points the user at
|
|
235
|
+
the next step (`--apply` to apply, or `/qualia-learn` to promote
|
|
236
|
+
specific patterns). No follow-up prompts. Idempotent: re-running on the
|
|
237
|
+
same phase appends `### Re-run {timestamp}` to the existing report
|
|
238
|
+
rather than overwriting.
|
|
@@ -29,8 +29,9 @@ node ~/.claude/bin/qualia-ui.js banner review
|
|
|
29
29
|
### 0. Load Context
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
node ~/.claude/bin/knowledge.js
|
|
33
|
+
node ~/.claude/bin/knowledge.js load fixes
|
|
34
|
+
node ~/.claude/bin/knowledge.js load patterns
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
Detect project shape:
|
|
@@ -19,6 +19,7 @@ Spawn a verifier agent to check if the phase goal was achieved. Does NOT trust b
|
|
|
19
19
|
`/qualia-verify` — verify the current built phase
|
|
20
20
|
`/qualia-verify {N}` — verify specific phase
|
|
21
21
|
`/qualia-verify {N} --auto` — verify + auto-chain: PASS → next phase (or milestone close); FAIL → gap closure; gap limit → halt with escalation
|
|
22
|
+
`/qualia-verify {N} --adversarial` — run a SECOND verifier in fresh context with an adversarial prompt ("find what's wrong, not what's right"). Union the findings. Recommended for high-stakes phases (Handoff milestone, payment/auth/migration code) where a biased single-pass review would silently approve a bad change. v4.3.0+.
|
|
22
23
|
|
|
23
24
|
## Process
|
|
24
25
|
|
|
@@ -80,6 +81,52 @@ Drive the running dev server and test the routes this phase touched. Append a '#
|
|
|
80
81
|
|
|
81
82
|
Wait for both the main verifier and the QA browser agent before moving to step 3. If Playwright MCP is unavailable, the QA browser agent returns BLOCKED — that's not a phase failure, just a note in the report.
|
|
82
83
|
|
|
84
|
+
### 2c. Adversarial Second Opinion (--adversarial flag, optional)
|
|
85
|
+
|
|
86
|
+
When `--adversarial` is in the args, OR when the current milestone is
|
|
87
|
+
`Handoff` OR the phase plan touches files matching `auth|payment|migration|rls|service_role`, spawn a SECOND verifier in fresh context with an
|
|
88
|
+
adversarial prompt. This is the "kid-grading-their-own-homework"
|
|
89
|
+
mitigation — a single verifier instance trained on the same rubric the
|
|
90
|
+
planner+builder optimized against gets ~70% fewer real findings than a
|
|
91
|
+
fresh-context adversarial pass (Cole Medin, NotebookLM 2026-04-25, citing
|
|
92
|
+
PR-acceptance studies).
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
node ~/.claude/bin/qualia-ui.js spawn verifier "Adversarial pass — find what's wrong"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Agent(prompt="
|
|
100
|
+
Read your role: @~/.claude/agents/verifier.md
|
|
101
|
+
Grounding + rubrics: @~/.claude/rules/grounding.md
|
|
102
|
+
|
|
103
|
+
You are an ADVERSARIAL reviewer. Your job is to find what's WRONG with
|
|
104
|
+
this phase, not to confirm it works. Assume the previous verifier missed
|
|
105
|
+
something. Use the same Severity Rubric, the same evidence-citation
|
|
106
|
+
requirement, but bias your search toward edge cases the cooperative
|
|
107
|
+
verifier would skip:
|
|
108
|
+
• What untested error path exists?
|
|
109
|
+
• What input would crash this?
|
|
110
|
+
• What concurrent access pattern is unhandled?
|
|
111
|
+
• What downstream consumer breaks if this contract changes?
|
|
112
|
+
• Where is a security assumption (auth, RLS, secrets) implicit
|
|
113
|
+
instead of enforced?
|
|
114
|
+
|
|
115
|
+
Project conventions: @.planning/PROJECT.md
|
|
116
|
+
Phase plan: @.planning/phase-{N}-plan.md
|
|
117
|
+
Cooperative verifier's report (do NOT re-find what they found, find
|
|
118
|
+
what they MISSED): @.planning/phase-{N}-verification.md
|
|
119
|
+
|
|
120
|
+
Append a '## Adversarial Findings' section to the verification file.
|
|
121
|
+
Empty section is fine if you genuinely found nothing — better that than
|
|
122
|
+
inventing findings to look productive.
|
|
123
|
+
", subagent_type="qualia-verifier", description="Adversarial verify phase {N}")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Findings from the adversarial pass merge into the main verification
|
|
127
|
+
report. The combined PASS/FAIL is the union: if either pass found a
|
|
128
|
+
CRITICAL or HIGH gap, the phase is FAIL.
|
|
129
|
+
|
|
83
130
|
### 3. Present Results
|
|
84
131
|
|
|
85
132
|
Read the verification report. Present:
|
|
@@ -102,6 +149,19 @@ Then for each gap:
|
|
|
102
149
|
node ~/.claude/bin/qualia-ui.js fail "{gap description}"
|
|
103
150
|
```
|
|
104
151
|
|
|
152
|
+
**Self-healing layer (v4.3.0+):** before re-planning the gaps, run a
|
|
153
|
+
postmortem so the framework itself learns from the miss. This is Cole
|
|
154
|
+
Medin's pillar 5: don't just fix the bug, fix the AI-layer file that
|
|
155
|
+
should have caught it. The postmortem writes a report to
|
|
156
|
+
`.planning/phase-{N}-postmortem.md` for review — it does NOT auto-apply
|
|
157
|
+
deltas to agents/rules unless the user runs `/qualia-postmortem --apply`
|
|
158
|
+
explicitly. Without this loop, the same class of bug ships in PR-3, PR-7,
|
|
159
|
+
PR-11 of the next project.
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
/qualia-postmortem --phase {N}
|
|
163
|
+
```
|
|
164
|
+
|
|
105
165
|
End:
|
|
106
166
|
```bash
|
|
107
167
|
node ~/.claude/bin/qualia-ui.js end "PHASE {N} GAPS FOUND" "/qualia-plan {N} --gaps"
|