qualia-framework 6.7.0 → 6.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 (40) hide show
  1. package/CHANGELOG.md +2304 -0
  2. package/FLAGS.md +73 -0
  3. package/SOUL.md +17 -0
  4. package/TROUBLESHOOTING.md +183 -0
  5. package/agents/plan-checker.md +4 -0
  6. package/agents/planner.md +8 -0
  7. package/agents/qa-browser.md +6 -2
  8. package/agents/research-synthesizer.md +4 -0
  9. package/agents/researcher.md +4 -0
  10. package/agents/roadmapper.md +4 -0
  11. package/agents/verifier.md +1 -1
  12. package/agents/visual-evaluator.md +8 -6
  13. package/bin/cli.js +7 -1
  14. package/bin/install.js +69 -7
  15. package/bin/runtime-manifest.js +1 -0
  16. package/bin/security-scan.js +24 -10
  17. package/bin/trust-score.js +34 -0
  18. package/docs/onboarding.html +1 -1
  19. package/hooks/migration-guard.js +4 -4
  20. package/hooks/pre-deploy-gate.js +14 -4
  21. package/hooks/stop-session-log.js +10 -7
  22. package/package.json +6 -2
  23. package/qualia-design/design-rubric.md +3 -1
  24. package/rules/architecture.md +1 -1
  25. package/rules/grounding.md +3 -1
  26. package/rules/speed.md +2 -2
  27. package/skills/qualia-idk/SKILL.md +3 -3
  28. package/skills/qualia-polish/REFERENCE.md +11 -6
  29. package/skills/qualia-polish/SKILL.md +20 -3
  30. package/skills/qualia-polish/scripts/loop.mjs +24 -6
  31. package/skills/qualia-polish/scripts/playwright-capture.mjs +89 -11
  32. package/skills/qualia-polish/scripts/vibe-tokens.mjs +57 -1
  33. package/skills/qualia-research/SKILL.md +1 -1
  34. package/skills/qualia-road/SKILL.md +6 -0
  35. package/skills/qualia-scope/SKILL.md +2 -2
  36. package/skills/qualia-secure/SKILL.md +5 -5
  37. package/templates/help.html +1 -1
  38. package/templates/knowledge/index.md +4 -4
  39. package/tests/bin.test.sh +4 -4
  40. package/tests/lib.test.sh +2 -2
package/CHANGELOG.md ADDED
@@ -0,0 +1,2304 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Qualia Framework are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ > Note: git tags for historical versions were not retained; commit references are approximate
9
+ > and dates reflect commit history rather than npm publish timestamps.
10
+
11
+ ## [6.8.0] - 2026-06-06 (audit remediation — installer, guards, trust-score, polish)
12
+
13
+ Closes the verified findings from the 2026-06-06 framework audit (4 CRITICAL · 7 HIGH · 33 MEDIUM, adversarially verified). Root cause of most CRITICALs was a stale/incomplete install, not source rot — fixed in the installer so a clean reinstall is complete and correct.
14
+
15
+ ### Fixed — installer (the highest-leverage fixes)
16
+ - **Installed CLI no longer crashes.** `bin/install.js` now writes a root `package.json` (version marker) into the install, and `bin/cli.js` guards the `require("../package.json")` read (falls back to `.qualia-config.json`). The installed `qualia-framework` CLI was dead via `MODULE_NOT_FOUND`.
17
+ - **`references/archetypes/*.md` now install to the canonical `references/` path** (in addition to `qualia-references/`), so `/qualia-scope` and `constitution.md` resolve their archetype DoDs. `qualia-scope` reads them via absolute paths.
18
+ - **Companion docs shipped:** `SOUL.md`, `FLAGS.md`, `TROUBLESHOOTING.md`, `CHANGELOG.md` are now copied by the installer and included in the npm package `files`.
19
+ - **`auto-report.js` added to the runtime manifest** so the Stop-hook ship-time auto-report is actually installed; `stop-session-log.js` guards the spawn with `fs.existsSync`.
20
+ - **Installer is idempotent for hooks:** reinstall prunes orphan `.js` hooks (e.g. legacy `brain-*.js`) and `DEPRECATED_HOOKS` lists them.
21
+
22
+ ### Fixed — guards fail closed (were failing open / silent)
23
+ - **`pre-deploy-gate`:** hook-registration timeout raised 180→600s and per-gate budgets lowered to 120s so four quality gates + security scan can't exhaust the hook timeout and let a deploy through. Brownfield ship-policy short-circuit now logs to stderr. `QUALIA_SKIP_LINT` is OWNER-gated.
24
+ - **`migration-guard`:** block reason now printed to **stderr** (was stdout, invisible to the model on exit 2).
25
+ - **`security-scan`:** unreadable files are recorded in `skipped[]`, degrade the score, and force a non-clean exit — no more silent fail-open per file.
26
+ - **`trust-score`:** now load-probes spine scripts (`node --check`) that are present, so a syntax-broken installed script forces status off PASS (it previously reported 100/PASS regardless).
27
+
28
+ ### Changed — config
29
+ - **Renamed the env key `CLAUDE_AGENT_FORK_ENABLED` → `CLAUDE_CODE_FORK_SUBAGENT`** — the official Claude Code variable (v2.1.117+); the old name was a no-op. Installer + `cli.js` repair env now agree.
30
+ - Installer writes a `$schema` reference and seeds a scoped `permissions.allow` baseline instead of leaving it empty.
31
+
32
+ ### Fixed — skills, agents, rules, docs
33
+ - Repointed dangling command routes (`/qualia-status`→`/qualia-doctor`, `/qualia-debug`→`/qualia-fix`, `/qualia-pause`,`/qualia-resume`→`/qualia`/`/qualia-handoff`), fixed `~/qualia-memory` path, added 6 omitted skills to the `/qualia-road` map.
34
+ - Added `rules/grounding.md`/`rules/trust-boundary.md` references to agents that were missing them; granted the verifier `Write` and qa-browser `Edit` (the contracts that require writing the verification file).
35
+ - Fixed stale rule paths (`rules/design-rubric.md`→`qualia-design/design-rubric.md`), replaced the non-existent `/supabase` skill references with `npx supabase`, annotated knowledge index stubs.
36
+
37
+ ### Improved — polish subsystem
38
+ - Screenshot capture is now **full-page** (was above-the-fold only) across all backends; visual-evaluator scores below-fold sections.
39
+ - `--vibe` now routes back through verification (tsc + slop-detect + a scoped vision pass) instead of terminating at the token swap.
40
+ - Deterministic loop token accounting (fixed per-iteration cost) and an iteration-monotonicity assertion; single-sourced design rubric + the 10-font banned list (lockstep with `bin/slop-detect.mjs`).
41
+
42
+ ## [6.7.1] - 2026-05-31 (docs patch — A4 surface-collapse follow-up)
43
+
44
+ Documentation-only patch. No code or behavior changes.
45
+
46
+ ### Fixed
47
+
48
+ - **User-facing help docs caught up with the A4 surface collapse.** `docs/onboarding.html` and `templates/help.html` still advertised `/qualia-discuss` as a live slash command, though it was retired into `qualia-scope` in 6.7.0 (`RETIRED_SKILLS`, PR #64). Both now point at `/qualia-scope` with accurate PROJECT/PHASE-mode descriptions (PR #66). No code path was affected — `qualia-discuss` was already absent from `ACTIVE_SKILLS`.
49
+
50
+ ## [6.7.0] - 2026-05-31 (A5 — per-increment, concurrency-aware state model)
51
+
52
+ Additive release. No breaking changes. Completes A5: multiple people can work the same project on different branches without merge-conflicting on the planning files. The change is **dual-layout** — projects without `.planning/increments/` run the exact legacy code path (all 65 prior state tests pass unchanged); the new path activates only after `state.js migrate`.
53
+
54
+ ### Added
55
+
56
+ - **Per-increment layout (`bin/state.js`)** — the committed source of truth becomes one file per increment, `.planning/increments/{id}.md` (frontmatter: `status`, `claimed_by`, `branch`, `verification`, `gap_cycles`, build counters, `deployed_url`; body carries a Definition-of-Done checklist), wrapped in `.planning/releases/{rid}.md`. Two people editing two increments edit two files → **no conflict by construction**.
57
+ - **`STATE.md` + `tracking.json` + `.cursor.json` are now LOCAL generated views** — `regenerateViews()` rebuilds them from the increment files. `tracking.json` stays **fat** (mirrors the active increment + keeps identity/lifetime + gains an `increments`/`releases`/`mode` index), so all 13 back-compat consumers (`report-payload.js`, `project-snapshot.js`, `trust-score.js`, `statusline.js`, hooks, …) keep working with zero edits. They're gitignored, so the only per-step-mutated files are never committed.
58
+ - **`state.js migrate`** — non-destructive conversion of a legacy project: backs up `STATE.md`+`tracking.json`, writes a reversible `migration-manifest.json`, is idempotent, and supports `migrate --revert` (byte-identical restore). Hard-stop, human-initiated — never silent.
59
+ - **`state.js claim` / `state.js release`** — claim writes `claimed_by`+`branch` onto one increment (a second actor is refused with `ALREADY_CLAIMED`); release ships the increment, runs the **profile-aware Definition-of-Done gate** (strict: any open `- [ ]` blocks; standard: open lines need a `WAIVED:` reason; `--force` overrides), and clears the claim.
60
+ - **`templates/planning.gitignore`** — installed into `.planning/.gitignore` by `qualia-new`; lists the now-local generated files.
61
+
62
+ ### Changed
63
+
64
+ - **`check` and `transition` are increment-aware** when `.planning/increments/` exists — `check` is read-only and returns `my_claim` / `next_increment` / `claimed_increments[]` so the router skips work held by another person; `transition` operates on one increment file (by `--id`, or `--phase N`/cursor for full back-compat with the existing plan→build→verify→ship flow).
65
+ - **Skills repointed** — `qualia-scope` claims the scoped increment, `qualia-ship` releases it, `qualia` routes around others' claims, `qualia-new` scaffolds `.planning/.gitignore`. All gated on the increment layout; legacy projects are unaffected.
66
+
67
+ ### Security
68
+
69
+ - **Increment-id validation** (`isValidIncrementId`) — `claim`/`release`/`transition --id` reject any id that isn't a plain `inc-<slug>` token before it reaches `path.join`, closing a path-traversal vector (`--id "../../etc/passwd"` → `INVALID_ID`).
70
+
71
+ ### Tested
72
+
73
+ - 14 new `tests/state.test.sh` assertions (state suite 65 → 79, all green): migration + idempotency + byte-identical revert, claim/double-claim, router skip, release + DoD gate (strict/standard/force), id-traversal guard, and the **two-actor zero-conflict keystone** (two clones ship two increments on two branches → merge to main with zero conflicts, `STATE.md` never committed). All 10 suites green.
74
+
75
+ ## [6.6.0] - 2026-05-31 (B1 auto-capture — ship-time ERP reporting)
76
+
77
+ Additive release. No breaking changes. Completes B1: the ERP receives a session report **automatically when work ships**, with no manual `/qualia-report` — closing the "data is self-reported and optional" gap.
78
+
79
+ ### Added
80
+
81
+ - **`bin/auto-report.js`** — ship-time auto-capture. `maybeAutoReport()` fires ONLY when a project reaches `status: shipped`, deduped once per shipped `(milestone, phase)` via a marker file, and POSTs a session report tagged `source: 'auto'`. Fail-soft: enqueues to the existing `erp-retry` queue on any failure, never throws, never blocks. (Deliberately NOT triggered per-turn — the Stop hook fires every turn, so a naive hook there would spam the ERP with a new report every few minutes.)
82
+ - **`source` provenance on the report payload** — `bin/report-payload.js` `buildPayload()` tags `source` (`'auto'` when `SOURCE=auto`, else `'manual'`) and honors `DRY_RUN` for safe testing. The ERP side (`session_reports.source`) shipped separately in `qualia-erp`.
83
+
84
+ ### Changed
85
+
86
+ - **`hooks/stop-session-log.js`** — spawns `auto-report.js` **detached** (fire-and-forget) so the hook stays fast and non-blocking; the auto-report's own guards make it a no-op except the one turn right after a ship.
87
+ - **`bin/erp-retry.js`** — exports `postOnce` / `readApiKey` / `readConfig` so auto-report and the manual `/qualia-report` flow share ONE ERP-upload seam.
88
+
89
+ ### Tested
90
+
91
+ - New `tests/auto-report.test.sh` (14 assertions): source tagging, every guard (no key, ERP disabled, not-shipped), ship-time POST delivering `source:'auto'` to a stub endpoint, dedupe, fail-soft enqueue. All 10 suites green. E2E-verified against the live ERP (a real `source='auto'` row landed, then was removed).
92
+
93
+ ## [6.5.0] - 2026-05-30 (Seniority profiles + archetype-aware intake hardening)
94
+
95
+ Additive release. No breaking changes. Completes the A1/A3 intake work, adds the seniority profile primitive, and hardens the router against state drift.
96
+
97
+ ### Added
98
+
99
+ - **Seniority profile (`strict` / `standard`)** — a project now carries a `Profile:` field (STATE.md + tracking.json), resolved as `$QUALIA_PROFILE` (env wins) → STATE.md → tracking.json → `strict` (safe default; anything but the exact string `standard` coerces to `strict`). `state.js check` surfaces it; `state.js init --profile` sets it and re-init preserves it. `state.js` only stores/surfaces the field — gate enforcement is a documented contract owned by the consuming skill (`qualia-scope`), not enforced in `state.js`. Router + `guide.md` document the semantics: `strict` = hard gates, no waivers; `standard` = advisory, waiver logged to `.planning/decisions/`. (`bin/state.js`, `skills/qualia/SKILL.md`, `guide.md`)
100
+ - **`web-app` + `voice-agent` archetypes** — completes the archetype Definition-of-Done set that `qualia-scope` reads at runtime (`references/archetypes/${ARCHETYPE}.md`); the skill previously broke for these two selections. `qualia-scope` also registered in `bin/command-surface.js` `ACTIVE_SKILLS`. (`references/archetypes/web-app.md`, `references/archetypes/voice-agent.md`)
101
+
102
+ ### Fixed
103
+
104
+ - **Router no longer self-cancels on a drifted `STATE.md`.** `state.js check` read phase/status from `STATE.md` and returned `NO_PROJECT` (exit 1) whenever it was missing/corrupt — even with `tracking.json` intact — which made the `/qualia` router's parallel command batch cancel its siblings. `check` now reconstructs from the surviving file, exits 0, and routes to `state.js fix`; true `NO_PROJECT` (both files absent) is unchanged. (`bin/state.js`)
105
+
106
+ ### Changed
107
+
108
+ - **De-brittled skill-surface tests.** `tests/lib.test.sh`'s surface manifest and trust-score fixtures now derive from `command-surface.js` `ACTIVE_SKILLS` instead of hardcoding a count — adding or removing a skill no longer requires test edits.
109
+
110
+ ### Docs
111
+
112
+ - **A5 multi-person concurrency spec + line-cited implementation plan** (`docs/implementation-handoff.md`, `docs/a5-concurrency-plan.md`): partition state per-increment with `claimed_by`/`branch`, demote `STATE.md` to a generated dashboard, so concurrent contributors on different increments never conflict on planning files. Build deferred (highest-risk `state.js` rework — its own effort).
113
+
114
+ ### Deferred
115
+
116
+ - **Command-surface collapse.** Retiring `qualia-discuss` into `qualia-scope` is blocked on `qualia-scope` first absorbing the PROJECT MODE intake interface (`PROJECT_TYPE`, `project-discovery.md`); retiring it now would break `qualia-new` kickoff. All 26 skills remain active.
117
+
118
+ ## [6.4.0] - 2026-05-28 (Audit-driven remediation + mechanism grafts)
119
+
120
+ Substantive additive release. No breaking changes. Consolidates four feature commits previously labeled v6.3.1–v6.3.4 in commit messages (never published) plus today's CI cleanup and polish.
121
+
122
+ ### Added
123
+
124
+ - **`/qualia-idk` restored + enhanced** — three-scan diagnostic (planning + code + conversation/memory), returns guidance plus a paste-ready Qualia command sequence. Was retired in v6.3.0; owner pivot brought it back deeper. (`skills/qualia-idk/SKILL.md`)
125
+ - **`/qualia-secure`** — security audit of agent config (CLAUDE.md / settings.json / hooks / MCP). Two-pass: fast static pattern scan + optional Opus 4.7 adversarial red/blue/auditor pipeline. (`skills/qualia-secure/SKILL.md`, `bin/security-scan.js`)
126
+ - **`hooks/pre-compact.js`** — PreCompact hook writes `.planning/.compaction-snapshot.md` with in-flight state before context compaction. No git pollution (unlike the v6.2.0-removed version) — pure sidecar that `/qualia-resume` and `session-start` consume.
127
+ - **`bin/learning-candidates.js`** (`qualia-framework learn-scan`) — scans recent commits + daily-log for repeated fix-scope patterns and hot files; writes `~/.claude/knowledge/learning-candidates.md` with action hints.
128
+ - **`bin/status-snapshot.js`** (`qualia-framework status`) — portable operator snapshot (install health + active project + work in flight + ERP queue + memory state). Markdown / `--json` / `--write` / `--exit-code`.
129
+ - **`bin/security-scan.js`** (`qualia-framework secure`) — static scanner for AI-agent config surfaces. Detects leaked secrets (Anthropic/OpenAI/GitHub/AWS/Supabase JWT/Vercel/Bearer), unscoped Bash tool, service_role-in-client smells, hook hygiene issues. `--deep` emits a prompt pack for the `/qualia-secure` adversarial pass.
130
+ - **`bin/prune-deprecated.js`** — shared helper used by both install and doctor. Detects and removes ghost retired skills from `~/.claude/skills/` and `~/.codex/skills/`. Errors are surfaced (not swallowed) so users see permission/mount issues that would otherwise leave trap skills installed.
131
+ - **`SOUL.md`** — 17-line identity statement (Identity / Stance / 5 named principles / What We Reject). Linked from `README.md` and `CLAUDE.md`.
132
+ - **`FLAGS.md`** — single-page index of every Qualia skill flag, grouped by lane.
133
+ - **`TROUBLESHOOTING.md`** — 185-line problem-to-fix doc, grounded in actual error strings from `bin/state.js`, hooks, ERP retry.
134
+ - **Hard rules now pair negative with positive principle** in `CLAUDE.md` and `AGENTS.md` (italic explanation per rule).
135
+
136
+ ### Changed
137
+
138
+ - **`doctor` auto-prunes ghost retired skills** in every install home and lists each failure if any prune step errors out.
139
+ - **17 SKILL.md descriptions slimmed** to one verb-phrase + short Triggers list (was 3–6 sentence trigger essays). Aggregate savings: ~600 words per session in harness-routing instructions.
140
+ - **`README.md` and `guide.md` openers slimmed** — version-history walls (35+ and 25+ lines respectively) moved to `CHANGELOG.md`. Both files now lead with thesis + first commands + cross-links (`SOUL.md` / `FLAGS.md` / `TROUBLESHOOTING.md`).
141
+ - **`ACTIVE_SKILLS` count: 23 → 25** (`qualia-idk` restored, `qualia-secure` added).
142
+ - **Hooks count: 12 → 13** (`pre-compact.js` reintroduced with sidecar mechanism).
143
+
144
+ ### Fixed
145
+
146
+ - **macOS CI** — `tests/refs.test.sh` refactored off bash 4 `declare -A` (macOS ships bash 3.2). Replaced with temp-file key-value store. macOS CI went from red since 2026-05-21 to all 6/6 green on first PR after the fix.
147
+ - **CI matrix cleanup** — Windows runners dropped from the matrix. Qualia is Cyprus-stack (Linux/macOS dev); Windows isn't supported. Two coercion attempts (`pwd -W`, `cygpath -m`) didn't catch every shell-side path interpolation site, and the cure was more brittle than the disease. The workflow comment documents the path forward if Windows support is ever needed (env-var-pass paths instead of bash-interpolating them).
148
+ - **CodeRabbit advisory** — `bin/prune-deprecated.js` no longer silently swallows filesystem errors; returns `{removed, errors}` and surfaces failures via doctor or non-zero exit on the CLI.
149
+ - **CodeRabbit advisory** — `README.md` "First commands" code fence got a `text` language specifier (satisfies MD040).
150
+ - **Stale `/qualia-idk` reference** in `/qualia` skill description removed; clean separation between the mechanical router and the deep diagnostic.
151
+
152
+ ### Audit artifacts
153
+
154
+ Three `.planning/codebase/` audit documents drove this release: `qualia-confusion-audit.md` (16 cited defects with file:line citations), `ecc-vs-qualia.md` (8-pair head-to-head skill comparison), `qualia-vs-ecc-final.md` (16-query NotebookLM consolidated audit with execution order). The release closes 14 of 14 actionable items from the final audit; 1 item (Q2 AGENTS.md skill table) was deliberately rejected to preserve the 25-line instruction-budget cap.
155
+
156
+ ## [6.3.0] - 2026-05-23 (Harness hardening + command surface reduction)
157
+
158
+ ### Changed
159
+
160
+ - **Default install surface reduced from 35-ish skills to 23 active skills.** `bin/command-surface.js` is now the canonical active/retired skill manifest; installer summary and Claude/Codex skill copying use it.
161
+ - **Retired helper commands are deleted from shipped skill source and pruned on upgrade.** The installer still removes folded helpers such as `qualia-debug`, `qualia-vibe`, `qualia-idk`, `qualia-pause`, `qualia-resume`, `qualia-zoom`, `qualia-issues`, `qualia-triage`, `qualia-hook-gen`, `qualia-skill-new`, and `qualia-flush` from older installed homes.
162
+ - **`/qualia-polish --vibe` absorbs the separate vibe command.** Vibe token/extract scripts now ship under `skills/qualia-polish/scripts/`.
163
+
164
+ ### Added
165
+
166
+ - **`bin/harness-eval.js`** writes deterministic project eval artifacts under `.planning/evals/`, combining state health, ledger validation, plan contract validation, machine evidence, verification report status, trust score, and ERP linkage into a 0-100 score.
167
+ - **ERP reports and project snapshots carry the latest harness eval summary** (`status`, `score`, `phase`, `generated_at`, artifact path).
168
+ - **`qualia-framework eval` CLI** runs the harness eval (`--run --write --json` supported).
169
+
170
+ ### Fixed
171
+
172
+ - **PASS state transitions now require evidence.** When a phase contract exists, `state.js transition --to verified --verification pass` refuses to pass without a clean `.planning/evidence/phase-N-contract-run.json`; it also refuses PASS if the verification report contains `INSUFFICIENT EVIDENCE`.
173
+
174
+ ## [6.2.11] - 2026-05-23 (Owner approval integrity)
175
+
176
+ ### Changed
177
+
178
+ - **Fawzi OWNER code changed** from `QS-FAWZI-01` to `QS-FAWZI-11`.
179
+ - **Employee force-ship override is blocked.** `QUALIA_SHIP_FORCE=1` is OWNER-only in `/qualia-ship` and in the deploy hook.
180
+ - **Ship refusals are shorter and routed.** When the framework refuses deploy from the wrong state, it says why and prints the correct next command.
181
+
182
+ ### Added
183
+
184
+ - **`fawzi-approval-guard.js`** silently records employee proxy-approval claims such as "Fawzi said OK" into a local counter and ERP policy-event queue.
185
+ - **ERP policy-event contract** for `/api/v1/policy-events`.
186
+
187
+ ## [6.2.9] - 2026-05-22 (Codex hook noise + status line)
188
+
189
+ ### Fixed
190
+
191
+ - **PreToolUse hook spam.** Codex was printing eight "Running PreToolUse hook: Qualia X..." status messages on every Bash tool call, even though six of the eight hooks would immediately exit 0 because their `if` filter excluded them. Codex's hook schema doesn't include an `if` field — only `command`, `commandWindows`, `timeout`, `async`, `statusMessage`. The `if:` we shipped was silently dropped and Codex showed the `statusMessage` for every entry in the matched group before running it. v6.2.9 removes `statusMessage` from all conditional hooks; only the always-running hooks (`auto-update`, `git-guardrails`) still show a status line. Conditional hooks render silently.
192
+ - **`pre-deploy-gate.js` firing on unrelated commands.** Claude Code's `if: "Bash(vercel --prod*)"` matcher does substring matching (not glob), so any Bash command containing the literal text `vercel --prod` or `pre-deploy-gate` as a token tripped the gate and ran the full tsc/lint/test/build sweep. Added an inline `selfFilter()` IIFE at the top of the hook that reads `tool_input.command` from stdin and exits 0 fast unless the command actually starts with `vercel --prod` or `vercel deploy --prod`. Same pattern added to `pre-push.js`.
193
+
194
+ ### Added
195
+
196
+ - **`[tui] status_line = [...]` in Codex `config.toml`.** Installer now writes (or appends to existing config) the rich Codex bottom status line: `model-with-reasoning · task-progress · current-dir · git-branch · context-used · five-hour-limit · weekly-limit`. Codex doesn't support custom-command status lines like Claude's `statusLine`, so the Qualia phase/state info continues to render via the `SessionStart` banner at the top of the session; this commit ensures Codex's native bottom status line is at least configured for richness, not left to default. Existing user configs are appended-to only when they have no `[tui]` block; otherwise left untouched.
197
+
198
+ ## [6.2.8] - 2026-05-22 (Codex /goal integration + install hardening)
199
+
200
+ ### Fixed
201
+
202
+ - **Codex agent TOMLs missing `name` field.** `renderCodexAgentToml` now emits `name = "..."` as the first line of every `~/.codex/agents/*.toml`. v6.2.7 shipped without this and Codex 0.133 rejected all 9 agent files at session start with `Ignoring malformed agent role definition: ... must define a non-empty \`name\``.
203
+ - **ERP API key missing on Codex installs.** When both targets are installed, the installer now mirrors `~/.claude/.erp-api-key` → `~/.codex/.erp-api-key` (0600). Without this, every ERP write from a Codex session 401'd and the retry queue grew silently.
204
+ - **Deprecated skills lingered after upgrade.** Installer now prunes `qualia-task`, `qualia-quick`, `qualia-polish-loop`, `qualia-design`, `qualia-prd` from both `~/.claude/skills/` and `~/.codex/skills/` on every run. Previously left orphaned after the v5.7.0 / v5.8.0 / v4 consolidations.
205
+
206
+ ### Added
207
+
208
+ - **`bin/codex-goal.js`** — reads `.planning/STATE.md` + `.planning/ROADMAP.md` and emits a `/goal {objective}` line plus a token-budget suggestion calibrated to scope (`phase` 80k · `task` 30k · `feature` 30k · `quick` 10k). Output is meant to be pasted into a Codex session or consumed by the model via the `update_goal` tool.
209
+ - **`rules/codex-goal.md`** — guidance: detect Codex runtime, run `codex-goal.js`, call `update_goal` or surface the `/goal` line. Skip entirely on Claude Code.
210
+ - **`/goal` integration wired into phase-start skills** — `qualia-build`, `qualia-plan`, `qualia-feature` each open with a Step 0 that references `rules/codex-goal.md`. Codex users get native burn-vs-budget tracking against the active phase/task objective without extra typing.
211
+
212
+ ## [6.2.7] - 2026-05-21 (Codex runtime compatibility)
213
+
214
+ ### Added
215
+
216
+ - **Codex-native install surface** now writes `~/.codex/hooks.json`, `~/.codex/hooks/*.js`, `~/.codex/agents/*.toml`, `~/.codex/bin/*.js`, `~/.codex/rules/`, `~/.codex/skills/`, `~/.codex/qualia-design/`, `~/.codex/qualia-templates/`, `~/.codex/knowledge/`, and `~/.codex/qualia-guide.md`.
217
+ - **Codex agent conversion** turns framework `agents/*.md` frontmatter/body into Codex TOML agents.
218
+
219
+ ### Changed
220
+
221
+ - Shared runtime scripts and hooks now resolve their Qualia install home from `~/.claude` or `~/.codex`, so Codex-only installs no longer depend on a Claude install existing.
222
+ - Installer tests and packaged smoke tests now prove Codex runtime files are present, not just `AGENTS.md`.
223
+
224
+ ## [6.2.6] - 2026-05-21 (project snapshot upload)
225
+
226
+ ### Added
227
+
228
+ - **`qualia-framework project-snapshot --upload`** posts the current project snapshot to ERP's project snapshot intake.
229
+ - **Upload coverage** verifies the Framework sends the 0-to-100 progress object, ERP identifiers, and bearer token to `/api/v1/project-snapshots`.
230
+
231
+ ## [6.2.5] - 2026-05-21 (project snapshot export)
232
+
233
+ ### Added
234
+
235
+ - **`qualia-framework project-snapshot`** exports a single project progress JSON object for ERP/admin import.
236
+ - **`--write` snapshot mode** writes `.planning/snapshots/project-snapshot-*.json` with shared IDs, current milestone/phase, closed milestones, lifetime counters, and a 0–100 progress percentage.
237
+
238
+ ## [6.2.4] - 2026-05-21 (report payload contract hardening)
239
+
240
+ ### Added
241
+
242
+ - **`bin/report-payload.js`** is now the canonical Framework -> ERP report payload builder used by `/qualia-report`.
243
+ - **Executable coverage** now proves slug-like ERP IDs are omitted while canonical UUID fields are sent, keeping admin/project linking reliable.
244
+
245
+ ## [6.2.3] - 2026-05-21 (ERP ID guard hotfix)
246
+
247
+ ### Fixed
248
+
249
+ - **`/qualia-report`** now only sends `erp_project_id`, `client_id`, and `workspace_id` when values are UUID-shaped. This prevents ERP `422 VALIDATION_FAILED` responses when local `tracking.json` contains slug-like values such as `acme` or `qualia-solutions`.
250
+ - **ERP contract docs and work-packet template** now label ERP-native identifiers as UUIDs. Local slugs remain in `project_id` and `team_id`.
251
+
252
+ ## [6.2.2] - 2026-05-21 (memory/ERP operating model)
253
+
254
+ This patch incorporates the Framework/Memory/ERP connection note into the framework without reviving the old passive git-scrape model.
255
+
256
+ ### Added
257
+
258
+ - **`docs/ecosystem-operating-model.md`** documents the boundary: Framework builds, Memory remembers, ERP operates. `.planning` imports stay explicit and approved; ERP does not depend on passive git scraping or hook-created bot commits.
259
+ - **`docs/reviews/v6.2.2-memory-erp-audit.md`** records how the downloaded Framework/Memory/ERP note was applied and where it needed correction.
260
+ - **`templates/work-packet.md`** gives ERP/admins a clean way to hand approved project context into Claude Code or Codex sessions.
261
+ - **`docs/release.md`** documents the pre-publish, publish, and post-publish proof path so local package smoke is not mistaken for public install proof.
262
+ - **`tests/published-install-smoke.test.sh`** is the release-only public smoke: it fails until npm `latest` matches `package.json`, then runs `npx qualia-framework@latest install` into an isolated HOME/cache and verifies Claude + Codex output.
263
+
264
+ ### Changed
265
+
266
+ - **`tracking.json` and `/qualia-report`** now preserve/pass through optional `erp_project_id`, `client_id`, and `workspace_id` identifiers when present, so ERP dashboards can link reports without guessing from names.
267
+ - **`tests/install-smoke.test.sh`** now isolates npm cache/log/userconfig state and reports npm pack stderr instead of swallowing pack failures.
268
+ - **`skills/qualia-report`** now shows the safe piped `set-erp-key` command instead of the retired positional-key syntax.
269
+
270
+ ## [6.2.1] - 2026-05-21 (revival audit surface guard)
271
+
272
+ This patch closes the remaining active-surface drift found during the framework revival audit. v6.2.0 removed hook-created bot commits, but several user-facing surfaces still described the old model: ERP reads from git, `pre-compact` saves state, 32 skills, and stale v6.0 headings.
273
+
274
+ ### Changed
275
+
276
+ - **README / guide / onboarding** now reflect the current package identity, 33-skill surface, `/qualia-vibe`, and the explicit `/qualia-report` ERP contract.
277
+ - **`skills/qualia-road`, `skills/qualia-milestone`, `agents/roadmapper`, and `docs/erp-contract.md`** now describe `tracking.json` as local/report telemetry, not passive ERP git input.
278
+ - **`skills/qualia-verify`** now states the current fail-closed `INSUFFICIENT EVIDENCE` behavior directly instead of describing the old false-pass vector as if it still applied.
279
+ - **`skills/qualia-polish`** now requires optional Lighthouse/axe gate skips to be reported, not silently hidden.
280
+ - **`docs/reviews/v6.2.1-revival-audit.md`** records the evidence, remaining release blocker, and next high-leverage work.
281
+
282
+ ### Tests
283
+
284
+ - **`tests/refs.test.sh`** now also guards stale active-surface claims: passive ERP tracking, removed pre-compact guidance, stale skill count, stale README version, old `INSUFFICIENT EVIDENCE` wording, and silent optional gate language.
285
+ - **`tests/install-smoke.test.sh`** builds the actual npm tarball, extracts it, runs the packaged installer with target `Both`, and verifies Claude `CLAUDE.md`, Codex `AGENTS.md`, 11 hooks, no `pre-compact`, and matching installed config version.
286
+
287
+ ## [6.2.0] - 2026-05-20 (no more hook-created bot commits)
288
+
289
+ Two hooks were creating bot commits whose only purpose was to feed a phantom consumer:
290
+
291
+ - **`hooks/pre-push.js`** — created `chore(track): ERP sync …` on every push to stamp `.planning/tracking.json` into git. Rationale: "the ERP at portal.qualiasolutions.net reads tracking.json from GitHub." That rationale was false; the ERP repo has no route, cron, MCP, or background worker that reads `tracking.json` (verified — search returns only marketing copy and one substring-match comment).
292
+ - **`hooks/pre-compact.js`** — committed STATE.md + tracking.json on every Claude Code context compaction. Rationale: "preserve mutations across compactions." Misdiagnosed; `bin/state.js` already provides crash-safe atomic writes (`state.js:18`) plus a write-ahead journal (`state.js:36-64`) and recovery (`state.js:49-63`). Compaction is in-memory only — disk writes survive it without help.
293
+
294
+ The bot commits were pushing data into git for a consumer that doesn't exist, polluting every Qualia project's history, and on any Vercel project with GitHub auto-deploy accidentally on, triggering redeploys for nothing.
295
+
296
+ v6.2 strips both. The pre-push hook still stamps `tracking.json` locally so `bin/statusline.js`, `hooks/stop-session-log.js`, and `/qualia-report` see fresh telemetry — it just doesn't touch git anymore. The pre-compact hook is deleted outright; `state.js` already covers crash safety with a stronger guarantee (atomic + journaled) than git ever did.
297
+
298
+ ### Changed
299
+
300
+ - **`hooks/pre-push.js`** — rewrite. Stamps `last_commit`, `last_updated`, `last_pushed_at` locally only. No `git add`, no `git commit`, no rollback dance, no branch-guard mirroring (irrelevant without a commit). Net code reduction: ~220 → ~85 lines.
301
+ - **`docs/erp-contract.md`** — strikes the false "ERP reads `tracking.json` directly from git" claim and removes the dangling `GET /api/v1/tracking/:project` endpoint that was documented but never implemented on the ERP.
302
+ - **`bin/install.js`** — fixes the false "tracking.json syncs to ERP on every push" install-summary line; drops empty hook-event keys after Qualia-owned cleanup so settings.json doesn't accumulate empty `PreCompact: []` arrays.
303
+
304
+ ### Removed
305
+
306
+ - **`hooks/pre-compact.js`** — deleted. Added to `DEPRECATED_HOOKS` array in `bin/install.js` so existing installs get the file unlinked from `~/.claude/hooks/`. Added to `QUALIA_LEGACY_HOOK_FILES` in `bin/cli.js` so the `wire` path also strips it. The PreCompact event entry in user `settings.json` is detected and removed; if PreCompact is now empty, the key is dropped.
307
+
308
+ ### Migration
309
+
310
+ No action required. Existing `chore(track): ERP sync` and `state: pre-compaction save` commits in your project histories stay (you can't unmake history); v6.2 just stops creating new ones. Existing ERP integrations are unaffected — `/qualia-report` continues to POST to `/api/v1/reports` exactly as before. On upgrade, the framework will:
311
+
312
+ 1. Delete `~/.claude/hooks/pre-compact.js` from existing installs.
313
+ 2. Strip any `pre-compact.js` references from your `~/.claude/settings.json`.
314
+ 3. Drop the `PreCompact` key entirely if it becomes empty.
315
+
316
+ ## [6.1.0] - 2026-05-17 (design pivot path — /qualia-vibe + design-surface fixes)
317
+
318
+ The design path was missing a fast pivot. `/qualia-polish` polishes within a chosen vibe; `/qualia-polish --redesign` rebuilds from scratch (~30 min). When a client says "different vibe" and you want a 3-minute token swap, neither fits. v6.1 adds **`/qualia-vibe`** — the impeccable middle path.
319
+
320
+ This release also closes the design-surface bugs surfaced by the v6.0 audit (viewport mismatch, slop-detect path resolution, dead `/qualia-design` references, bounce-easing contradiction) and adds the EventMaster discipline as a real rule.
321
+
322
+ ### New — `/qualia-vibe` skill
323
+
324
+ Layout-preserving aesthetic pivot. Modes:
325
+
326
+ - **Default** — propose ONE direction (per `rules/one-opinion.md`), justify it from PRODUCT.md / anti-references / scene sentence, apply on approval. Never enumerates a menu of options.
327
+ - **`--variants N`** — the opt-in menu, when the user explicitly asked for choices. Default N=3, max 5. Uses `AskUserQuestion`.
328
+ - **`--extract <URL or image path>`** — reverse-engineer a DESIGN.md draft from a reference site or screenshot. Captures via `playwright-capture.mjs`, runs an extract-mode prompt (description, not scoring), emits a DESIGN.md draft for user review.
329
+ - **`--sync [--write]`** — show drift between code (CSS vars, Tailwind config, font imports) and DESIGN.md. Three categories reported: undocumented (in code, not declared), orphaned (declared, not used), drifted (different values). With `--write`, patches DESIGN.md to match code.
330
+
331
+ Hard contract: vibe NEVER touches JSX structure, routing, data flow, or layout grid. Only tokens (color, type, depth, motion) + DESIGN.md sections 1, 2, 3, 6, 7. If a pivot would need structural change, vibe stops and routes to `/qualia-polish --redesign`.
332
+
333
+ Supporting scripts:
334
+
335
+ - `skills/qualia-vibe/scripts/tokens.mjs` — `sync` (code↔DESIGN.md diff + patch) and `propose-variants` (LLM prompt scaffold). Pure utility, no LLM call.
336
+ - `skills/qualia-vibe/scripts/extract.mjs` — capture orchestrator + extract-mode prompt scaffold. Pure utility, no LLM call.
337
+ - Reuses `skills/qualia-polish/scripts/playwright-capture.mjs`, `bin/slop-detect.mjs`, `agents/visual-evaluator.md`.
338
+
339
+ ### New — `rules/one-opinion.md`
340
+
341
+ Codifies the EventMaster discipline (from a real session where the user pivoted aesthetic 3 times in one block and finally said `ANYTHING JUST CHANGE IT STOP ASKING`). Rule: when proposing a design decision the user has not already named, propose ONE opinionated direction with justification — never a menu. If rejected, ask what didn't fit and propose ONE replacement. Lazy-loaded by `/qualia-vibe`, `/qualia-polish` Stage 0, `/qualia-new` DESIGN.md step.
342
+
343
+ ### Fixed — design-surface bugs from v6.0 audit
344
+
345
+ - **Viewport mismatch:** `/qualia-polish` SKILL.md Stage 4 said 1280px desktop. `agents/visual-evaluator.md`, `REFERENCE.md`, and `playwright-capture.mjs` all use 1440. Aligned to 1440.
346
+ - **slop-detect path in `loop.mjs`:** Was hardcoded to `~/.claude/bin/slop-detect.mjs` and silently skipped the gate if missing. Now searches `SLOP_DETECT_SCRIPT` env, `~/.claude/bin/...`, and the framework-relative path. Skip is now logged-on-miss, not silent.
347
+ - **`loop.mjs commit-fix` git identity:** Was failing on fresh clones with no global git config. Now sets `Qualia Polish Loop / polish-loop@qualia.solutions` inline so the commit works regardless.
348
+ - **Dead `/qualia-design` references:** `qualia-design/frontend.md` still listed `/qualia-design` as an active command — it was deleted in v4.5. Replaced with `/qualia-polish` and `/qualia-vibe`.
349
+ - **Bounce easing token contradicting design-laws:** `qualia-design/design-reference.md` shipped `--ease-spring: cubic-bezier(0.34, 1.56, …)` as a generic token — but `design-laws.md` §6 and `slop-detect.mjs` MED-BOUNCE-EASING ban that exact curve. Removed the token, replaced with a note explaining when (and only when) brand-register vibes can override the ban.
350
+ - **Stale "deferred to v5.2" in REFERENCE.md:** Multi-route and reduced-motion have been implemented for releases. Removed from the deferred list and replaced with an "aesthetic pivot belongs in /qualia-vibe" pointer.
351
+ - **Menu-of-options anti-pattern in `/qualia-polish` Stage 0:** Brief format listed `{editorial · brutalist · luxury · maximalist · …}` as options. Per `rules/one-opinion.md`, agent now proposes ONE direction inferred from PRODUCT.md. Pushback routes to `/qualia-vibe`, not to enumerating more.
352
+
353
+ ### Changed — `bin/slop-detect.mjs`
354
+
355
+ - **Added banned fonts:** Montserrat, Poppins, Lato, Open Sans (already banned in `qualia-design/design-brand.md` but missing from the linter).
356
+ - **Added `--watch` flag:** Re-scan on file change with 200ms debounce. Watches tracked extensions (`tsx/jsx/ts/js/css/scss/html/svelte/vue/astro`). Makes slop-detect proactive instead of pre-commit only.
357
+ - **Broadened default scan paths:** Added `packages/` and `apps/` to the default roots (turbo / nx / pnpm-workspaces monorepo conventions).
358
+
359
+ ### Surface counts
360
+
361
+ - **33 skills** (was 32). `/qualia-vibe` added.
362
+ - **8 rules** in `rules/` (7 always-loaded + 1 lazy-loaded). `rules/one-opinion.md` added (lazy-loaded by design-adjacent skills).
363
+ - Same 9 agents, same 12 hooks.
364
+
365
+ ### Migration
366
+
367
+ - Run `npx qualia-framework@latest install` (or `migrate`) once. Pulls in `/qualia-vibe` and `rules/one-opinion.md`.
368
+ - `/qualia-vibe --extract` requires Playwright to be installed in the target project (same dependency as `/qualia-polish --loop`).
369
+ - `/qualia-vibe --sync` works on any project with `app/globals.css`, `src/app/globals.css`, or similar, and optionally `tailwind.config.{ts,js,mjs,cjs}`.
370
+ - No skill removed, no command renamed.
371
+
372
+ ---
373
+
374
+ ## [6.0.0] - 2026-05-17 (audit, cleanup, reliability)
375
+
376
+ A wide-surface audit pass. No new flagship feature — every change is a real bug, a silent failure surfaced, an outdated reference replaced, or a token-budget reduction. The framework is the same shape and the road commands behave exactly as before; what changed is that broken edges are now fixed.
377
+
378
+ ### Fixed — uninstall and migrate left orphan files on disk
379
+
380
+ `cli.js` shipped a `QUALIA_HOOK_FILES` manifest listing 9 hooks but the framework ships 12. Uninstall left `env-empty-guard.js`, `supabase-destructive-guard.js`, and `vercel-account-guard.js` orphaned under `~/.claude/hooks/`. Same shape for agents: `QUALIA_AGENT_FILES` was missing `visual-evaluator.md`. And `cmdMigrate()` `requiredBashHooks` was missing the same 3 hooks, so users on `qualia-framework migrate` ended up with an incomplete hook set vs. those on a fresh `install`. All three manifests now match what ships.
381
+
382
+ ### Fixed — silent catches in hooks
383
+
384
+ `auto-update.js` had two bare `catch {}` blocks (the npm-version fetch and the top-level wrapper) that swallowed every error type including ENOMEM and ETIMEDOUT. `pre-compact.js` had the same shape around the commit logic. Both now write to `~/.claude/.qualia-traces/` so failures are debuggable instead of vanishing. `env-empty-guard.js` was exiting 2 (BLOCK) on any unparseable stdin payload — which meant a malformed JSON from an unrelated tool call would block the user from running `vercel env`. Now allows on parse error and only blocks when it actually matched a `vercel env add` with an empty value.
385
+
386
+ ### Fixed — phantom `rules/frontend.md` references
387
+
388
+ `CLAUDE.md`, `AGENTS.md`, and `skills/qualia-feature/SKILL.md` pointed at `rules/frontend.md` which has not existed since the design substrate moved to `qualia-design/` in v4.5. Agents loading these references hit a dead end. Now points at `qualia-design/frontend.md`. Also added `rules/architecture.md` (the deep-modules rule from v5.x) to the discoverable substrate list.
389
+
390
+ ### Fixed — skill bugs that the registry never caught
391
+
392
+ - `/qualia-learn` declared `Read, Write, Edit, Glob, Grep` in `allowed-tools` but its process calls `node ~/.claude/bin/knowledge.js` and `git add`. Without `Bash` the skill literally could not run its own instructions. Added.
393
+ - `/qualia-map` describes an `AskUserQuestion` Re-scan? prompt but did not declare the tool. Added.
394
+ - `/qualia-plan` Rule 2 said "Max 3 revision cycles" while the description and process said "max 2." Reconciled to 2 (matches the actual revision-loop code).
395
+ - `/qualia-postmortem` had `skills/qualia-design/SKILL.md` in its design-regression lookup table — that path has not existed since the polish skill consolidated design work. Now points at `qualia-polish` + `qualia-design/design-laws.md`.
396
+
397
+ ### Fixed — agent tool frontmatter gaps
398
+
399
+ `agents/planner.md` referenced `mcp__context7__*` tools but did not declare them in frontmatter; same for `agents/qa-browser.md` and Playwright MCP. Both agents were unable to call the tools their process described. Both frontmatters updated.
400
+
401
+ ### Fixed — hardcoded `/tmp` paths
402
+
403
+ `agents/verifier.md` drift audit wrote to `/tmp/used-tokens` and `/tmp/declared` (Windows-incompatible, symlink-attackable on multi-user systems). Now uses `mktemp` with cleanup. `agents/qa-browser.md` dev-server log goes to `${TMPDIR:-/tmp}/qualia-dev-server-$$.log` instead.
404
+
405
+ ### Changed — `tests/run-all.sh` replaces the `&&`-chain test orchestrator
406
+
407
+ `npm test` used to chain 8 suites with `&&`, so the first failure aborted everything else and you only ever saw the failure of the earliest-failing suite. New `tests/run-all.sh` runs every suite, collects failures, and prints which suites failed at the end. Also stripped silent `|| true` from `slop-detect.test.sh` so genuine slop-detect crashes can no longer pass the suite invisibly.
408
+
409
+ ### Changed — `rules/trust-boundary.md` extracts duplicated security block
410
+
411
+ Builder, planner, verifier, and visual-evaluator each carried a ~150-token inline copy of the trust-boundary block (~600 tokens duplicated across the four agents). Extracted to `rules/trust-boundary.md`; agents reference it with one line and add the role-specific reporting shape. Net: ~500 tokens saved per phase that spawns the full agent set, plus a single canonical place to update the rule.
412
+
413
+ ### Removed — stale version stamps from user-facing skill surfaces
414
+
415
+ `/qualia-road` had four "v4.5.0+" / "v5.0+" / "v5.1+" / "v5.3+" headings; removed. `/qualia-new` headings stamped `(v5.0 — REQUIRED)` / `(v4.5.0 OKLCH-first)`; removed. `/qualia-flush` had a "deferred to v4.3.0" caveat that has long since been fixed in `knowledge.js`; updated to reflect current behavior. Similar cleanups in `/qualia-polish`, `/qualia-verify`, `/qualia-milestone`, `/qualia-hook-gen`, `/qualia-feature`. `/qualia-feature` description no longer mentions the removed `/qualia-quick` and `/qualia-task`. Stale `<!-- v5.9: -->` comments in agent headers stripped.
416
+
417
+ ### Archived — pre-v4 CHANGELOG entries
418
+
419
+ Moved v2.x and v3.x release notes (851 lines) to `docs/archive/CHANGELOG-pre-v4.md`. Main `CHANGELOG.md` now ends at v4.0.0 with a pointer to the archive. The active changelog dropped from 2726 to 1875 lines.
420
+
421
+ ### Fixed — `templates/help.html` drift
422
+
423
+ Showed "28 skills" (actual 32) and was missing entries for `/qualia-hook-gen`, `/qualia-issues`, `/qualia-road`, `/qualia-triage`, `/qualia-zoom`, `/zoho-workflow`. Added. `docs/onboarding.html` version-stamped `v5.5`; bumped to v6.0.
424
+
425
+ ### Test posture
426
+
427
+ 489 tests still passing on the full suite. No tests removed; one test (em-dash detection) tightened to also assert exit code, not just message presence. Test runner is now fail-collect, not fail-fast, so future regressions in early suites do not hide later regressions.
428
+
429
+ ### Migration notes (v5.9.x → v6.0.0)
430
+
431
+ - Run `npx qualia-framework@latest install` (or `migrate`) once. The migrate path now wires the three v5.0 hooks (`vercel-account-guard.js`, `env-empty-guard.js`, `supabase-destructive-guard.js`) that earlier migrate runs missed.
432
+ - If you had a previous uninstall leave orphan hook files, re-run `npx qualia-framework@latest uninstall` to clean them up cleanly.
433
+ - No skill removed; no command renamed; no API change.
434
+
435
+ ---
436
+
437
+ ## [5.9.2] - 2026-05-16 (hook ordering + ERP payload fixes)
438
+
439
+ **Two production bugs that were silently corrupting state.** Neither was caught by tests because both required specific runtime conditions to reproduce — a blocked push in one case, a fresh project with no session_started_at stamp in the other. Both surfaced from real session traces, not synthetic testing.
440
+
441
+ ### Fixed — pre-push.js no longer orphans a bot commit when the push is blocked
442
+
443
+ - **Root cause:** Claude Code PreToolUse hooks run *in parallel*, not in declared order. `pre-push.js` (stamps `tracking.json` and creates a bot commit) and `branch-guard.js` (blocks non-OWNER pushes to main/master) both fire on `git push *`. When `pre-push` ran and `branch-guard` exited 2, the bot commit was already in the local branch — orphaned, sitting around to be shipped on the next push to a feature branch.
444
+ - **Fix:** `pre-push.js` now self-gates with a `wouldBeBlocked()` mirror of `branch-guard`'s checks (role from config + refspec parse + current-branch fallback). If the push would be blocked, it skips `commitStamp()` entirely and exits 0. `branch-guard` still produces the user-facing block message via its own exit-2.
445
+ - **Why not just declare ordering?** Claude Code hook config doesn't expose execution-order priorities for PreToolUse. The only safe primitive is self-gating. When v6.0 extracts the shared runtime, both hooks call one `wouldBeBlocked()` from `lib/`.
446
+
447
+ ### Fixed — qualia-report ERP payload no longer 422s on empty datetimes
448
+
449
+ - **Root cause:** The payload builder coalesced missing `session_started_at` and `last_pushed_at` to `''` via `t.session_started_at||''`. The ERP validator (Pydantic-style) accepts missing-Optional but rejects empty-string-as-datetime → HTTP 422 on every fresh project, never-pushed branch, or brand-new session.
450
+ - **Fix:** Conditional spread in the payload object — `...(t.session_started_at?{session_started_at:t.session_started_at}:{})` — drops the key entirely when the value is empty. ERP accepts the missing-Optional cleanly. Applied to both fields.
451
+ - **Verified:** Manual retry without the empty datetime keys succeeded with HTTP 200 in the session that caught the bug.
452
+
453
+ ### Files changed
454
+
455
+ - `hooks/pre-push.js` — added `wouldBeBlocked()` and early-exit
456
+ - `skills/qualia-report/SKILL.md` — payload builder uses conditional spreads
457
+ - `package.json`, `README.md`, `guide.md` — version bumped to 5.9.2
458
+ - `CHANGELOG.md` — this entry
459
+
460
+ ### Carries forward from v5.9.1
461
+
462
+ Demo-first gate at kickoff, AskUserQuestion-only mode, single free-text question, hard hand-off to `/qualia-discuss`.
463
+
464
+ ---
465
+
466
+ ## [5.9.1] - 2026-05-11 (qualia-new — demo-first gate, AskUserQuestion everywhere)
467
+
468
+ **Targeted UX fix for the kickoff flow.** Observed a session where `/qualia-new` opened with a free-text "tell me what you want to make" prompt, then drifted into ad-hoc clarification questioning ("What does the SaaS DO?") before ever reaching the Demo vs Full gate. That's both spec violation and bad UX — the shape gate drives the entire downstream question set, so it must come first.
469
+
470
+ ### Changed — qualia-new step ordering
471
+
472
+ - **Step 1 is now the Demo/Full/Quick gate** via `AskUserQuestion`. It is the literal first interaction with the user — before "what are you building". Banner-only Step 0 stays; the next thing the user sees is the project-shape picker.
473
+ - **Step 3 is the only free-text question** in the kickoff flow: a single one-line pitch, accepted as-is even if broad ("a SaaS platform" is a valid answer). No clarification round, no ad-hoc questioning.
474
+ - **Step 4 hand-off to `/qualia-discuss` is now a hard rule.** "The next tool call after Step 3 must be `/qualia-discuss`. No free-form follow-up." Discovery depth is the discuss skill's job — not improvised.
475
+ - All downstream steps renumbered (old Step 2 → 5, etc.). Internal references updated.
476
+
477
+ ### Changed — qualia-new Rules section
478
+
479
+ - New Rule 1: Project type is the first question, period — even before "what are you building".
480
+ - New Rule 2: `AskUserQuestion` for every discrete-choice question; free-text only for Step 3.
481
+ - New Rule 3: No ad-hoc clarification questioning between Step 3 and `/qualia-discuss`.
482
+ - Demo non-negotiables (Rule 6) made explicit: 1 milestone, no mock data, real backend, real agent/platform functionality, DESIGN.md mandatory, focus on design + functionality. Speed never comes from mocking the backend.
483
+
484
+ ### Changed — qualia-discuss PROJECT MODE
485
+
486
+ - P1 (project-type detection): when invoked standalone, uses `AskUserQuestion` (interactive UI) — never a plain-text prompt. When invoked by `/qualia-new`, skip the gate entirely (already locked upstream).
487
+
488
+ ### Why
489
+
490
+ The screenshot evidence: a fresh `/qualia-new` session was free-form questioning the user before locking project shape. That violates the spec and produces shallow discovery — which then poisons every downstream phase. Reordering puts the shape gate first (where it always belonged) and tightens the rules so no future session can ad-hoc-clarify its way past the structured interview.
491
+
492
+ ---
493
+
494
+ ## [5.9.0] - 2026-05-11 (Deep-research fixes — surface drift, ERP retry queue, model tiering)
495
+
496
+ **The "fix what the deep-research audit found" release.** Three independent wins
497
+ shipped together: every dead command reference on user-facing surfaces is gone,
498
+ the ERP report upload now has a real retry mechanism (not just a lying message),
499
+ and four structured agents move from inherited Opus to Sonnet for a substantial
500
+ cost cut with no flow change.
501
+
502
+ ### Fixed — surface drift
503
+
504
+ - `rules/speed.md` no longer recommends `/qualia-quick` and `/qualia-task` (removed in v5.7). Now points at `/qualia-feature`.
505
+ - `templates/help.html` Quick Paths section no longer lists `/qualia-quick`, `/qualia-task`, `/qualia-design`. Replaced with `/qualia-feature` and `/qualia-polish`.
506
+ - `docs/onboarding.html` no longer lists `/qualia-quick`, `/qualia-task`, `/qualia-prd`, or `/qualia-polish-loop`. Updated to point at `/qualia-feature` and `/qualia-polish --loop`.
507
+ - `docs/playwright-loop-pilot-results.md` path references updated from `skills/qualia-polish-loop/` to `skills/qualia-polish/` (the v5.8.0 consolidation moved them; the historical pilot doc still pointed at the old location).
508
+ - New `tests/refs.test.sh` greps every active surface for backticked `/qualia-*` references and asserts each name maps to a shipped skill. Wired into `npm test`. Excludes historical surfaces (`docs/reviews/`, `docs/research/`, CHANGELOG) and migration-context prose ("Replaces /qualia-quick"). 10 references checked.
509
+
510
+ ### Added — ERP report retry queue
511
+
512
+ - New `bin/erp-retry.js` script. Persistent queue at `~/.claude/.erp-retry-queue.json`. Replaces the v5.8.0 "will appear in ERP after retry" message which was misleading — no retry mechanism existed before this release.
513
+ - `skills/qualia-report/SKILL.md` Step 6 enqueues failed uploads (all 3 attempts exhausted) into the queue with the full payload, idempotency key, and last error. Local commit still happens first; the queue is only the cloud-sync mechanism.
514
+ - `hooks/session-start.js` drains up to 5 queued items quietly on every Claude Code launch (2.5s per-item timeout, 8s total budget, fire-and-forget).
515
+ - New CLI: `qualia-framework erp-flush [show|clear]`. Drains verbosely, lists current queue, or clears with backup. Useful after rotating the API key or when the ERP comes back online.
516
+ - Permanent failures (401, 422) and 10-attempt exhaustion mark the item `give_up: true` — it stays in the queue for visibility but is no longer auto-retried until the user runs `erp-flush` after fixing the underlying issue.
517
+
518
+ ### Added — ERP payload contract completion
519
+
520
+ - `Idempotency-Key` header now sent with every report upload. Deterministic UUID-v5 hash of `(client_report_id, submitted_at, project)` so retries carry the same key. The ERP's documented 24-hour replay window protects against response-lost-mid-flight duplicates (`docs/erp-contract.md:42-49`).
521
+ - `session_duration_minutes` now computed from `tracking.json.session_started_at` to `submitted_at` and included in the payload. The ERP's example payload (`docs/erp-contract.md:93`) already expected this; the framework was silently omitting it.
522
+
523
+ ### Changed — verifier strictness
524
+
525
+ - `/qualia-verify` now grep-checks the verification report for `INSUFFICIENT EVIDENCE` lines after the verifier returns. Any occurrence downgrades the verdict to FAIL. Closes the deep-research audit's #1 false-pass vector — the verifier was instructed to emit INSUFFICIENT EVIDENCE on tool-budget exhaustion, but the orchestrator was treating those as silent PASS.
526
+ - `agents/verifier.md` tool budget changes from fixed 25 calls to `max(25, task_count * 5)`. A 3-task phase still gets 25 calls; a 10-task phase now gets 50. The fixed budget was tight on phases with many tasks.
527
+
528
+ ### Changed — model tiering (cost cut, zero flow risk)
529
+
530
+ - Four structured agents move to Sonnet via `model: sonnet` frontmatter:
531
+ - `agents/verifier.md` — deterministic grep + score against criteria
532
+ - `agents/plan-checker.md` — 11-rule structured checklist
533
+ - `agents/roadmapper.md` — template-driven milestone decomposition
534
+ - `agents/qa-browser.md` — mechanical browser interaction + finding capture
535
+ - `builder.md`, `planner.md`, `researcher.md`, `visual-evaluator.md` stay on inherited Opus where real architectural / vision / synthesis reasoning lives.
536
+ - `research-synthesizer.md` already used Haiku — unchanged.
537
+ - Net effect on a typical phase cycle (1 plan + 1-2 checker spawns + 1 verifier + 0-1 QA-browser): roughly 40% cost reduction without changing any prompts or skill flow.
538
+
539
+ ### Fixed — progress bar
540
+
541
+ - `bin/state.js:332` progress formula was `(phase - 1) / total_phases` which meant a completed 3-phase project showed 66% forever and a 1-phase project showed 0%. Now factors in `verified|polished|shipped|handed_off` statuses so the bar reaches 100% when the project is actually done.
542
+
543
+ ### Tests
544
+
545
+ - 472 assertions passing (up from 462). The 10 new assertions come from `tests/refs.test.sh`. All seven prior test suites continue to pass with the v5.9 changes.
546
+
547
+ ### Migration notes
548
+
549
+ - No breaking changes. Skills, agents, hooks, state machine, and CLI are all backward-compatible.
550
+ - Existing installs upgrade via `npx qualia-framework@latest install`. After upgrade, the next `/qualia-report` failure will enqueue the report; the queue drains on the next session-start. Old reports stranded by v5.8.0 are not auto-recovered (they were never queued), but re-running `/qualia-report` for those days will succeed if the ERP is reachable.
551
+ - Cost-curious users can confirm the model tiering by running `qualia-framework agents --failed` after a phase verification — the `model` field on each spawn record will show `sonnet` for the four tiered agents.
552
+
553
+ ## [5.8.0] - 2026-05-11 (Surface cleanup, polish-loop consolidation)
554
+
555
+ **The "stop shipping deprecated skills" release.** Removes the three skills
556
+ deprecated in v5.7.0 and consolidates `/qualia-polish-loop` into `/qualia-polish`
557
+ as a `--loop` flag. Skill count drops from 35 to 32.
558
+
559
+ ### Removed
560
+
561
+ - **`/qualia-quick`** removed. Was deprecated in v5.7.0; use `/qualia-feature`,
562
+ which auto-routes to the inline path for trivial work.
563
+ - **`/qualia-task`** removed. Was deprecated in v5.7.0; use `/qualia-feature`,
564
+ which auto-routes to a fresh builder spawn for 1-5 file work.
565
+ - **`/qualia-prd`** removed. Niche surface that overlapped `/qualia-discuss`
566
+ in PROJECT MODE (v5.6.0). Conversation-to-spec capture now lives in
567
+ `/qualia-discuss` for kickoff and in regular phase-context docs for
568
+ mid-project additions.
569
+
570
+ ### Changed
571
+
572
+ - **`/qualia-polish-loop` consolidated into `/qualia-polish --loop`**. The
573
+ autonomous visual-polish loop is now a flag on `/qualia-polish`, not a
574
+ separate skill. Scripts moved from `skills/qualia-polish-loop/scripts/`
575
+ to `skills/qualia-polish/scripts/`; fixtures and REFERENCE.md follow.
576
+ Visual evaluator agent description updated to point at the new surface.
577
+ The seven-scope table in `/qualia-polish` gains a "Loop" row.
578
+
579
+ ### Migration notes
580
+
581
+ - Most workflows update by find-and-replace: `/qualia-polish-loop` becomes
582
+ `/qualia-polish --loop`. Flag syntax (`--brief PATH`, `--max N`,
583
+ `--viewports`, `--ref PATH`, `--budget N`, `--reduced-motion`,
584
+ `--routes`) is preserved.
585
+ - `/qualia-quick`, `/qualia-task`, `/qualia-prd` are gone with no shim.
586
+ Projects still typing these will see a "command not found" path. The
587
+ v5.7.0 deprecation warnings were the migration window.
588
+ - README and guide.md reflect the new skill count (32) and v5.8 framing.
589
+
590
+ ### Tests
591
+
592
+ - `tests/bin.test.sh` updated: polish-loop path assertions now target
593
+ `skills/qualia-polish/`. Pass labels renamed. Added v5.8 cleanup
594
+ assertions confirming non-existence of `qualia-quick`, `qualia-task`,
595
+ `qualia-prd` and presence of `qualia-feature`.
596
+
597
+ ## [5.7.0] - 2026-05-11 (Feature consolidation, /qualia-feature)
598
+
599
+ **The "one command instead of three for everything between a typo and a phase"
600
+ release.** Replaces the `/qualia-quick` + `/qualia-task` split with a single
601
+ auto-scoped `/qualia-feature` command. The old commands stay functional for one
602
+ minor-version migration window so the ~40 active projects on prior versions
603
+ don't break overnight.
604
+
605
+ ### Added
606
+
607
+ - **`/qualia-feature` skill** (`skills/qualia-feature/SKILL.md`). Auto-scopes
608
+ the work into one of three buckets:
609
+ - **inline**: typo, comment edit, 1-line config change, single rename. Direct
610
+ work in the current Claude context, no subagent spawn.
611
+ - **spawn**: add a component, add a route, fix a non-trivial bug, refactor
612
+ one module. Fresh builder spawn with atomic commit and validation contract.
613
+ - **refuse**: 5+ files or multi-step workflow. Routes to `/qualia-plan`
614
+ instead of trying to fit a phase into a single-task slot.
615
+
616
+ Escape hatches: `--force-spawn` and `--force-inline` flags override the
617
+ classifier when it guesses wrong. The interactive gate also offers
618
+ "Force inline", "Force spawn", and "Route to /qualia-plan" options.
619
+
620
+ ### Changed
621
+
622
+ - **`/qualia-quick` and `/qualia-task` marked deprecated**
623
+ (`skills/qualia-quick/SKILL.md`, `skills/qualia-task/SKILL.md`). Both still
624
+ work as before for v5.7.x. They print a one-line deprecation warning and
625
+ end with "use /qualia-feature next time" instead of the plain end banner.
626
+ Removal scheduled for v5.8.0.
627
+
628
+ - **Primary-surface references updated**. The road skill, the install banner,
629
+ and the session-start tip now point at `/qualia-feature` as the canonical
630
+ single-feature path. Old references to `/qualia-quick` are gone from those
631
+ primary surfaces (the deprecated skills themselves still self-document).
632
+
633
+ ### Migration notes
634
+
635
+ - Existing projects don't break. `/qualia-quick` and `/qualia-task` still run
636
+ end-to-end with the same behavior they had in v5.6.0; the only change is the
637
+ deprecation warning on entry.
638
+ - The classifier is intentionally confident. When in doubt, it picks `spawn`
639
+ (one fewer surprise than guessing `inline` and contaminating the current
640
+ context). Use `--force-inline` for the over-scoped cases.
641
+ - v5.8.0 will remove `/qualia-quick` and `/qualia-task` entirely. Plan to
642
+ switch primary usage to `/qualia-feature` during the v5.7.x window.
643
+
644
+ ## [5.6.0] - 2026-05-11 (Demo vs Full Project, mandatory discovery)
645
+
646
+ **The "every project starts with the right kickoff shape" release.** Splits the
647
+ project workflow into two paths at the very first fork: demo (single
648
+ shippable milestone for sales conversations) versus full project (multi-milestone
649
+ arc to Handoff). Makes the kickoff interview mandatory and structured, not an
650
+ ad-hoc free-form chat. Surfaces a clean conversion path when a demo client signs.
651
+
652
+ ### Added
653
+
654
+ - **Step 0.6 Project Type Gate** in `skills/qualia-new/SKILL.md`. Asks Demo vs
655
+ Full Project as the first decision after the brownfield check. Every
656
+ downstream step (research scope, journey shape, milestone count) branches
657
+ on this answer. Demo design philosophy is enforced: real backend always,
658
+ DESIGN.md mandatory, slop-detect hard-block. Speed comes from skipping
659
+ multi-milestone planning, never from skipping design quality or mocking the
660
+ backend.
661
+
662
+ - **PROJECT MODE in `/qualia-discuss`** (`skills/qualia-discuss/SKILL.md`).
663
+ Two-mode skill now. With no args, runs the non-technical kickoff interview
664
+ (8 questions for demo, 14 for full project), captures answers verbatim to
665
+ `.planning/project-discovery.md`. With a phase number arg (e.g.
666
+ `/qualia-discuss 2`), runs the existing technical pre-plan grilling
667
+ unchanged. The PROJECT MODE rule "never go technical here" preserves the
668
+ client's own phrasing as input to PRODUCT.md voice and CONTEXT.md glossary.
669
+
670
+ - **Mandatory discovery in `/qualia-new` Step 1**. Replaces the free-form
671
+ deep-questioning loop with an inline invocation of `/qualia-discuss` in
672
+ PROJECT MODE. The discovery doc seeds PROJECT.md, PRODUCT.md, CONTEXT.md,
673
+ and (full projects only) JOURNEY.md milestone names.
674
+
675
+ - **`templates/project-discovery.md`**, the new discovery document template.
676
+ Demo path covers §1-§8 (pitch, users, "remember 24h later" sentence,
677
+ anti-references, brand voice, success criterion, hard constraints, out of
678
+ scope). Full project adds §9-§14 (milestone arc, compliance, integrations,
679
+ content ownership, post-handoff team, budget/timeline shape).
680
+
681
+ - **Demo-Extension Branch in `/qualia-milestone`** (`skills/qualia-milestone/SKILL.md`).
682
+ When a demo project closes its only milestone, asks "did the client sign?".
683
+ On yes: invokes `/qualia-discuss` for the §9-§14 top-up, then spawns the
684
+ roadmapper in `extend-demo-to-full` mode to add M2..M{N-1} plus Handoff,
685
+ with M1 untouched because it shipped. On no: closes the demo as a shipped
686
+ artifact and routes to `/qualia-report`.
687
+
688
+ - **`<scope>quick</scope>` in researcher agents** (`agents/researcher.md`,
689
+ `agents/research-synthesizer.md`). Demo projects pass `quick` scope; each
690
+ researcher gets a 3-call budget instead of 8. The synthesizer produces a
691
+ single-milestone suggestion (no Handoff, no multi-milestone arc). Total
692
+ research time drops roughly 3x with no loss of correctness on the demo
693
+ path. The depth was wasted when there's only one milestone to ship.
694
+
695
+ - **`project_type` frontmatter** in `templates/project.md`. Stored as
696
+ `project_type: demo | full`. The milestone-close branch reads it to decide
697
+ whether to fire the demo-extension question.
698
+
699
+ ### Changed
700
+
701
+ - **`/qualia-discuss` description and routing.** Description now documents
702
+ both modes. The skill picks mode based on whether an arg is passed (no
703
+ arg = PROJECT MODE, numeric arg = PHASE MODE). All existing PHASE MODE
704
+ behavior is preserved unchanged.
705
+
706
+ - **`/qualia-new` Step 8 research scope** now branches on `PROJECT_TYPE`.
707
+ Demo projects pass `<scope>quick</scope>` to all 4 researchers and the
708
+ synthesizer; full projects use the standard 8-call budget per researcher.
709
+
710
+ - **`/qualia-new` Step 10 roadmapper output** now branches on `PROJECT_TYPE`.
711
+ Demo: 1 milestone (the demo itself, 2-4 phases), no Handoff, fully detailed.
712
+ Full: standard 2-5 milestone arc ending in Handoff.
713
+
714
+ ### Migration notes
715
+
716
+ - Projects on v5.5 or earlier do not have `project_type` in their PROJECT.md.
717
+ The milestone-close branch treats missing `project_type` as `full` and
718
+ skips the demo-extension question. Backward-compatible.
719
+ - Existing in-flight projects don't need to re-run discovery. The mandatory
720
+ interview only fires at `/qualia-new` kickoff for net-new projects.
721
+ - `/qualia-discuss N` (phase-mode usage) is unchanged. Existing scripts and
722
+ team habits keep working.
723
+
724
+ ## [5.5.0] - 2026-05-09 (Plan-discipline pass)
725
+
726
+ **The "stop the LLM from quietly simplifying the spec" release.** Pre-execution
727
+ discipline upgrades that catch the most common failure modes (silent scope
728
+ reduction, missing requirement coverage, decision drift) before the builder
729
+ spawns and burns context. Synthesised from a deep research pass across six
730
+ external coding-agent frameworks; only the patterns with clear leverage and
731
+ no ceremony tax were inherited.
732
+
733
+ ### Added
734
+
735
+ - **Scope-Reduction Prohibition** in `agents/planner.md` and `agents/builder.md`.
736
+ Banned phrases (`v1`, `simplified version`, `hardcoded for now`, `will be
737
+ wired later`, `stub`, `placeholder`, etc.) plus three legitimate split
738
+ reasons (context cost over 50%, missing info, dependency conflict). LLMs
739
+ systematically simplify specs; this is a zero-token-cost guardrail in
740
+ steady state that targets the #1 quality failure mode.
741
+
742
+ - **Decision Coverage Audit** in `agents/planner.md`. Planner verifies that
743
+ every `D-NN` row from `.planning/phase-{N}-context.md` is covered by a task
744
+ before returning the plan. Closes the discuss → plan → verify → ship
745
+ traceability loop.
746
+
747
+ - **Auto-heal loop in builder Self-Verify** (`agents/builder.md`). On `tsc`
748
+ or `slop-detect` failure, fix and retry up to 2x before BLOCKED. Moves
749
+ correctness checks from post-hoc verifier to in-builder self-heal,
750
+ saving a verifier round per failure.
751
+
752
+ - **Plan-checker Rule 9: Decision Coverage** (`agents/plan-checker.md`).
753
+ Reads `.planning/phase-{N}-context.md`; BLOCKS if any `D-NN` is unclaimed
754
+ by the plan, or if a `Deferred Ideas` row is being implemented.
755
+
756
+ - **Plan-checker Rule 10: Scope Reduction Detection**. Greps the plan for
757
+ banned phrases; BLOCKS with a quoted citation. Exception is the project's
758
+ own product versioning (e.g. `migrate to API v2`).
759
+
760
+ - **Plan-checker Rule 11: Requirement Coverage**. Reads ROADMAP.md for
761
+ per-phase REQ-IDs; BLOCKS if any REQ-ID listed for the current phase is
762
+ not referenced by any task.
763
+
764
+ - **`findScopeReductionPhrases()` in `bin/plan-contract.js`**. The same scan
765
+ runs on the JSON contract path (`task.action`, `task.acceptance_criteria`)
766
+ so both paths catch the same failure mode. Exported for reuse.
767
+
768
+ ### Changed
769
+
770
+ - **`/qualia-discuss` output format** (`skills/qualia-discuss/SKILL.md`).
771
+ Locked Decisions now carry stable `D-NN` IDs in a four-column table
772
+ (`ID | Decision | Rationale | Source`). Downstream agents reference these
773
+ IDs in commit messages and task Why fields for traceability.
774
+
775
+ - **`templates/phase-context.md`** gains an `ID` column on the Locked
776
+ Decisions table.
777
+
778
+ ### Removed
779
+
780
+ - **9 build-time engineering archive docs** (~140KB) referenced only from
781
+ CHANGELOG: `install-redesign-builder-prompt.md`, `install-redesign-pilot.md`,
782
+ `instruction-budget-audit.md`, `journey-demo.html`, the four
783
+ `playwright-loop-*` engineering notes (the active `pilot-results.md`
784
+ stays), `polish-loop-supervised-run.md`, and the matching archived
785
+ session report.
786
+
787
+ ### Tests
788
+
789
+ - New regression: `tests/lib.test.sh` covers scope-reduction detection on
790
+ both `task.action` and `task.acceptance_criteria` (16 passing, was 15).
791
+ - Total suite: **491 passing across 7 suites**, no regressions.
792
+
793
+ ### Notes
794
+
795
+ - Plan-checker now covers 6 of 7 industry-standard goal-backward dimensions.
796
+ Per-task context budget enforcement was intentionally skipped (heuristic,
797
+ false-positive prone, low signal); the existing Quality Degradation Curve
798
+ in `rules/grounding.md` covers the prompt-side hint.
799
+ - No public API changes. Skill and agent prompt deltas are additive; existing
800
+ plans without `D-NN` IDs or REQ-IDs in ROADMAP.md continue to pass (Rules
801
+ 9 and 11 are conditional on those artifacts existing).
802
+
803
+ ## [5.4.0] — 2026-05-07 (Token-discipline + grounding pass)
804
+
805
+ **The "less tokens, no quality loss" release.** Driven by a re-study of
806
+ Matt Pocock's *Skills and Strategies for Real Engineering*, Patrick
807
+ Debois's *Context is the New Code*, Karpathy on Software 3.0, and Mario
808
+ Zechner on agentic search. Eight PRs landed:
809
+
810
+ ### Added
811
+
812
+ - **`rules/architecture.md`** — deep modules (Ousterhout), locality
813
+ over DRY, adapters at seams, layered service boundaries, interface
814
+ stability, test-the-seam-not-the-function. Auto-loaded only on
815
+ architectural-judgment tasks.
816
+
817
+ - **`rules/speed.md`** — CLI-first / MCP tier-list rule. Default to
818
+ CLI; reach for MCP only when the CLI doesn't expose the operation
819
+ or there's no CLI alternative. Per-MCP guidance for the 10+ MCP
820
+ servers we use. The `/supabase` skill (replacing 32 supabase MCP
821
+ tools) is the canonical pattern.
822
+
823
+ - **`docs/instruction-budget-audit.md`** — anchors the discipline. The
824
+ ~22 KB-per-session leak from auto-loaded design rules is documented
825
+ with cost breakdown and a relocation plan.
826
+
827
+ - **`tests/skills.test.sh`** (168 assertions) — smoke tests every
828
+ `skills/*/SKILL.md`: frontmatter parses, name matches folder,
829
+ description ≥ 50 chars, has trigger phrases (or `disable-model-
830
+ invocation`), body has h1 + section. **Plus a cache-aware spawn
831
+ audit:** every spawn to a custom `qualia-*` subagent must anchor
832
+ the prompt with `@~/.claude/agents/{name}.md` so Anthropic's prompt
833
+ cache reuses the prefix (documented 81–90% cost reduction).
834
+
835
+ - **`tests/slop-detect.test.sh`** (9 assertions) — behavioral tests
836
+ for the AI-tells gatekeeper. Verifies em-dash detection (HIGH),
837
+ banned-font detection (CRITICAL exits 1), purple-blue gradient
838
+ detection (CRITICAL), JSON output, missing-path graceful exit.
839
+
840
+ - **NotebookLM-first research path** in `agents/researcher.md` and
841
+ `/qualia-research`. Mandatory pre-flight: query `mcp__notebooklm-mcp__
842
+ cross_notebook_query` and `~/qualia-memory` (via knowledge.js +
843
+ qualia-recall) BEFORE any external Context7/WebFetch/WebSearch
844
+ call. Local pre-flight is FREE (not counted against the 8-call
845
+ external budget). Skip web round when local sources cover ≥ 80% at
846
+ confidence ≥ MEDIUM. Estimated 60–80% reduction in research-phase
847
+ tokens for `/qualia-new` and `/qualia-research` — the team has 21
848
+ curated NotebookLM notebooks covering most domains we ship in.
849
+
850
+ - **Citation-enforcement preambles** in `agents/builder.md`,
851
+ `agents/verifier.md`, `agents/plan-checker.md`, `agents/qa-browser.md`,
852
+ `agents/researcher.md`, `agents/research-synthesizer.md`,
853
+ `agents/roadmapper.md`. Every claim cites `file:line — "quoted"`,
854
+ no hedging language (banned: "seems", "appears", "probably",
855
+ "might", "likely", "possibly"), `INSUFFICIENT EVIDENCE` is the
856
+ correct answer when tool-budget is exhausted. Closes the *Never
857
+ Trust an LLM* gap surfaced by Pocock and Karpathy's *jagged
858
+ intelligence* framing.
859
+
860
+ - **Trigger phrases** added to three previously-vague skill
861
+ descriptions: `qualia-map` ("map this codebase", "brownfield
862
+ setup"), `qualia-milestone` ("close milestone", "next milestone"),
863
+ `qualia-research` ("best practices for X", "compare libraries").
864
+ Skills now fire on natural-language requests, not just slash command.
865
+
866
+ ### Changed
867
+
868
+ - **Design substrate relocated** from `~/.claude/rules/` (auto-loaded
869
+ by Claude Code's harness on every session) to `~/.claude/qualia-design/`
870
+ (load-on-demand via explicit `Read`). Six files affected:
871
+ `design-laws.md`, `design-brand.md`, `design-product.md`,
872
+ `design-rubric.md`, `design-reference.md`, `frontend.md`. **~22 KB
873
+ of instruction budget recovered per session** for non-frontend work.
874
+ Skills/agents that need the substrate `Read` it explicitly when they
875
+ need it (already the pattern in `agents/builder.md` and
876
+ `agents/verifier.md`). `bin/install.js` migrates legacy paths
877
+ on next install.
878
+
879
+ - **`state.js cmdTransition`** split from a 195-line monolith into 7
880
+ named helpers (`applyNoteOrActivity`, `applyPlannedTransition`,
881
+ `applyBuiltTransition`, `applyVerifiedTransition`,
882
+ `applyPolishedTransition`, `applyShippedTransition`,
883
+ `commitTransitionAtomic`). Orchestrator now reads top-to-bottom in
884
+ 84 lines. Behavior preserved exactly — verified by all 59
885
+ state.test.sh assertions.
886
+
887
+ - **Skill description boundaries sharpened** for the four
888
+ picker-confusable pairs: `qualia-quick` vs `qualia-task` ("NO
889
+ spawn" vs "FRESH builder spawn"), `qualia-road` vs `qualia-help`
890
+ ("TERMINAL" vs "BROWSER HTML"). Picker now disambiguates correctly.
891
+
892
+ - **`rules/infrastructure.md`** Supabase guidance reconciled with the
893
+ new CLI-first rule. Was: "MCP server is available for direct
894
+ database operations". Now: "prefer `npx supabase` over MCP; reach
895
+ for MCP only when CLI can't".
896
+
897
+ - **`README.md`** — three updates:
898
+ - `## Don't run Claude's /init` warning at the top, directing users
899
+ to `/qualia-new` (greenfield) or `/qualia-map` (brownfield) per
900
+ Pocock's *Never run /init* — built-in `/init` generates bloated
901
+ docs that rot and consume instruction budget.
902
+ - `## What's Inside` — split rules section into 6 always-loaded
903
+ rules (`rules/`) + 6 lazy-loaded design files (`qualia-design/`).
904
+ - Skill listings now include `/qualia-flush`, `/qualia-postmortem`,
905
+ `/zoho-workflow` (previously installed but undocumented).
906
+
907
+ - **`SESSION_REPORT.md` + `V4_REVIEW.md`** moved to `docs/archive/`.
908
+ Historical artifacts; git history preserves them.
909
+
910
+ ### Test surface
911
+
912
+ | Group | Assertions |
913
+ |---|---:|
914
+ | statusline | 14 |
915
+ | state | 59 |
916
+ | hooks | 66 |
917
+ | bin | 146 |
918
+ | lib | 15 |
919
+ | skills (new) | 178 |
920
+ | slop-detect (new) | 9 |
921
+ | **Total** | **487** |
922
+
923
+ ### Source attribution (research basis)
924
+
925
+ - Matt Pocock — *Skills and Strategies for Real Engineering with
926
+ Claude Code* (13-source NotebookLM): citation discipline,
927
+ instruction-budget rule, deep modules, never-run-/init, never-trust-
928
+ an-LLM.
929
+ - Patrick Debois — *Context is the New Code*: CDLC, eval pillar.
930
+ - Andrej Karpathy — *Software 3.0 / Vibe Coding to Agentic
931
+ Engineering*: jagged intelligence, verifiable intelligence.
932
+ - Mario Zechner — *Tokens*: agentic search, context rot.
933
+ - Plus 12 sources in *Context and Tools: Mastering the AI Engineering
934
+ Lifecycle* on RAG, agent harnesses, voice agents, CLI vs MCP.
935
+
936
+ ## [5.3.0] — 2026-05-05 (Matt Pocock gaps)
937
+
938
+ **The "absorb the missing patterns" release.** A re-study of Matt
939
+ Pocock's published skills repo and Claude-Code-for-Real-Engineers
940
+ content surfaced three patterns Qualia hadn't yet absorbed: the
941
+ PRD-from-conversation flow, the parallel-interface-alternatives pattern
942
+ in deep-module refactoring, and the instruction-budget-to-hook
943
+ generator. v5.3 ships all three. Most of Matt's other patterns
944
+ (CONTEXT.md, ADRs, slim CLAUDE.md, /qualia-discuss = grill, /qualia-test
945
+ --tdd, /qualia-issues = to-issues, /qualia-zoom = zoom-out, /qualia-debug
946
+ = diagnose, /qualia-optimize --deepen ≈ improve-codebase-architecture)
947
+ were already in v5.x.
948
+
949
+ ### Added
950
+
951
+ - **`/qualia-prd`** — synthesize the current conversation into a
952
+ durable PRD at `.planning/PRD-{slug}.md`. Optionally opens a parent
953
+ GitHub issue. No interview — just synthesis. Pairs with
954
+ `/qualia-issues` to break the PRD into vertical-slice issues.
955
+ Distinct from `/qualia-plan` (phase-operational) — `/qualia-prd` is
956
+ feature-durable. Distinct from `/qualia-new` (one-shot project
957
+ setup) — `/qualia-prd` runs every time a new feature needs a spec.
958
+ Forked subagent for synthesis: full conversation context flows into
959
+ the fork, only `{path, summary}` flows back to the parent session.
960
+ Token discipline preserved.
961
+
962
+ - **`/qualia-hook-gen`** — convert a CLAUDE.md or rules/*.md
963
+ instruction into a deterministic Claude Code `pre-tool-use` hook.
964
+ Three patterns: block (exit 2 with message), rewrite (block with
965
+ alternative), warn (exit 0 with stderr message). Generates
966
+ `hooks/block-{name}.js` (pure Node, cross-platform — no `.sh`) and
967
+ the `settings.json` patch. Tests the hook before committing. After
968
+ install, surfaces the now-redundant CLAUDE.md line so the user can
969
+ trim instruction budget. Refuses non-deterministic rules
970
+ (stylistic / judgment-based) — recommends a skill or ESLint rule
971
+ instead. Closes the gap between Matt's "instruction-budget
972
+ discipline" advocacy and actually shrinking real-project CLAUDE.md
973
+ files.
974
+
975
+ - **Step 5b: Parallel Interface Design (Wave 3)** in
976
+ `/qualia-optimize --deepen` — after the strategist returns
977
+ deepening candidates and the user picks one, spawn 3 fan-out agents
978
+ IN THE SAME RESPONSE TURN, each producing a *radically different*
979
+ interface design (variant 1 = functional/data-oriented, variant 2 =
980
+ OOP/encapsulated, variant 3 = event-driven/message-based). Present
981
+ the 3 alternatives in a comparison table; user picks 1, 2, 3, or
982
+ hybrid. Then a synthesizer writes the Refactor RFC to
983
+ `.planning/REFACTOR-{slug}.md` honoring the user's pick. From
984
+ Matt's improve-codebase-architecture skill — produces dramatically
985
+ better refactor RFCs than a single-pass proposal. ~15K tokens per
986
+ candidate (cached prefix shared across the 3 spawns).
987
+
988
+ - **9 new tests** (bin.test.sh #135-143): qualia-prd installs,
989
+ describes synthesis flow, documents fork-based token discipline;
990
+ qualia-hook-gen installs, documents block/rewrite/warn patterns,
991
+ mandates pure-Node hooks; qualia-optimize Step 5b parallel-interface
992
+ is documented; qualia-optimize REFERENCE.md has the spawn template;
993
+ package.json version assertion accepts 5.3.x.
994
+
995
+ ### Changed
996
+
997
+ - **`skills/qualia-optimize/SKILL.md`** — adds "Step 5b: Wave 3 --
998
+ Parallel Interface Design" section. Triggers in `--deepen` mode
999
+ only after candidate selection.
1000
+ - **`skills/qualia-optimize/REFERENCE.md`** — adds the verbatim
1001
+ "Parallel interface design prompt" with per-variant lens
1002
+ assignments and output contract (5 numbered sections per variant).
1003
+ - `package.json` version bumped to 5.3.0.
1004
+
1005
+ ### Honest carryover (still deferred)
1006
+
1007
+ - **CLAUDE.md slimming to 1 line** (Matt's "you are on WSL on
1008
+ Windows" pattern) — Qualia's CLAUDE.md is multi-tenant team-aware
1009
+ with role substitution. Can't go to 1 line without losing role
1010
+ injection. Wait until install.js can inline role into a session
1011
+ prompt instead of a global file. v5.4+ candidate.
1012
+ - **`user-invocable: false` frontmatter convention** — small
1013
+ marking that says "this skill is invoked by other skills, not
1014
+ users." Low impact, fold into v5.3.x patch.
1015
+ - **Graybox-locking pattern in /qualia-test** — when refactoring
1016
+ a deep module, lock the interface with comprehensive tests.
1017
+ Educational extension, fold into /qualia-test's TDD docs in
1018
+ v5.3.x.
1019
+ - **"What-to-do / supporting-info" structured sections** in
1020
+ SKILL.md — Matt's recent authoring convention. Fold into
1021
+ `/qualia-skill-new` template in v5.3.x.
1022
+
1023
+ ### Why these changes
1024
+
1025
+ The Matt-Pocock NotebookLM study surfaced exactly what we'd missed.
1026
+ v5.0 absorbed the philosophy (instruction-budget discipline, alignment
1027
+ substrate, deep modules); v5.1 shipped the visual-polish loop; v5.2
1028
+ hardened it. v5.3 closes the remaining patterns gap so Qualia is at
1029
+ parity with Matt's published toolkit while still carrying its own
1030
+ flagship contributions (visual-polish loop, multi-target install,
1031
+ state-machine project lifecycle, ERP integration, the 8-dimension
1032
+ design rubric, the Karpathy raw-to-wiki memory layer).
1033
+
1034
+ Tests: 291 (v5.2) → **300 (v5.3)**. All passing. slop-detect clean
1035
+ on all v5.3 changes.
1036
+
1037
+ ## [5.2.0] — 2026-05-05 (Polish-loop reliability)
1038
+
1039
+ **The "close the v5.1 deferrals" release.** v5.1 shipped the autonomous
1040
+ visual-polish loop (`/qualia-polish-loop`) with three named deferrals in
1041
+ the CHANGELOG: the `prefers-reduced-motion` forced-capture flag, multi-
1042
+ route sweeps, and the first real-project supervised run. v5.2 closes all
1043
+ three. The loop is now production-ready against multi-page sites and
1044
+ honors user a11y intent at capture time.
1045
+
1046
+ ### Added
1047
+
1048
+ - **`--reduced-motion`** flag on `playwright-capture.mjs` and
1049
+ `loop.mjs init`. Forces `prefers-reduced-motion: reduce` in the
1050
+ captured page. Implemented for both backends — Playwright's
1051
+ `newContext({ reducedMotion: 'reduce' })` and Chromium's
1052
+ `--force-prefers-reduced-motion` CLI flag. State records
1053
+ `state.reduced_motion: true` so the vision evaluator knows to score
1054
+ motion on CSS-declaration quality only (not penalize "no animation
1055
+ visible"). Closes v5.1 §5g adversarial deferral.
1056
+ - **`--routes URL1,URL2,URL3`** flag on `loop.mjs init`. Multi-route
1057
+ mode. State stores both `state.url` (first URL, for backward compat
1058
+ with single-route SKILL.md drivers) and `state.urls` (full list).
1059
+ Orchestrator drives capture+eval per URL each iteration; aggregate
1060
+ scores are min across URLs and viewports. The kill-switch fingerprint
1061
+ set is shared across all URLs — a regression on any route halts the
1062
+ loop. Closes v5.1 §"Multi-route sweeps" deferral.
1063
+ - **`docs/polish-loop-supervised-run.md`** — write-up of the first
1064
+ supervised end-to-end run. Captures real wall-clock time, token
1065
+ estimates, both flag combinations exercised, what worked, what
1066
+ surprised. Removes the "first real-project supervised run not done"
1067
+ caveat from v5.1's CHANGELOG.
1068
+ - **6 new tests** (tests #129-134 in `bin.test.sh`) covering: `--routes`
1069
+ multi-route init, `state.url` first-entry backward compat,
1070
+ `--reduced-motion` flag recording, capture --help documents
1071
+ `--reduced-motion`, init rejects missing `--url`/`--routes`, report
1072
+ renders multi-route header.
1073
+
1074
+ ### Changed
1075
+
1076
+ - **`scripts/loop.mjs report`** — when `state.urls.length > 1`, the
1077
+ header renders `**URLs (N):** url1, url2, ...` instead of single
1078
+ URL. Reduced-motion mode renders an extra `**Reduced motion:**
1079
+ forced` row.
1080
+ - **`scripts/loop.mjs init`** — accepts either `--url` or `--routes`
1081
+ (one is required, `--routes` wins if both given). Records
1082
+ `state.reduced_motion` for downstream capture invocations.
1083
+ - `package.json` version bumped to 5.2.0.
1084
+
1085
+ ### Honest caveats
1086
+
1087
+ - Multi-route mode requires the SKILL.md driver to loop the
1088
+ capture+eval per URL each iteration. The state-machine primitives
1089
+ (`init`, `record`, `commit-fix`, `report`) are URL-agnostic, but the
1090
+ orchestrator (Claude session) has to invoke them N times per
1091
+ iteration where N is `state.urls.length`. The SKILL.md guidance for
1092
+ multi-route is documented in `loop.mjs --help` and the v5.2
1093
+ supervised run write-up.
1094
+ - `--reduced-motion` on the chromium-binary backend uses Chrome's
1095
+ `--force-prefers-reduced-motion` flag which has been stable since
1096
+ Chrome 87 (2020). Older browsers may ignore it; Playwright's
1097
+ `reducedMotion: 'reduce'` is more reliable when both backends are
1098
+ available.
1099
+ - Pixel-similarity reference-image comparison still deferred to v5.3.
1100
+ The `--ref` flag remains rubric-anchored (the evaluator looks at
1101
+ both screenshots and scores against the rubric). True
1102
+ structural-similarity comparison needs an embedding step that's
1103
+ outside the scope of this release.
1104
+
1105
+ ### Tests
1106
+
1107
+ 274 (v5.0) → 285 (v5.1) → **291 (v5.2)**. All passing. slop-detect
1108
+ clean (0 critical) on all v5.2 changes.
1109
+
1110
+ ## [5.1.0] — 2026-05-03 (Multi-target install + live-progress redesign)
1111
+
1112
+ **The "first impression matters" release.** Every Qualia user — Fawzi,
1113
+ Hasan, Moayad, Rama, Sally, future hires — meets the framework first
1114
+ through `npx qualia-framework install`. v5.0's installer was functional
1115
+ but minimal: silent for 5 seconds, then a wall of green checkmarks. v5.1
1116
+ turns the install into a polished, intentional document: live progress on
1117
+ every operation, per-section timing, and a target-selection prompt that
1118
+ acknowledges Qualia ships AGENTS.md (the open standard adopted by Codex,
1119
+ Cursor, Continue, Aider, Devin) and meets users wherever they edit.
1120
+
1121
+ The root cause this addresses: silence reads as a hung process. When the
1122
+ installer copies 33 skills + 12 hooks + 24 templates and prints nothing
1123
+ between section headers and the final summary, the user wonders if their
1124
+ laptop froze. Live updates tell them the framework is alive and working
1125
+ through the list. Visual feedback is trust.
1126
+
1127
+ ### Added
1128
+
1129
+ - **Multi-target install** — after the team-code prompt, the installer
1130
+ asks: install to Claude Code (`~/.claude/`), OpenAI Codex
1131
+ (`~/.codex/`), or both. Default is `1` (Claude Code only) so legacy
1132
+ scripts keep working untouched. `2` writes only `~/.codex/AGENTS.md`
1133
+ with role substitution; `3` does both. Codex CLI is detected via
1134
+ `which codex`; if absent, the installer warns and writes the file
1135
+ anyway so the user is set up for when they install Codex.
1136
+ - **Live-progress lifecycle** — every meaningful copy operation prints a
1137
+ `⏳ doing...` line that overwrites in place to `✓ done` when the op
1138
+ completes. Long-running ops (settings.json merge, recursive template
1139
+ copy) show a Braille-pattern spinner. Sub-50ms ops skip the "doing"
1140
+ state and go straight to `✓` to avoid noise.
1141
+ - **Per-section summaries** — each install phase (Skills, Agents, Rules,
1142
+ Hooks, Templates, etc.) closes with a `└─ N items · Xs` line showing
1143
+ the count and elapsed time. The final summary card adds rows for
1144
+ **Targets** (Claude Code · Codex · Both) and **Time** (total install
1145
+ duration), plus a contextual "first command to try" hint that
1146
+ recommends `/qualia` if a `.planning/` folder exists in the current
1147
+ directory and `/qualia-new` otherwise.
1148
+ - **`bin/qualia-ui.js` extended** — exports `step()`, `spinner()`,
1149
+ `progress()`, `box()`, `kv()`, `divider()`, `section()`,
1150
+ `sectionClose()` for require-side consumption from `install.js` and
1151
+ any future CLI work. The existing CLI dispatch (`node qualia-ui.js
1152
+ banner` etc.) is preserved — gated behind `require.main === module`
1153
+ so importing the file doesn't trigger argv parsing.
1154
+ - **`docs/install-redesign-pilot.md`** — captured output of all three
1155
+ install scenarios (Claude only, Codex only, Both), timing
1156
+ measurements, and the TTY-degradation verification.
1157
+
1158
+ ### Changed
1159
+
1160
+ - **`bin/install.js`** — same semantic install logic as v5.0 (skills,
1161
+ agents, hooks, rules, templates, knowledge layer, ERP config,
1162
+ settings.json merge with backup) wrapped in the new live-progress
1163
+ primitives + section timing. Backward compatible: a piped install
1164
+ with only the team code (`echo "QS-FAWZI-11" | npx qualia-framework
1165
+ install`) still completes correctly and defaults to Claude only.
1166
+ - **`bin/qualia-ui.js`** — module is now require-able (gated CLI
1167
+ dispatch) and exports the new primitives alongside an OKLCH-tinted
1168
+ color palette. Color discipline preserved: teal/green/dim/white from
1169
+ v5.0; errors stay red, warns stay yellow.
1170
+ - **`package.json`** — `files` array adds `AGENTS.md` so the Codex
1171
+ install can read the framework copy at install time (it was already
1172
+ shipped in source but excluded from the published tarball).
1173
+ - **`tests/bin.test.sh`** — adds 11 tests for v5.1: target=1/2/3 paths,
1174
+ legacy single-line backward compat, Codex AGENTS.md backup before
1175
+ overwrite, no redundant backup on identical re-install, non-TTY log
1176
+ cleanliness (no orphan `\r` / hide-cursor / clear-line escapes),
1177
+ summary card shows Targets+Time, qualia-ui exports check, qualia-ui
1178
+ CLI dispatch still works, package.json version bump assertion.
1179
+
1180
+ ### Honest caveats
1181
+
1182
+ - **Codex install scope in v5.1: AGENTS.md only (superseded by v6.2.7).** Codex's runtime did not
1183
+ then consume Claude-style skills/hooks/agents on disk in a way
1184
+ the framework can map 1:1 (Codex agents use a `.toml` format and a
1185
+ different hook schema). AGENTS.md carries the rules — the open
1186
+ standard Codex / Cursor / Continue / Aider / Devin all read — and
1187
+ commands continue to route through Claude Code. If Codex grows
1188
+ skill/hook support that lines up, the framework will extend the
1189
+ Codex install path here without breaking AGENTS.md compat.
1190
+ - **Spinner cosmetics on `cmd.exe`.** Modern Windows Terminal renders
1191
+ Braille frames fine. Older `cmd.exe` may render them as boxes; the
1192
+ install still completes correctly. The non-TTY (piped) path skips
1193
+ spinners entirely and prints plain `✓` lines.
1194
+ - **Total install time shown in seconds.** On modern hardware the entire
1195
+ install completes in ~100–300ms, so the Time row often shows `0.1s`
1196
+ or `0.2s`. Not a bug — the framework is just fast.
1197
+ - **Two readline races avoided.** v5.1's first implementation had a
1198
+ subtle bug: between `await askCode()` and `await askTarget()`, EOF
1199
+ on piped stdin emitted `'close'` before the second `question()`
1200
+ could attach a line listener — `target` always defaulted to `1`
1201
+ even when the user piped `CODE\n2\n`. Fixed by pre-buffering all
1202
+ stdin lines synchronously when the input is non-TTY. Documented here
1203
+ so future contributors don't reinvent the bug.
1204
+
1205
+ ### Why these changes
1206
+
1207
+ A boring install signals a boring framework. v5.0 was functional; v5.1
1208
+ is the version Fawzi can demo to a client and have them say "this feels
1209
+ like a product." The Codex addition is strategic: AGENTS.md adoption
1210
+ across Codex / Cursor / Continue / Aider / Devin means Qualia rules can
1211
+ follow the user across vendors without forking the framework. v5.1 makes
1212
+ that explicit, opt-in, and one keystroke away (`2` or `3`).
1213
+
1214
+ Hooks/skills/agents stay Claude-only because Claude Code is where the
1215
+ framework's automation lives. AGENTS.md is the rule layer; the rest is
1216
+ the engine.
1217
+
1218
+
1219
+
1220
+ ## [5.0.0] — 2026-05-03 (Visual-Polish Loop addendum)
1221
+
1222
+ **The "see your own work" addition** to the v5.0.0 release.
1223
+ Adds `/qualia-polish-loop`, the autonomous visual-polish loop that
1224
+ screenshots a live URL at three viewports, scores against the
1225
+ 8-dimension `rules/design-rubric.md` using a vision-anchored evaluator,
1226
+ fixes the top issues, and loops until every dimension scores 3 or the
1227
+ kill-switch trips. Closes the design-iteration churn friction documented
1228
+ in Fawzi's `/insights` data (the #1 strategic workflow opportunity from
1229
+ v5.0's hardening audit).
1230
+
1231
+ The root cause this addresses: the framework's design QA was text-only.
1232
+ `slop-detect` grep-scans CSS for known anti-patterns. The verifier
1233
+ scores design by reading TSX/CSS. Both miss visual failures that only
1234
+ show on a rendered page — hero-video framing on mobile, breakpoint
1235
+ collapse, spacing rhythm, motion presence. `/qualia-polish-loop` is the
1236
+ first Qualia skill that actually looks at what the browser draws.
1237
+
1238
+ ### Added
1239
+
1240
+ - **`/qualia-polish-loop`** — new flagship skill. CLI:
1241
+ `/qualia-polish-loop {url} [--brief PATH] [--max 8] [--viewports 375,768,1440] [--budget 100000]`.
1242
+ Pre-flight gates check substrate, brief, browser backend, URL
1243
+ reachability, working-tree cleanliness, and token budget before any
1244
+ capture runs. Each iteration: capture (3 viewports) → spawn the
1245
+ vision evaluator → record the verdict → spawn 1-3 fix-builders in
1246
+ parallel → commit each fix with `qpl-{N}:` prefix → loop. Stops on
1247
+ SUCCESS (all 8 dims 3, no critical issues), KILL on regression
1248
+ (same issue fingerprint 3 consecutive iterations), KILL on budget,
1249
+ KILL on max iterations.
1250
+ - **`agents/visual-evaluator.md`** — new agent role. Vision-anchored,
1251
+ rubric-inlined, JSON-output-contract. Defaults to score 3
1252
+ (acceptable); only deviates with cited evidence. Aggregate score is
1253
+ the MINIMUM across viewports per dimension — a layout that's elegant
1254
+ on desktop but breaks at 375px is a fail. Trust-boundary block
1255
+ refuses prompt injection from inlined project files.
1256
+ - **`skills/qualia-polish-loop/scripts/playwright-capture.mjs`** —
1257
+ capture helper. Auto-selects backend: `import('playwright')` first,
1258
+ then cached `~/.cache/ms-playwright/chromium-*` binary, then
1259
+ `google-chrome` / `chromium` on PATH. No npm dependency required if
1260
+ any Chrome-family binary is already on disk.
1261
+ - **`skills/qualia-polish-loop/scripts/loop.mjs`** — deterministic
1262
+ state-machine orchestrator. Subcommands: `init`, `record`, `status`,
1263
+ `commit-fix`, `report`. State persists in JSON outside the LLM
1264
+ context (iteration counter, fingerprints, fixes, verdict). The
1265
+ `commit-fix` subcommand runs `slop-detect` first; critical findings
1266
+ block the commit and the fix-builder must retry.
1267
+ - **`skills/qualia-polish-loop/scripts/score.mjs`** — pure scoring
1268
+ utility. Takes 8 dimension scores, computes pass/fail per the rubric
1269
+ formula. Pipe-friendly. Used by the orchestrator and reusable for
1270
+ ad-hoc scoring.
1271
+ - **`skills/qualia-polish-loop/fixtures/clean.html`** — synthetic
1272
+ well-designed page for self-test Scenario 1 (Fraunces + JetBrains
1273
+ Mono, OKLCH palette, varied work-grid layout, fluid clamp() spacing,
1274
+ reduced-motion respected, 65ch line lengths).
1275
+ - **`skills/qualia-polish-loop/fixtures/broken.html`** — synthetic
1276
+ deliberately-bad page for self-test Scenario 2. Hits Inter font,
1277
+ blue-purple gradient, gradient text, three identical cards, side-stripe
1278
+ border, generic CTAs, max-width:1280, em-dash, outline:none — the
1279
+ full slop suite.
1280
+ - **`docs/playwright-loop-pilot-results.md`** — self-test results across
1281
+ the 3 mandated scenarios with screenshots, scores, iteration counts,
1282
+ token measurements.
1283
+ - **`docs/playwright-loop-design-notes.md`** — 1-page integration notes:
1284
+ how /qualia-polish-loop relates to /qualia-polish, when to use which,
1285
+ what's deferred to v5.2.
1286
+
1287
+ ### Changed
1288
+
1289
+ - **`bin/install.js`** — recursively copies `scripts/` and `fixtures/`
1290
+ subfolders from each skill (was: only `SKILL.md` + `REFERENCE.md`).
1291
+ Required so `qualia-polish-loop` can ship its Node helpers and HTML
1292
+ test fixtures alongside the skill.
1293
+ - **`skills/qualia-road/SKILL.md`** — already mentions
1294
+ `/qualia-polish-loop` (added in the v5.1-prep commit).
1295
+ - **`tests/bin.test.sh`** — adds 5 install assertions for the new skill,
1296
+ agent, and `scripts/` subfolder copying.
1297
+ - `package.json` stays at 5.0.0 — polish-loop folded into the same v5.0 release window per Fawzi's "all v5, not v5.1" call.
1298
+
1299
+ ### Honest caveats
1300
+
1301
+ - The vision evaluator runs as a Claude Agent spawn, NOT a separate
1302
+ vision-API call. Token cost per iteration is ~14.5K (3 PNG reads +
1303
+ rubric + brief + previous-iteration delta). The 100K budget cap covers
1304
+ ~6-7 iterations comfortably; 8 needs `--budget 150000`.
1305
+ - Capture defaults to dev-localhost. Vercel-preview mode is opt-in
1306
+ (`--deploy preview`) and slower (~30-60s/iter for the deploy).
1307
+ - Chromium-only — same precedent as `qualia-polish` Stage 4. Cross-
1308
+ browser visual diffs are deferred to v5.2.
1309
+ - One URL per invocation. Multi-route sweeps require chaining the loop
1310
+ per route. Deferred to v5.2.
1311
+
1312
+ ### Why these changes
1313
+
1314
+ Insights from `/insights` data (122 sessions, 292 commits, 10 days)
1315
+ identified design-iteration churn as the #1 recurring friction pattern.
1316
+ Quotes from the transcripts: "many frustrating iterations" on hero
1317
+ videos, "FUCK U / I CHANGED THE PAGE SO U STOP LYING" when Claude
1318
+ described unchanged screens. The root cause is that Claude could not
1319
+ see what the browser actually drew — only what was in the source. Every
1320
+ fix that didn't show up was a fight.
1321
+
1322
+ `/qualia-polish-loop` makes Claude look. Three viewports per iteration,
1323
+ real screenshots, vision-anchored scoring, deterministic kill-switch
1324
+ when the loop oscillates. It's the first Qualia skill where the agent
1325
+ can verify its own work end-to-end without a human in the visual loop.
1326
+
1327
+
1328
+
1329
+ ## [5.0.0] — 2026-05-03
1330
+
1331
+ **The "alignment discipline + insights-driven hardening" release.**
1332
+ Inspired by Matt Pocock's [skills](https://github.com/mattpocock/skills)
1333
+ repo and [Claude Code for Real Engineers](https://www.aihero.dev/cohorts/claude-code-for-real-engineers-2026-04),
1334
+ with a hardening pass driven by Fawzi's actual `/insights` data (122
1335
+ sessions, 292 commits, 10 days) and a 6-agent deep-research audit of
1336
+ the framework codebase.
1337
+
1338
+ Misalignment is the #1 failure mode in AI coding — vague plans become
1339
+ shipped bugs, terms overload across phases, decisions drift between
1340
+ sessions. v5.0 introduces an alignment substrate (CONTEXT.md domain
1341
+ glossary, decisions/ ADR folder), slims the global instruction budget
1342
+ per Matt's strongest claim ("LLMs realistically hold 300–500 instructions;
1343
+ bloating CLAUDE.md hamstrings every spawn"), folds grilling/deepening/TDD
1344
+ into existing skills, adds three small new skills for the autonomous
1345
+ loop (zoom, issues, triage), AND ships three insights-driven hooks
1346
+ (Vercel account verification, empty env-var guard, Supabase destructive-
1347
+ command guard) that prevent the documented top friction patterns
1348
+ deterministically. All existing skills remain. No substitution.
1349
+
1350
+ **Honest delta from earlier v5 drafts:** the deep-research audit caught
1351
+ real issues introduced by my own v5 work (dead `/qualia-grill` references
1352
+ in the road, a new prompt-injection surface from inlining CONTEXT.md
1353
+ into agent spawns, gh CLI heredoc shell injection in qualia-issues +
1354
+ qualia-triage). Those are all fixed before release.
1355
+
1356
+ ### Added
1357
+
1358
+ - **`templates/CONTEXT.md`** — domain glossary template seeded by
1359
+ `/qualia-new` from the discovery questioning. Loaded by every road
1360
+ agent BEFORE PROJECT.md and DESIGN.md. Each term has a one-sentence
1361
+ definition and an `Avoid:` list of rejected synonyms. Updated inline
1362
+ by `/qualia-discuss` as decisions crystallize. Killer of the "wait,
1363
+ what do you mean by *user*?" round-trips that waste tokens and surface
1364
+ bugs late.
1365
+ - **`templates/decisions/ADR-template.md`** — Architecture Decision
1366
+ Record template. Created sparingly: only for hard-to-reverse,
1367
+ surprising-without-context, real-tradeoff decisions. Cargo-culting
1368
+ ADRs ruins the signal. `/qualia-discuss` writes them when triggered.
1369
+ - **`/qualia-zoom`** — 50-line user-fired-only skill
1370
+ (`disable-model-invocation: true`). Maps an unfamiliar code area in
1371
+ domain-glossary terms — modules, callers, dependencies, smallest safe
1372
+ edit window. Used 50× a day in mature projects. Doesn't propose
1373
+ changes — just orients.
1374
+ - **`/qualia-issues`** — Externalize a phase plan to GitHub as
1375
+ independent vertical-slice issues with `needs-triage` label. Each
1376
+ issue is demoable end-to-end (schema → API → UI → tests),
1377
+ dependency-ordered. Uses CONTEXT.md domain language in titles.
1378
+ Externalized work means parallel humans, parallel sessions, or
1379
+ autonomous agents can pull from the queue.
1380
+ - **`/qualia-triage`** — State machine over the open issue queue:
1381
+ `needs-triage` / `needs-info` / `ready-for-agent` / `ready-for-human`
1382
+ / `wontfix`. Optionally routes `ready-for-agent` issues into
1383
+ autonomous `/qualia-build` runs. Together with `/qualia-issues` this
1384
+ is the autonomous-loop unlock — agent pulls from backlog, builds,
1385
+ verifies, closes, picks next.
1386
+ - **`/qualia-road`** — Discoverable workflow map (every command, when
1387
+ to use it, how phases chain). Lives in `skills/qualia-road/SKILL.md`
1388
+ so the agent loads it on demand instead of carrying the road in the
1389
+ global system prompt. Trigger phrases: "how does Qualia work",
1390
+ "what's the workflow", "show me the road", "what command does X".
1391
+ - **`docs/reviews/matt-pocock-skills-analysis.md`** — Deep analysis of
1392
+ Matt's repo and the alignment-discipline framing, with the original
1393
+ 15-change proposal and the rationale for each accepted/rejected fold.
1394
+
1395
+ ### Changed
1396
+
1397
+ - **`CLAUDE.md` slimmed from 88 lines to ~22.** The Road, Quality
1398
+ Gates, Context Isolation, Compaction, and prose explanations all
1399
+ moved out of the global system prompt. They now live in
1400
+ `/qualia-road` (discoverable) and the hooks (deterministic
1401
+ enforcement). Per Matt's strongest claim: LLMs realistically hold
1402
+ 300–500 instructions; everything in CLAUDE.md burns budget on every
1403
+ spawn. Steering rules belong in skills (loaded on relevant tasks) or
1404
+ hooks (enforced deterministically), not in CLAUDE.md.
1405
+ - **`AGENTS.md` slimmed identically** — multi-vendor mirror (Codex,
1406
+ Cursor, Continue, Aider, Devin) of CLAUDE.md. Same content, same
1407
+ size, cross-tool compatibility.
1408
+ - **`/qualia-discuss` upgraded with grilling pattern.** Was passive
1409
+ "capture decisions"; now actively grills: one question at a time,
1410
+ proposes a recommended answer with each, walks every branch of the
1411
+ decision tree until resolved. Updates CONTEXT.md inline as terms
1412
+ crystallize. Writes ADRs only for hard-to-reverse decisions. Auto-
1413
+ creates CONTEXT.md from template if missing. Same job (write
1414
+ `phase-{N}-context.md`), much more powerful interview.
1415
+ - **`/qualia-optimize` gained deepening pillar.** New `--deepen` mode
1416
+ spawns the architecture strategist with Ousterhout vocabulary
1417
+ (depth, locality, leverage, seam, deletion test). The Wave 2
1418
+ architecture-strategist prompt now includes deepening lens for full
1419
+ mode too. Reads CONTEXT.md and decisions/ as substrate. Refuses
1420
+ "extract a helper function" candidates that don't pass the deletion
1421
+ test — adding shallow modules is the disease, not the cure.
1422
+ - **`/qualia-test` gained `--tdd` mode.** Vertical-slice
1423
+ red→green→refactor loop. Anti-pattern: writing all tests first then
1424
+ all impl (horizontal). Correct: one test → one minimal impl → repeat.
1425
+ Test through public interface only. Never refactor while red. Each
1426
+ cycle is a commit.
1427
+ - **`/qualia-map` gained onboarding adapter.** New 5th parallel agent
1428
+ detects existing issue tracker (GH/GL/local), labels (mapped to
1429
+ canonical roles), domain docs (CONTEXT.md/glossary location), and
1430
+ existing CLAUDE.md/AGENTS.md. Writes `.planning/agents/{tracker,
1431
+ labels, domain}.md` adapter config. APPENDS (never overwrites)
1432
+ agent-skills block to existing CLAUDE.md/AGENTS.md. Brownfield
1433
+ projects now get Qualia capabilities without losing their existing
1434
+ process.
1435
+ - **`/qualia-new` emits CONTEXT.md and decisions/.** New Step 5a
1436
+ copies the templates and seeds the glossary from questioning
1437
+ answers (terms the user repeatedly used → glossary entries with
1438
+ `Avoid:` lines). Required for every new project — domain glossary
1439
+ is the single highest-leverage piece of substrate.
1440
+ - **`/qualia-report` tightened from 299 → 240 lines.** Hasan and
1441
+ Moayad will not get stuck on it. Improvements: empty-day handling
1442
+ (asks the employee what they did instead of forcing a fake report),
1443
+ structured synthesis template (verb list + 3-6 bullet format,
1444
+ blocker discipline), graceful pre-flight (no STATE.md / no git → soft
1445
+ warnings only, never blocks), git-push failure handling (exit code
1446
+ check, never silently fails), encouraging closing message ("You can
1447
+ clock out now. See you tomorrow."), self-service common-errors
1448
+ table for permission-denied/network/auth issues. ERP payload
1449
+ preserved verbatim — `client_report_id` (QS-REPORT-NN), full
1450
+ milestones[], build_count/deploy_count/deployed_url for tree
1451
+ rendering, 3-attempt retry with 1s/3s/9s backoff, 401/422 permanent-
1452
+ failure handling. The ERP connection stays beautiful: every payload
1453
+ field the portal needs is populated, every error path is actionable.
1454
+
1455
+ ### Hardening pass (insights-driven hooks, security, instruction-budget)
1456
+
1457
+ Added after the deep-research audit. Each item maps to a documented
1458
+ friction pattern in Fawzi's `/insights` report or a security/integrity
1459
+ issue surfaced by the 6 specialist agents.
1460
+
1461
+ **New hooks (insights-driven friction prevention)**
1462
+
1463
+ - **`hooks/vercel-account-guard.js`** — PreToolUse on `vercel --prod*` /
1464
+ `vercel deploy*`. Verifies active Vercel account against
1465
+ `~/.claude/.vercel-allowed-teams` (one team slug per line, mode 0600).
1466
+ Fail-OPEN when config is missing (don't block legit deploys when the
1467
+ user hasn't set the allowlist yet); fail-CLOSED when the active team
1468
+ doesn't match an allowed entry. Prevents the documented "wrong Vercel
1469
+ account redeploys" friction.
1470
+ - **`hooks/env-empty-guard.js`** — PreToolUse on `vercel env*`. Detects
1471
+ `vercel env add NAME ""` / `''` / trailing-`=` patterns and blocks
1472
+ with a clear message. Escape: `QUALIA_ALLOW_EMPTY_ENV=1`. Prevents
1473
+ the documented "empty env vars on production" incident.
1474
+ - **`hooks/supabase-destructive-guard.js`** — PreToolUse on `supabase*` /
1475
+ `npx supabase*`. Blocks `supabase db reset`, `supabase db push --force`,
1476
+ `supabase migration repair`. Escape: `QUALIA_ALLOW_DESTRUCTIVE=1`
1477
+ (shared with git-guardrails). Prevents the documented "DB wipe leaves
1478
+ orphan rows" incident.
1479
+
1480
+ **State machine + reliability**
1481
+
1482
+ - **`state.js cmdInit` throwaway-name guard** — `init --project test|tmp|
1483
+ scratch|demo|sample|untitled|new-project|...` returns `SUSPICIOUS_NAME`
1484
+ instead of creating a throwaway project. `--force` bypasses. Prevents
1485
+ the documented "test-name-only project accidentally created" incident.
1486
+ - **`hooks/pre-deploy-gate.js` lint escape** — `QUALIA_SKIP_LINT=1` skips
1487
+ the lint gate while keeping tsc, tests, build, and security gates
1488
+ mandatory. For the documented "lint blocks ship after JSX auto-fixer
1489
+ broke things" friction.
1490
+ - **`hooks/pre-compact.js` saves tracking.json too** — was only `git add
1491
+ STATE.md`, losing tracking.json mutations across compactions. ERP got
1492
+ stale data. Now stages both planning files.
1493
+ - **`hooks/pre-push.js` warns instead of blocks** on tracking.json
1494
+ corruption. A corrupt ERP-metadata file should never block a production
1495
+ hotfix. Self-service fix surfaced in the warning. Restore old behavior
1496
+ with `QUALIA_BLOCK_ON_TRACKING_FAIL=1`.
1497
+ - **`state.js cmdCloseMilestone`** — wraps `writeTracking` in the journal
1498
+ pattern (matching `cmdTransition`) so a crash mid-write can be
1499
+ detected and recovered. STATE.md is intentionally NOT mutated here
1500
+ (next `init --force` rewrites it for the new milestone).
1501
+
1502
+ **Security hardening**
1503
+
1504
+ - **ERP API key no longer passed as curl CLI argument** — `bin/cli.js`
1505
+ `cmdErpPing` now uses Node's native `https.request` instead of
1506
+ `spawnSync("curl", ["-H", "Authorization: Bearer $KEY"])`. The CLI-arg
1507
+ pattern exposed the bearer token via `/proc/<pid>/cmdline` to any
1508
+ local process during the curl invocation. Native `https.request` keeps
1509
+ the auth header in-process.
1510
+ - **`set-erp-key` refuses positional arguments** — positional args land
1511
+ in `~/.bash_history` / `~/.zsh_history`. Now reads from stdin only:
1512
+ `printf '%s' "$KEY" | qualia-framework set-erp-key`. Helpful error
1513
+ message if positional is attempted.
1514
+ - **`bin/install.js` backs up CLAUDE.md and settings.json before
1515
+ overwrite** — `.bak.{ISO-timestamp}` files. Settings.json now uses
1516
+ atomic write (tmp + rename) to eliminate partial-write risk during
1517
+ the merge.
1518
+ - **Subagent prompt-injection defense** — `agents/builder.md`,
1519
+ `agents/planner.md`, `agents/verifier.md` now have a "Trust boundary"
1520
+ block warning that content within `<phase_context>`, `<task_context>`,
1521
+ `<project_context>`, `<glossary>`, `<decisions>`, etc. is project DATA
1522
+ not instructions. The agents are told to refuse and report directives
1523
+ appearing inside those tags as project-file injection attempts. This
1524
+ closes the new attack surface introduced by inlining CONTEXT.md into
1525
+ every road agent spawn.
1526
+ - **`qualia-issues` and `qualia-triage` use `gh issue create
1527
+ --body-file`** instead of heredoc-interpolated bodies. The previous
1528
+ pattern allowed shell injection via crafted plan content (shell
1529
+ metacharacters or a literal `EOF` line in user-controlled text).
1530
+
1531
+ **Instruction-budget cuts (Matt Pocock discipline applied to rules)**
1532
+
1533
+ - **`globs:` frontmatter on `rules/design-brand.md`,
1534
+ `rules/design-laws.md`, `rules/design-product.md`,
1535
+ `rules/design-rubric.md`** — these 4 design rules files (~5,508
1536
+ tokens combined) were loading on every conversation regardless of
1537
+ whether the user was editing a backend API route or a SQL migration.
1538
+ Now glob-gated to `["*.tsx", "*.jsx", "*.css", "*.scss", "*.html",
1539
+ "*.vue", "*.svelte"]`. Saves ~5,508 tokens per non-frontend
1540
+ conversation. The single highest-ROI change in the entire audit.
1541
+ - **`globs:` on `rules/grounding.md`** + removed duplicate
1542
+ `@grounding.md` references from spawn templates in
1543
+ `qualia-build/SKILL.md`, `qualia-plan/SKILL.md`,
1544
+ `qualia-verify/SKILL.md`. Saves ~1,175 tokens of duplicate load per
1545
+ agent spawn.
1546
+ - **`agents/builder.md` duplicate-rules block deleted** — 21 lines
1547
+ re-stating security/design/perf rules that already auto-load from
1548
+ `rules/*.md`. Replaced with a single line pointing to the auto-load
1549
+ source of truth. Saves ~280 tokens per builder spawn.
1550
+ - **`templates/CONTEXT.md` prose stripped** — meta-commentary
1551
+ ("What this is", "Why it exists", "How to update this file") was
1552
+ loading into every road agent via `.planning/CONTEXT.md`. Replaced
1553
+ with a one-line HTML comment. Saves ~138 tokens per spawn.
1554
+
1555
+ **Discoverability + consistency**
1556
+
1557
+ - **`disable-model-invocation: true`** added to `qualia-road`,
1558
+ `qualia-ship`, `qualia-handoff` (joining `qualia-zoom` from earlier
1559
+ in v5). These are pure-reference / irreversible-production skills
1560
+ that should never auto-fire from natural-language ambiguity.
1561
+ - **5 under-described skill descriptions expanded** —
1562
+ `qualia-verify`, `qualia-build`, `qualia-plan`, `qualia-task`,
1563
+ `zoho-workflow` (each was <25 words with no "Use when" clause).
1564
+ Now 30-60 words with explicit trigger phrases per the framework's
1565
+ description-as-API-surface convention.
1566
+ - **`qualia-road` dead skill references removed** — `/qualia-grill`,
1567
+ `/qualia-deepen`, `/qualia-tdd`, `/qualia-onboard` were listed as
1568
+ commands but were folded into existing skills. Replaced with the
1569
+ actual folded locations (`/qualia-discuss`, `/qualia-optimize
1570
+ --deepen`, `/qualia-test --tdd`, `/qualia-map`).
1571
+ - **`templates/CONTEXT.md` `/qualia-grill` reference removed** — same
1572
+ fold, same dead reference, same fix.
1573
+ - **README.md and guide.md updated to v5** — version, skill count
1574
+ (32), hook count (12), template count (24), v5 changes summary.
1575
+
1576
+ ### Test coverage (+34 new tests, 226 → 260)
1577
+
1578
+ 19 v5-specific tests added in Wave B and 15 hardening-pass tests
1579
+ added in Wave C. Coverage now includes: CONTEXT.md install,
1580
+ decisions/ADR-template install, all 4 new skill folder installs,
1581
+ qualia-discuss grilling reference, qualia-discuss CONTEXT.md
1582
+ reference, qualia-road `disable-model-invocation`, qualia-road dead-
1583
+ ref guard, CONTEXT.md template `/qualia-grill` guard, builder.md
1584
+ trust-boundary block, qualia-issues `--body-file` (no heredoc
1585
+ injection), 3 new hooks parse-validity + install, state.js
1586
+ `next-report-id` (alloc + increment + --peek), state.js init
1587
+ suspicious-name guard (3 cases), pre-deploy-gate `QUALIA_SKIP_LINT`
1588
+ escape.
1589
+
1590
+ ### Deferred to v5.1
1591
+
1592
+ - **SKILL.md / REFERENCE.md / scripts/ split** for skills > 200 lines
1593
+ (qualia-new at 487, qualia-optimize at 466, others 200–300). The
1594
+ pattern is correct per Matt's progressive-disclosure rule, but no
1595
+ precedent exists in the framework's loader behavior, and the v5.0
1596
+ test suite assumes single-file skills. Deferring is honest. The
1597
+ oversized skills are still cohesive and execution-essential —
1598
+ splitting will be a focused v5.1 project with loader-behavior
1599
+ testing.
1600
+ - **Caveman-mode template** for in-flight subagent prompts (~25%
1601
+ token reduction × 50 builder spawns per project). Worth real money
1602
+ at scale. Deferred to keep v5.0 scope honest.
1603
+ - **Autonomous visual-polish loop with Playwright MCP** — for the
1604
+ documented "design iteration churn" friction (5-10 manual rounds
1605
+ on hero videos, mobile layouts). The insights report's #1 strategic
1606
+ workflow opportunity. Substantial design work; v5.1.
1607
+ - **Parallel lead-enrichment swarm** — multi-source confidence-scored
1608
+ merge for lead-gen pipelines. Insights report's #2 strategic
1609
+ opportunity. v5.1.
1610
+
1611
+ ### Why these changes
1612
+
1613
+ Matt Pocock teaches that the bottleneck on AI-coding quality is not
1614
+ the model — it's the alignment between human, agent, code, and
1615
+ domain. Every skill in his repo fixes one alignment failure mode.
1616
+ Qualia v4.5.0 was strong on execution machinery (phase/wave/task
1617
+ hierarchy, fresh-context spawning, the verifier loop, the design
1618
+ substrate) but treated alignment as a one-shot at `/qualia-new`.
1619
+ v5.0 adds the alignment rituals that prevent decision drift between
1620
+ phases: a domain glossary every agent reads, ADRs for hard-to-reverse
1621
+ decisions, grilling that exposes vagueness before code is written,
1622
+ deepening that fights shallow-module entropy, vertical-slice TDD that
1623
+ keeps tests honest. Combined with Qualia's existing execution machinery
1624
+ this is genuinely a different framework. The instruction-budget
1625
+ discipline (CLAUDE.md slim) is the multiplier — every spawn now uses
1626
+ its 300–500 instruction budget on the work, not on rules-it-already-knows.
1627
+
1628
+ ## [4.5.0] — 2026-05-02
1629
+
1630
+ **The "Design as a thread" release.** Design stops being a final phase
1631
+ and becomes a verification dimension every road agent honors. Informed
1632
+ by deep research (UI-Bench, Refactoring UI, Anthropic frontend-design
1633
+ skill, awesome-claude-design), the impeccable repo's vocabulary
1634
+ (OKLCH, registers, scene sentence, second-order slop test), and 5
1635
+ internal research agents.
1636
+
1637
+ ### Added
1638
+
1639
+ - **`rules/design-laws.md`** — universal design rules both registers
1640
+ honor: OKLCH mandate, color strategy commitment scale, scene sentence
1641
+ for theme, absolute bans (gradient text, side-stripe borders,
1642
+ glassmorphism default, hero-metric template, identical card grids,
1643
+ modal-as-first-thought), no em-dashes, second-order slop test, single
1644
+ icon family rule, container depth max 2.
1645
+ - **`rules/design-brand.md`** — Brand register (marketing, landing,
1646
+ portfolio): distinctiveness is the bar. Reflex-reject aesthetic lanes.
1647
+ Pre-code design brief (direction, color strategy, scene sentence,
1648
+ differentiation). Banned display fonts. Allowed visual flourishes
1649
+ (gradient meshes, noise, parallax signature motion).
1650
+ - **`rules/design-product.md`** — Product register (app UI, admin,
1651
+ dashboards): earned familiarity is the bar. Reference-app anchoring.
1652
+ Density target table (comfortable / standard / compact / ultra-compact).
1653
+ Per-component rules (buttons 3 variants max, tables tabular numerals,
1654
+ empty states require icon + context + action).
1655
+ - **`rules/design-rubric.md`** — 8-dimension anchored 1-5 scoring used
1656
+ by verifier and `/qualia-polish --critique`. Default to 3 (= ships).
1657
+ Score below 3 fails the phase, same as functional bug.
1658
+ - **`templates/PRODUCT.md`** — REQUIRED at /qualia-new (v4.5.0+). Users,
1659
+ brand voice, register, anti-references (mandatory 3-5), strategic
1660
+ principles, differentiation. Substrate every road agent loads.
1661
+ - **`templates/DESIGN.md`** — Rewritten OKLCH-first. Mandatory direction
1662
+ block (aesthetic, color strategy, scene sentence, differentiation).
1663
+ Token-driven components. Anti-pattern checklist auto-runnable.
1664
+ - **`bin/slop-detect.mjs`** — Standalone CLI scanner. ~17 anti-pattern
1665
+ rules across critical / high / medium / low. Exit 1 on critical
1666
+ blocks commit. No AI required. Builders run pre-commit.
1667
+ - **`/qualia-polish` rewritten as scope-adaptive** — six modes:
1668
+ Component (~30s) | Section (~3m) | App (~12m) | Redesign (~30m) |
1669
+ Critique (read-only) | Quick (~1m). Stage selection follows from
1670
+ scope. Mandatory preflight gates (PRODUCT, DESIGN, slop-detect).
1671
+ - **Vision-loop architecture** for Redesign scope: webapp-testing skill
1672
+ + 3-viewport matrix (375/768/1280) + anchored rubric prompt + 2-iter
1673
+ hard cap with regression-stop.
1674
+
1675
+ ### Changed
1676
+
1677
+ - **`agents/planner.md`** — Inputs add product_context, design_spec,
1678
+ design_substrate. Task template adds **Design:** field (required for
1679
+ any .tsx/.jsx/.css task) with register, tokens used, scope, anti-
1680
+ pattern guard line.
1681
+ - **`agents/plan-checker.md`** — New Rule 7b: frontend tasks must have
1682
+ Design field with valid register, non-empty token list, no raw hex.
1683
+ Greps plan for absolute-ban patterns and rejects.
1684
+ - **`agents/builder.md`** — Self-verify step 4 mandatory: slop-detect
1685
+ on touched frontend files. Exit 1 BLOCKS commit. Rule 5 frontend
1686
+ standards rewritten to point at design substrate as source of truth.
1687
+ - **`agents/verifier.md`** — Adds Design Verification block: slop-detect
1688
+ gate (Step A), 8-dim rubric scoring (Step B), drift audit (Step C).
1689
+ Combined phase verdict: functional AND slop-detect AND rubric pass.
1690
+ - **`/qualia-new`** — Adds Step 5b (PRODUCT.md generation, 5 questions,
1691
+ required) and rewrites Step 7 (DESIGN.md OKLCH-first with mandatory
1692
+ 4-line direction commit).
1693
+ - **`bin/cli.js`** — QUALIA_BIN_FILES adds slop-detect.mjs.
1694
+ QUALIA_RULE_FILES adds design-laws / design-brand / design-product /
1695
+ design-rubric. Help text removes /qualia-design, adds /qualia-polish.
1696
+ - **`bin/install.js`** — slop-detect.mjs copied to ~/.claude/bin and
1697
+ chmodded executable. New rules + PRODUCT.md template auto-picked up
1698
+ by directory walks.
1699
+ - **`CLAUDE.md` + `AGENTS.md`** — Road updated: design described as a
1700
+ thread through every phase, not just Handoff Phase 1. /qualia-polish
1701
+ six modes documented.
1702
+
1703
+ ### Removed
1704
+
1705
+ - **`/qualia-design`** skill — its surface area is fully covered by
1706
+ `/qualia-polish` modes. Help text and references purged.
1707
+
1708
+ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1709
+
1710
+ ---
1711
+
1712
+ ## [4.4.0] — 2026-04-28
1713
+
1714
+ **The "Plan as Data + Agent Telemetry" release.** Lays the substrate for deterministic verification and per-spawn observability. Skill rewiring lands in 4.5.
1715
+
1716
+ ### Added
1717
+
1718
+ - **`bin/plan-contract.js`** — JSON plan contract validator (zero deps, ~150 LOC). Replaces ad-hoc markdown re-parsing. Schema in `docs/plan-contract.md`. Four verification check types (`file-exists`, `grep-match`, `command-exit`, `behavioral`); behavioral evidence is structured (`{path, matcher?, description}`), blocking vibes-based passes at the schema level.
1719
+ - **`bin/agent-runs.js`** — append-only JSONL telemetry writer (`.planning/agent-runs.jsonl`). OTel GenAI-aligned field names. 14-code closed `failure_reason` enum. Side log files only on failure. Spec in `docs/agent-runs.md`.
1720
+ - **`qualia-framework agents`** — reader CLI. Flags: `--failed`, `--task <id>`, `--phase <n>`, `prune --before YYYY-MM-DD`.
1721
+ - **`docs/plan-contract.md`** + **`docs/agent-runs.md`** — committed v1 specs with locked design decisions.
1722
+ - **Drift detection:** `source_plan_hash` field on contracts; `plan-contract.checkDrift()` flags when the markdown plan diverges from its compiled contract.
1723
+ - **Privacy:** `QUALIA_TELEMETRY=off` disables agent-runs writes (reads still surface history).
1724
+ - `tests/lib.test.sh` — 15 cases covering both libraries.
1725
+ - `qualia-framework set-erp-key` for saving/enabling the ERP API key without manually editing `~/.claude/.erp-api-key`.
1726
+ - Targeted shell test scripts in `package.json` (`test:state`, `test:hooks`, `test:bin`, `test:lib`, `test:statusline`, `test:shell`); `npm test` runs the full shell gate.
1727
+
1728
+ ### Changed
1729
+
1730
+ - `migrate` now wires the full v4.3 hook set, including `git-guardrails.js`, `pre-compact.js`, and the `Stop` event.
1731
+ - `migrate` help text updated — no longer says "v2 to v3."
1732
+ - README/help docs now match the current package counts: 28 skills, 9 hooks, 8 agents, 6 rules, 21 templates.
1733
+ - `auto-update` caches failed npm lookups so offline registry checks do not add a timeout to every Bash command.
1734
+ - `install.js` copies `plan-contract.js` and `agent-runs.js` into `~/.claude/bin/`; `doctor` checks both.
1735
+
1736
+ ### Fixed
1737
+
1738
+ - State mutators now fail loudly with `STATE_LOCK_TIMEOUT` instead of proceeding without `.planning/.state.lock`.
1739
+ - `pre-push` now blocks when tracking sync cannot be committed instead of letting a stale ERP state push through silently.
1740
+ - `pre-compact` detects untracked `.planning/STATE.md` before compaction.
1741
+ - `pre-deploy-gate` surfaces the last gate output lines on failure instead of hiding root cause behind a generic block message.
1742
+ - `stop-session-log` reads `tracking.total_phases` and still supports legacy `phase_total`.
1743
+ - CLI analytics now reads top-level trace fields (`verification`, `gap_closure`) written by `state.js`.
1744
+ - Stale tests reconciled with v4.3 behavior: retired `block-env-edit`, PreToolUse exit code 2, forced milestone close tests, opt-in ERP key setup.
1745
+
1746
+ ### Changed
1747
+
1748
+ - `migrate` now wires the full v4.3 hook set, including `git-guardrails.js`, `pre-compact.js`, and the `Stop` event.
1749
+ - README/help docs now match the current package counts: 28 skills, 9 hooks, 8 agents, 6 rules, and 21 templates.
1750
+ - `auto-update` caches failed npm lookups so offline registry checks do not add a timeout to every Bash command.
1751
+
1752
+ ### Fixed
1753
+
1754
+ - State mutators now fail loudly with `STATE_LOCK_TIMEOUT` instead of proceeding without `.planning/.state.lock`.
1755
+ - `pre-push` now blocks when tracking sync cannot be committed instead of letting a stale ERP state push through silently.
1756
+ - `pre-compact` detects untracked `.planning/STATE.md` before compaction.
1757
+ - `pre-deploy-gate` surfaces the last gate output lines on failure instead of hiding root cause behind a generic block message.
1758
+ - `stop-session-log` reads `tracking.total_phases` and still supports legacy `phase_total`.
1759
+ - CLI analytics now reads top-level trace fields (`verification`, `gap_closure`) written by `state.js`.
1760
+ - Stale tests were reconciled with v4.3 behavior: retired `block-env-edit`, PreToolUse exit code 2, forced milestone close tests, and opt-in ERP key setup.
1761
+
1762
+ ## [4.3.0] — 2026-04-26
1763
+
1764
+ **The "Compound + Self-Healing" release.** Five sequenced phases (#9–#13 on GitHub) shipped in one window, scoped from the 2026-04-25 NotebookLM deep-dive on Anthropic's subagent upgrade, Karpathy's LLM knowledge bases, Cole Medin's parallel-worktrees playbook, and the mattpocock skills directory. Closes 11 of the 12 top-priority findings from the v4.1.0 audit. The framework now (a) compounds across every session through an automated memory layer, (b) heals itself when the verifier catches a gap, and (c) blocks destructive git operations universally.
1765
+
1766
+ ### Added
1767
+
1768
+ #### Memory layer (Karpathy raw → wiki, end-to-end automated)
1769
+
1770
+ - **`hooks/stop-session-log.js`** — Stop hook seeding the **raw tier**. Appends one mechanical line per turn to `~/.claude/knowledge/daily-log/{YYYY-MM-DD}.md` (project, branch, phase, task counts, commit count, top-3 touched files). Rate-limited 5min, skipped on no activity, never blocks.
1771
+ - **`bin/knowledge.js`** — Unified memory-layer loader. Subcommands: `load <file>` (with aliases `patterns`/`fixes`/`client` or any bare filename), `list`, `search <query>`, `append --type <pattern|fix|client> --title <T> --body <B>`, `path <file>`, `help`. Default invocation prints `index.md`. Subdirectory support: bare-name lookups auto-discover in `concepts/`/`connections/`/`daily-log/` if no top-level match exists; `concepts/foo` works as a qualified path; top-level wins on collision. Every command exits 0 on missing files with a `(no entries)` stub so skills can pipe output safely.
1772
+ - **`/qualia-flush` skill** — The LLM job that promotes raw → curated. Reads recent `daily-log/*.md` (default 14-day window, configurable), groups by project, identifies recurring patterns/decisions, writes promotions via `knowledge.js append`. Conservative: single-occurrence entries stay raw until they recur. `--dry-run`, `--project NAME` supported.
1773
+ - **`bin/knowledge-flush.js`** — Cron-runnable non-interactive `/qualia-flush` runner. Wraps `claude -p "/qualia-flush --days 7"` with a 5-minute hard cap and writes a structured JSONL audit log to `~/.claude/.qualia-flush.log`. Cron-spam-safe: missing CLI / empty daily-log → exits 0 with a logged skip; only true execution failures exit 1. Recommended cron: `0 3 * * 0 node ~/.claude/bin/knowledge-flush.js >> ~/.claude/.qualia-flush.log 2>&1`.
1774
+ - **`templates/knowledge/{agents,index}.md`** — Karpathy meta-doc + index entry point. Installed once at `~/.claude/knowledge/`, never overwrites existing content. Closes v4.1.0 audit finding #3 ("11 of 14 knowledge files are invisible") by giving every agent one deterministic place to start.
1775
+ - **Builder reads knowledge before writing code** (`agents/builder.md` §2b). New "Load Relevant Knowledge" section instructs the builder to call `knowledge.js` first. Hardcoded `cat` is forbidden — the loader is the only sanctioned path. Closes v4.1.0 audit finding #2 (the most-flagged miss).
1776
+
1777
+ #### Self-healing AI layer
1778
+
1779
+ - **`/qualia-postmortem` skill** — Cole Medin's pillar 5: "anytime we encounter a bug in a pull request, we don't just fix the bug, we fix the underlying system that allowed for the bug." After a verify FAIL, identifies which AI-layer file (`agents/X.md`, `rules/Y.md`, `skills/Z/SKILL.md`) should have caught the gap and proposes a surgical delta. Writes `.planning/phase-{N}-postmortem.md` for review. With `--apply`, edits the installed file and TODOs a framework-repo PR so the lesson survives reinstall. Promotes generalizable patterns to the knowledge layer. Conservative: max 3 deltas per postmortem.
1780
+ - **`/qualia-verify --adversarial` flag** — Spawns a SECOND verifier in fresh context with an adversarial prompt ("find what's wrong, not what's right"). Auto-enabled for the Handoff milestone and any phase whose plan touches `auth|payment|migration|rls|service_role` files. Findings union with the cooperative pass; either pass finding CRITICAL or HIGH = phase FAIL. Mitigates the "kid grading their own homework" bias documented in the NotebookLM source.
1781
+ - **`/qualia-verify` auto-invokes `/qualia-postmortem` on FAIL** before the gap-closure re-plan. The postmortem writes the report by default — no destructive AI-layer edits unless the user runs `--apply`.
1782
+
1783
+ #### Forked subagents
1784
+
1785
+ - **`CLAUDE_CODE_FORK_SUBAGENT=1`** in `~/.claude/settings.json` env block. Anthropic shipped forked subagents in 2026-04 to solve the "design subagent loses 50k tokens of nuance" failure mode. Forks inherit full conversation history + share the prompt cache. On by default for all installs.
1786
+ - **`/qualia-design` prefers forks for batch fan-out** when the conversation contains design-taste context. Blank-context spawns still used for mechanical anti-pattern fixes.
1787
+
1788
+ #### Operational tooling
1789
+
1790
+ - **`hooks/git-guardrails.js`** — PreToolUse/Bash hook blocking destructive git ops universally (OWNER too): `git push --force`/`-f` to main/master, `git reset --hard` while on main/master, `git clean -fd[x]`, `git branch -D main|master`, `rm -rf .git`. `--force-with-lease` is allowed. Escape hatch: `QUALIA_ALLOW_DESTRUCTIVE=1`. Exits 2 with a clear reason and remediation suggestion. Inspired by `mattpocock/skills/git-guardrails-claude-code`.
1791
+ - **`qualia-framework doctor`** (aliases: `health`, `health-check`) — Post-install diagnostic. Critical files, all 9 hooks present, knowledge layer initialized, `settings.json` hook wiring (SessionStart + PreToolUse + PreCompact + Stop), config metadata. Exits 0 if healthy, 1 with itemized issues. Inspired by davila7/claude-code-templates' `--health-check`.
1792
+ - **`qualia-framework flush`** — Convenience CLI wrapper around `bin/knowledge-flush.js` for ad-hoc invocation. `qualia-framework flush --dry-run` previews what the next cron run would do.
1793
+
1794
+ ### Changed
1795
+
1796
+ - **Hook count: 7 → 9.** Added `git-guardrails.js`, `stop-session-log.js`. New `Stop` event in `settings.json`.
1797
+ - **`/qualia-learn` rewritten to use the loader.** Duplicate detection now goes through `knowledge.js search`. Append step uses `knowledge.js append --type pattern --title ...` — no manual ID generation, no shell-escaping concerns.
1798
+ - **`/qualia-debug`, `/qualia-plan`, `/qualia-new`, `/qualia-review` migrated off hardcoded `cat`.** Five `cat ~/.claude/knowledge/*.md` calls across four skills now go through the loader. Newly-added knowledge files become reachable to every skill via the index automatically.
1799
+ - **`agents/research-synthesizer.md` uses `model: haiku`.** Conservative first entry in the model-per-agent matrix. Synthesizer is pure markdown merging — no new reasoning needed, ~7× cheaper. Other agents (planner/builder/verifier/plan-checker/roadmapper/qa-browser) retain their default model — they're stakes-bearing.
1800
+ - **`bin/install.js` initializes the knowledge layer** on first install (never overwrites existing content). The `templates/knowledge/` subdirectory is excluded from the regular templates copy to avoid double-installation.
1801
+ - **`bin/install.js` ships `knowledge.js` + `knowledge-flush.js`** to `~/.claude/bin/` alongside `state.js`/`qualia-ui.js`/`statusline.js`. `QUALIA_BIN_FILES` updated for clean uninstall.
1802
+
1803
+ ### Fixed
1804
+
1805
+ - **Two pre-existing test failures** in `tests/bin.test.sh` that had been broken since v3.2.0: hook-count assertion still expected 8 hooks (had been wrong for two releases), and the hook-wiring assertion still grep'd for the deleted `block-env-edit.js`. Both updated to match the v4.3.0 install state (9 hooks, no block-env-edit).
1806
+
1807
+ ### Notes
1808
+
1809
+ Cumulative tests: **+49 new passing assertions**, 2 broken tests fixed, 168/168 node tests + 78/79 bin tests + 61/68 hook tests (the 7 pre-deploy-gate + 1 erp-api-key shell failures predate this release and are tracked separately).
1810
+
1811
+ What's deferred to v4.4.0: worktree-aware phase parallelism (Cole Medin's pillars 2–4 — `bin/qualia-worktree.sh`, port-from-hash, Supabase branch-per-worktree), audit cleanup (orphan skills, color drift, per-employee memory scoping — v4.1.0 findings #4, #6, #7, #8), `npm publish` post-merge.
1812
+
1813
+ For developers integrating the framework: re-run `npx qualia-framework@latest install` after this release lands to pick up the new hooks, knowledge layer, and `bin/` scripts. Existing `~/.claude/knowledge/*.md` content is preserved on reinstall.
1814
+
1815
+ ## [4.1.1] — 2026-04-22
1816
+
1817
+ **Critical silent-fail hotfix.** Follow-up to the v4.1.0 audit (`docs/reviews/v4.1.0-audit.html`) which surfaced 142 findings across 4 dimensions. This release addresses the 5 highest-risk issues — each one previously let an operation fail silently or skip safety checks without telling the user. Subsequent releases (v4.2.0 structural, v4.3.0 harness patterns) will handle the remaining findings.
1818
+
1819
+ ### Fixed
1820
+
1821
+ - **`grounding.md` phantom on stale installs** (`hooks/session-start.js`, `hooks/auto-update.js`). Users who upgraded from v4.0.5 → v4.1.0 without re-running `npx qualia-framework@latest install` had no `~/.claude/rules/grounding.md`, so every planner/builder/verifier spawn silently received empty grounding context. Session-start now spot-checks 5 critical files (`grounding.md`, `security.md`, `frontend.md`, `deployment.md`, `state.js`) once per 24h and prints a loud banner with the exact install command when anything is missing. `auto-update.js` invalidates the health cache on every version bump so newly-shipped critical files are verified on the next session.
1822
+ - **`qualia-report` ERP upload silent-fail chain** (`skills/qualia-report/SKILL.md`). Three independent silent failures were producing garbage reports: empty `API_KEY` → sent `Authorization: Bearer ` (blank token) then surfaced a generic 401 with "Ask Fawzi" and no diagnostic. Empty `CLIENT_REPORT_ID` from a state.js failure → commit message dropped the ID, ERP payload carried empty string. `SUBMITTED_BY` shell-interpolated into `node -e` script → a single quote in `git config user.name` silently broke the payload. Fixes: guard empty API key before the POST loop with a clear `~/.claude/.erp-api-key` diagnostic, validate `CLIENT_REPORT_ID` is non-empty and fail loudly if state.js didn't return one, pass `SUBMITTED_BY`/`SUBMITTED_AT`/`CLIENT_REPORT_ID`/`REPORT_FILE` via environment variables (which are inert to shell metacharacters) instead of string interpolation, and make the 401 handler actually explain the likely cause.
1823
+ - **`/qualia-ship` had no state guard and a hallucinated domain** (`skills/qualia-ship/SKILL.md`). The skill would run from any state (setup/planned/built — even `shipped` → double-deploy possible), its security scan only grepped `service_role` (missed hardcoded keys, tracked `.env`, `dangerouslySetInnerHTML`), and its post-deploy verification used a literal `{domain}` placeholder that expected the LLM to hallucinate the URL. Now: state gate refuses any status except `polished` or `verified+pass` (with `--force` escape hatch for hotfixes), security scan inlines the CRITICAL checks from `/qualia-review` verbatim so the two skills agree, and the URL is read from `tracking.json.deployed_url` with a loud error if missing. Description also gained the missing trigger phrases (`deploy`, `ship it`, `go live`, `push to prod`, `launch`).
1824
+ - **`templates/help.html:410` mis-described `/qualia-idk`.** Was listed as "Alias for /qualia. The smart router handles all 'idk' situations" — directly contradicts the actual SKILL.md which defines it as a diagnostic intelligence running two isolated scans. Team members reading the help page were sent to the wrong skill. Description now matches the skill.
1825
+ - **`hooks/session-start.js` silent error swallow.** The top-level `try { ... } catch { }` block recorded `result: "allow"` in traces even when the try body threw, so silent session-start crashes were invisible in analytics. Error cases now log to `.qualia-traces/{date}.jsonl` with `result: "error"` and the exception message.
1826
+ - **CI was failing on every PR, across all 18 matrix cells, and being ignored.** The `.github/workflows/test.yml` used `actions/setup-node@v4` with `cache: 'npm'`, which requires a `package-lock.json` — but this framework has zero runtime deps and no lockfile. Every PR since the workflow was added reported FAILURE before tests even ran, and merges happened on red CI. Removed the `cache:` key; tests now actually execute on every push.
1827
+ - **`pre-push.js` now passes `-c core.autocrlf=false` on its stamp commands.** Defensive fix against the Windows failure mode where autocrlf normalization produces an empty diff, the stamp-commit fails, and the hook's rollback restores stale `last_commit`. The behavioral test for this path is temporarily skipped on Windows (tracked for v4.1.2) — the Linux + macOS matrix is fully green with this change. Windows platform-specific investigation needs a live Windows box and is out of scope for this hotfix.
1828
+
1829
+ ### Notes
1830
+
1831
+ Full framework review (142 findings) and v4.2.0 / v4.3.0 / v4.4.0 roadmap documented separately. This release handles the 5 highest-risk silent-fail paths; subsequent releases handle structural debt (3-tier memory, unified color module, orphan skill consolidation) and harness-engineering patterns (adversarial build, continuous reviewer agents, component-fetch skill).
1832
+
1833
+ ## [4.1.0] — 2026-04-21
1834
+
1835
+ **Command quality + build workflow hardening.** Deep research across 5 parallel Opus agents surfaced 15 concrete improvements — shipped across 4 commits. Every agent spawn now loads a shared **Grounding Protocol** (cite-or-INSUFFICIENT-EVIDENCE, no hedging, file:line evidence required for every finding) and deterministic scoring rubrics. Build workflow gains cache-aware prompt ordering (92% prefix-cache hit rate per Anthropic docs), explicit parallel wave dispatch, and a structured builder output contract. `qualia-debug` was fully rewritten from interactive to investigative one-shot. Research reports committed to `docs/research/`. 168/168 tests passing.
1836
+
1837
+ ### Added
1838
+
1839
+ - **`rules/grounding.md` — shared Grounding Protocol + 5 rubrics.** New file referenced from every skill that spawns a subagent. Contains: 8-rule Grounding Protocol (every claim requires `file:line — "quoted"` evidence, no hedging language, scores require rubric citations, output shapes are contracts, tool budgets enforced, preconditions checked); **Severity Rubric** with objective criteria per level and a deterministic `max(1, 5 − ⌊weighted_sum/8⌋)` category-score formula; **Task-Done Rubric** (compiles / no stubs / wired / AC validated / committed); **Evidence Citation Format**; **Deviation JSON Format**; **Design Quality Rubric** (6 dimensions × 3 levels); **cache-aware prompt-ordering rule**. Install.js picks this up automatically via `rules/` directory copy.
1840
+ - **Structured Output Contract for builder** (`agents/builder.md`). Builder must return `DONE — Task {N}: {commit_hash}` with file list, `BLOCKED — {reason}` with JSON deviation block (`{type, task, file, planned, actual, impact}`), or `PARTIAL — {done}; remaining: {left}`. Orchestrator can now parse results programmatically instead of regex-guessing free-text.
1841
+ - **Explicit file-based dependency graph for wave assignment** (`agents/planner.md`). Replaces vibes-based "tasks with no dependencies" with a mechanical algorithm: build `writes(T)` / `reads(T)` sets from Files and Context fields, declare edge A→B when `writes(A) ∩ reads(B) ≠ ∅`, topological-sort into waves, enforce write-conflict check within each wave. Worked example table included. Same inputs → same waves.
1842
+ - **Rule 8 for plan-checker** (`agents/plan-checker.md`). Each task's `**Validation:**` list must include at least one `grep-match` or `command-exit` that tests behavior — a task whose only Validation is `test -f {file}` fails the rule. Stops stubs and placeholders from passing the build gate.
1843
+ - **Tool budgets** across 3 open-ended agents: researcher (3 Context7 + 3 WebFetch + 2 WebSearch per dimension), verifier (25 bash/grep per invocation), plan-checker (10 per invocation), qualia-debug (10 Read/Grep/Bash). Enforces INSUFFICIENT EVIDENCE return over speculative output when budget exhausted.
1844
+ - **Frontend gate on verifier's Design Verification section** (`agents/verifier.md`). Grep the phase plan for `.tsx`/`.jsx`/`.css`/`Persona:\s*(frontend|ux)` first — if absent, skip the ~40-command design verification block entirely. Saves substantial time on backend-only phases.
1845
+ - **`<wave_context>` block in builder prompts** (`skills/qualia-build/SKILL.md`). Lists sibling tasks in the same wave (title + files only, ~50 tokens per task) so parallel builders don't make conflicting semantic choices on shared types or patterns.
1846
+ - **Evidence citation requirement for milestone suggestions** (`agents/research-synthesizer.md`). Every arc entry must cite `[DIMENSION.md: <finding>]`. Speculative milestones marked `[speculative — no source]`.
1847
+ - **Parallel Agent fan-out in `qualia-design`** for >5 target files. Batches of 5, one Agent per batch, all dispatched in a single response turn. Post-fix verification greps catch reverted anti-patterns (`outline:none` without replacement, generic fonts, `max-w-7xl`, missing alt, blue-purple gradients).
1848
+ - **Parallelized security scans in `qualia-review`.** Independent greps now explicitly dispatched as parallel Bash calls in one turn. Saves 15-30s on large codebases.
1849
+ - **Typed input contracts across 7 agents** (planner, plan-checker, builder, verifier, researcher, qa-browser, roadmapper). Replaces prose "You receive: X + Y" with `<variable>` blocks + types + sources. Catches missing inputs at prompt-assembly time instead of mid-execution.
1850
+ - **`<full_detail>` declared in roadmapper Input section.** Was a ghost parameter referenced in the body but never declared — orchestrator had no mechanism to pass it.
1851
+ - **Cache-aware prompt structure in `qualia-build`.** Split `<phase_context>` (PROJECT.md/DESIGN.md, phase-stable) from `<task_context>` (per-task @files, varies). Stable prefix first, dynamic last — preserves Anthropic prompt-caching prefix-hit across parallel wave tasks (docs report 92% hit rate + 81% cost reduction at Claude Code scale when prefix is byte-identical).
1852
+ - **Research reports in `docs/research/`** documenting the analysis: `2026-04-21-command-quality-deep-research.md` (15-item synthesis from 4 parallel Opus audits) and `2026-04-21-industry-best-practices.md` (255 lines, cited sources on prompt caching, verification loops, hallucination reduction, multi-agent orchestration).
1853
+
1854
+ ### Changed
1855
+
1856
+ - **Plan-checker revision loop capped at 2 iterations** (was 3). Amazon/NeurIPS 2025 measured reflection gains at 74%→86% for 1 round, only 88% for 3 rounds — iteration 3 added 2pp over iteration 1, not worth the extra planner spawn. Updated `qualia-plan/SKILL.md`, `plan-checker.md`, and all stale "3 cycles" references.
1857
+ - **`qualia-review` scoring replaced subjective thresholds with deterministic formula.** Quick-reference table rewritten to match the computed formula (earlier drafts had inconsistent boundary rules — verified mechanically during release QA and corrected).
1858
+ - **Verifier now receives PROJECT.md inlined in its spawn prompt.** Previously blind to project conventions — Quality scoring rubric referenced "project conventions" but verifier had no way to read them.
1859
+ - **Wave dispatch explicitly parallel in `qualia-build/SKILL.md`.** Replaced "parallel if multiple" language with an explicit instruction: spawn all wave tasks as separate `Agent()` calls in the SAME response turn — do NOT await one before the next. Prior natural-language phrasing relied on harness behavior rather than enforcing true concurrency.
1860
+ - **`qualia-debug` rewritten from interactive to investigative one-shot.** Previously required 4 mandatory user questions and a diagnosis-confirmation gate before any investigation. Now parses symptom from `$ARGUMENTS`, runs diagnostic grep batches (general/frontend/perf modes), hard 10-call tool budget, INSUFFICIENT EVIDENCE return instead of speculative fixes, structured DEBUG-{timestamp}.md report output to `.planning/`. Matches the one-shot pattern of every other `/qualia-*` command.
1861
+ - **`qualia-design` critique section now uses the structured Design Quality Rubric** (File | Dimension | Issue | Line | Severity) instead of vibes-based evaluation. Any dimension scoring below 4 is a mandatory fix.
1862
+
1863
+ ### Fixed
1864
+
1865
+ - **Latent `grep -qL` bug in `qualia-review` API auth check.** The combination of `-q` (quiet) and `-L` (list non-matching files) is undefined in POSIX and was producing inverted "UNPROTECTED" output. Rewrote as a clean `if ! grep -q ... then echo UNPROTECTED` loop. Verified against mock directory of protected + unprotected routes.
1866
+ - **Full `npx next build` removed from `qualia-review` Performance Scan.** A 30-120s side-effectful build triggered during a "scan" command was a hidden cost that made review surprisingly slow and polluted `.next/`. Replaced with `du -sh .next/static/chunks/*.js` against existing build artifacts, with a warning if no build output exists.
1867
+
1868
+ ### Notes
1869
+
1870
+ - **Always pin `@latest` when upgrading.** npx caches at `~/.npm/_npx/` and has no time-based TTL, so `npx qualia-framework install` can silently re-run a cached old copy. Use `npx qualia-framework@latest install` (or `npx clear-npx-cache` first). README updated to reflect this. ([npm/rfcs#700](https://github.com/npm/rfcs/issues/700))
1871
+ - Users who update the framework must re-run the install script so `~/.claude/rules/grounding.md` lands — every skill's spawn prompt now references this file.
1872
+ - Any client projects mid-phase where the plan-checker was on iteration 3 will now escalate at iteration 2. Acceptable trade-off per the measured reflection-gain data.
1873
+ - The builder Output Contract (`DONE/BLOCKED/PARTIAL`) is advisory today — existing orchestrator skills do not programmatically parse it. Enforcement will land in a follow-up minor when the parsing is wired through.
1874
+
1875
+ ### Deferred to v4.2.0
1876
+
1877
+ - Mechanical-fix bypass in plan-checker (skip planner re-spawn for frontmatter/wave-assignment issues — ~4 hrs orchestration work, regression risk not suitable for this release).
1878
+ - Pre-Build Context Packet (single JSON consolidating PROJECT.md + DESIGN.md + plan + wave-context before spawning any builders).
1879
+ - Intra-wave task verification (run task Validation contracts immediately after each builder completes, before next wave starts).
1880
+ - New agents: migrator, dependency-auditor, rollback.
1881
+ - `curl` fallback in qa-browser for environments without Playwright MCP.
1882
+
1883
+ ## [4.0.5] — 2026-04-19
1884
+
1885
+ **Statusline refresh.** The phase segment now shows milestone + tasks +
1886
+ blockers (not just phase number), and the line closes with a
1887
+ `⬢ Qualia · {firstName}` signature pulled from
1888
+ `~/.claude/.qualia-config.json`. Static `hooks N` / `skills N` counters
1889
+ removed — they never changed between projects, so they added noise
1890
+ without signal. All 168 tests still green.
1891
+
1892
+ ### Added
1893
+
1894
+ - **`bin/statusline.js` — milestone segment.** When
1895
+ `.planning/tracking.json` has `milestone` + `milestone_name`, the
1896
+ statusline renders `M{n}·{shortName}` (name truncated to 14 chars)
1897
+ before the phase number. Previously only the phase number (`P1/3`)
1898
+ was visible — milestone context had to be looked up manually.
1899
+ - **`bin/statusline.js` — task progress.** When `tasks_total > 0`,
1900
+ renders `T{done}/{total}` alongside the phase. Gives mid-phase
1901
+ progress at a glance during `/qualia-build` waves.
1902
+ - **`bin/statusline.js` — blocker badge.** When
1903
+ `tracking.json.blockers` is a non-empty array, renders `!{n}` in
1904
+ red. Intentionally loud — blockers should never sit unnoticed.
1905
+ - **`bin/statusline.js` — Qualia signature.** Line 2 now ends with
1906
+ `⬢ Qualia · {firstName}` where `firstName` is the first whitespace-
1907
+ delimited token of `installed_by` in `~/.claude/.qualia-config.json`.
1908
+ Branded closer, makes the statusline feel like ours, not a generic
1909
+ Claude Code tool.
1910
+
1911
+ ### Removed
1912
+
1913
+ - **`bin/statusline.js` — hooks/skills counters.** The `hooks N`
1914
+ and `skills N` indicators were removed from line 1. Both counts are
1915
+ effectively static across all projects on a single machine (a given
1916
+ install has the same hooks and skills everywhere), so they were
1917
+ visual noise — they didn't help the employee understand *this*
1918
+ project's state. `mem N` is retained because it genuinely varies
1919
+ per project (different memories accumulated per working directory).
1920
+
1921
+ ## [4.0.4] — 2026-04-18
1922
+
1923
+ **Audit follow-up + ERP integration upgrade.** Eight concrete improvements
1924
+ from the framework deep-dive audit. Tests: 164 → 168 (+4 regression tests,
1925
+ covering the new `next-report-id` subcommand and the JOURNEY.md
1926
+ pre-populate on `close-milestone`).
1927
+
1928
+ ### Added
1929
+
1930
+ - **`qualia-framework erp-ping`** — new CLI subcommand that POSTs a
1931
+ synthetic `dry_run: true` payload to the ERP and prints HTTP code,
1932
+ response body, and the ERP-returned `report_id`. Single-command
1933
+ connectivity + key-validity + endpoint health check. Aliased as `ping`.
1934
+ - **`QS-REPORT-NN` client-side identifiers** — every session report
1935
+ now carries a stable, sequential client ID (`QS-REPORT-01`, `-02`, …
1936
+ per project) stored in `tracking.json.report_seq` and sent to the ERP
1937
+ in a new `client_report_id` field. Survives retries, survives UUID
1938
+ changes on the ERP side, is the preferred dedupe key going forward.
1939
+ - **`state.js next-report-id [--peek]`** — new mutator subcommand that
1940
+ increments `report_seq` and returns the next `QS-REPORT-NN`. `--peek`
1941
+ returns without incrementing (for `/qualia-report --dry-run`).
1942
+ - **`/qualia-report --dry-run`** — assemble + print the payload but
1943
+ skip the POST, skip the git commit, and peek the sequence counter
1944
+ without consuming one. Useful for previewing before a real clock-out.
1945
+ - **`/qualia-report` now retries with backoff** — 3 attempts at 1s, 3s,
1946
+ 9s on transient failures (timeout, 5xx, network). 401/422 are
1947
+ permanent failures and fail fast. Local report commit is unchanged —
1948
+ no data loss on upload failure, just a stale ERP view until retry.
1949
+ - **`/qualia-report` now displays both IDs on success** — "Uploaded as
1950
+ QS-REPORT-03 (ERP: {uuid})". Employees and the ERP share the same
1951
+ stable reference.
1952
+ - **`/qualia-new --full-detail`** — new flag that instructs the
1953
+ roadmapper to write full phase-level detail for EVERY milestone
1954
+ upfront (not just M1). Default behavior (progressive detail)
1955
+ unchanged. `agents/roadmapper.md` honors `<full_detail>` in its
1956
+ prompt contract.
1957
+ - **Visible progressive-detail notice** — after journey approval,
1958
+ `/qualia-new` now explicitly tells the user "Milestone 1 is fully
1959
+ planned. M2..M{N-1} are sketched. Full detail fills in when
1960
+ /qualia-milestone opens each one." Previously only in template
1961
+ comments — easy for a new team member to miss.
1962
+
1963
+ ### Fixed
1964
+
1965
+ - `bin/state.js` `close-milestone` now reads `.planning/JOURNEY.md` to
1966
+ pre-populate `tracking.json.milestone_name` with the next milestone's
1967
+ name. Previously, between `close-milestone` and the next
1968
+ `state.js init --force` from the roadmapper, `milestone_name` sat
1969
+ blank — the ERP tree view would briefly show an unnamed milestone.
1970
+ Falls back to blank if JOURNEY.md is missing (legacy projects, pre-v4).
1971
+ - `bin/cli.js` — `QUALIA_AGENT_FILES` expanded from 4 to all 8 agents
1972
+ (`planner`, `builder`, `verifier`, `qa-browser`, **`plan-checker`**,
1973
+ **`researcher`**, **`research-synthesizer`**, **`roadmapper`**).
1974
+ `qualia-framework uninstall` would previously leave the last 4 on
1975
+ disk as orphans.
1976
+ - `bin/cli.js` `cmdMigrate` — removed `block-env-edit.js` from
1977
+ `requiredEditHooks`. That hook was deleted in v3.2.0 and
1978
+ `install.js` actively purges it; `migrate` was trying to wire a
1979
+ non-existent file into `settings.json`.
1980
+ - `bin/install.js` + `bin/cli.js` — unpinned
1981
+ `next-devtools-mcp@0.3.10` → `@latest`. The pin was silent drift.
1982
+ - `bin/install.js` — warn (instead of OK) when an existing
1983
+ `~/.claude/.erp-api-key` is under 10 bytes. Clearly truncated or
1984
+ placeholder keys no longer silently pass install. Real bearer tokens
1985
+ are ≥ 20 bytes; the threshold is deliberately loose to avoid false
1986
+ positives.
1987
+
1988
+ ### Changed
1989
+
1990
+ - `templates/tracking.json` — new field `report_seq: 0`.
1991
+ - `docs/erp-contract.md` — documented `client_report_id` (recommended)
1992
+ and `dry_run` (optional) on the POST payload.
1993
+
1994
+ ### Tests
1995
+
1996
+ - 164 → 168 (+4). New coverage: `next-report-id` increments,
1997
+ `next-report-id --peek` is side-effect-free, `close-milestone`
1998
+ pre-populates `milestone_name` from JOURNEY.md, and the fallback
1999
+ path when JOURNEY.md is absent.
2000
+
2001
+ ## [4.0.3] — 2026-04-18
2002
+
2003
+ **Zero-deferral release.** Closes the last two items that were previously
2004
+ deferred as trade-offs.
2005
+
2006
+ ### Fixed
2007
+
2008
+ - `hooks/pre-compact.js`: `--no-verify` and `--no-gpg-sign` are now
2009
+ configurable via `~/.claude/.qualia-config.json`:
2010
+
2011
+ ```json
2012
+ {
2013
+ "pre_compact": {
2014
+ "respect_user_hooks": true,
2015
+ "respect_gpg_signing": true
2016
+ }
2017
+ }
2018
+ ```
2019
+
2020
+ Default behavior is unchanged (bot commits bypass both, because
2021
+ compaction can fire at any moment and pre-commit test suites would
2022
+ routinely block the auto-save and lose STATE.md). Compliance-sensitive
2023
+ projects opt into strict mode per-flag. The flags used are included
2024
+ in the hook trace.
2025
+
2026
+ ### Added
2027
+
2028
+ - **All 26 skills now declare `allowed-tools`** in frontmatter. Per-skill
2029
+ conservative tool unions — wider rather than narrower to avoid
2030
+ breakage. Read-only skills (`qualia-help`, `qualia-resume`) declare
2031
+ it explicitly. The framework no longer relies on the user's default
2032
+ permission mode for tool scoping.
2033
+
2034
+ ## [4.0.2] — 2026-04-18
2035
+
2036
+ **Stability pass.** Closes every remaining HIGH + MEDIUM item from the
2037
+ v4.0.0 audit that could surface as a silent failure or instability.
2038
+ Tests: 159 → 164 (+5 regression tests).
2039
+
2040
+ ### Fixed — HIGH
2041
+
2042
+ - `hooks/session-start.js`: `readConfig()` now defined above its call
2043
+ site. Previously worked by function-declaration hoisting — would have
2044
+ silently broken on any refactor to `const readConfig = …`.
2045
+ - `bin/state.js`: write-ahead journal (`.planning/.state.journal`)
2046
+ captures the pre-transition snapshot of STATE.md + tracking.json
2047
+ before the dual write. On next mutator invocation, if the journal
2048
+ exists we recover both files to the pre-transition state. A crashed
2049
+ mutator (SIGKILL / power loss between the two renames) no longer
2050
+ leaves the pair inconsistent. A corrupt journal is cleared, not fatal.
2051
+
2052
+ ### Fixed — MEDIUM
2053
+
2054
+ - `hooks/migration-guard.js`: DELETE / UPDATE `WHERE` scan is now
2055
+ per-statement (split on `;`) instead of file-global. A file
2056
+ containing `DELETE FROM foo;` followed by any later `… WHERE …`
2057
+ (in a SELECT, JOIN, etc.) would previously pass the check.
2058
+ - `hooks/migration-guard.js`: stdin read retry loop now sleeps 1ms
2059
+ between EAGAIN retries via `Atomics.wait` instead of spinning CPU.
2060
+ - `hooks/pre-push.js`: commit-failure path now unstages tracking.json
2061
+ and restores the working-tree copy, so the user's next manual commit
2062
+ isn't polluted by an aborted ERP-stamp change.
2063
+ - `bin/cli.js` — `cleanSettingsJson`: iterates ALL hook-event keys in
2064
+ settings.json instead of the hardcoded three (SessionStart /
2065
+ PreToolUse / PreCompact). Future hook events get cleaned automatically.
2066
+ - `bin/cli.js` — hook cleanup: introduce `QUALIA_LEGACY_HOOK_FILES`
2067
+ for removed-in-past-version hook filenames (currently
2068
+ `block-env-edit.js`). Uninstall cleans legacy hooks too.
2069
+ - `bin/statusline.js`: memory-path `dirKey` now strips BOTH `/` and `\`
2070
+ so Windows installs get a correct project key and the memory count
2071
+ actually renders.
2072
+
2073
+ ### Tests
2074
+
2075
+ - +5 regression tests:
2076
+ · state.js recovers STATE.md + tracking.json from `.state.journal`
2077
+ · state.js: corrupt `.state.journal` is cleared without crashing
2078
+ · migration-guard: `DELETE FROM x; SELECT … WHERE …;` still blocks
2079
+ · migration-guard: `UPDATE … SET …; SELECT … WHERE …;` still blocks
2080
+ · install.js: reinstall preserves user-added hooks in settings.json
2081
+
2082
+ ## [4.0.1] — 2026-04-18
2083
+
2084
+ **Post-v4.0.0 audit cleanup.** No behavior changes on the happy path —
2085
+ all fixes patch latent bugs, silent failure modes, and documentation
2086
+ drift found in a full-framework audit. Tests grew from 156 to 159.
2087
+
2088
+ ### Fixed — ship-blockers
2089
+
2090
+ - `bin/qualia-ui.js`: `/qualia` journey-tree no longer crashes when
2091
+ `JOURNEY.md` lacks a `project:` frontmatter line. A `const projectName`
2092
+ was shadowing the function name inside its own initializer, triggering
2093
+ `ReferenceError: Cannot access 'projectName' before initialization`.
2094
+ - `templates/help.html`: version pill, subtitle, and footer now render
2095
+ the real installed version. Previously hardcoded `v3.6.0` in three
2096
+ places, and the `sed "s/{{VERSION}}/$VERSION/g"` in `/qualia-help`
2097
+ had nothing to replace.
2098
+ - `skills/qualia-help/SKILL.md`: version fallback chain rewritten —
2099
+ `.qualia-config.json` → `package.json` → `"latest"`. Previously
2100
+ fell back to the string `"v3"`.
2101
+ - `skills/qualia-design/SKILL.md` + `rules/frontend.md`: remove references
2102
+ to 5 non-existent design skills (`/bolder`, `/design-quieter`,
2103
+ `/colorize`, `/distill`, `/delight`). The rules file ships to every
2104
+ user project; the ghost commands would have 404'd.
2105
+ - `CLAUDE.md`: Road section rewritten to describe the v4 hierarchy.
2106
+ Previously no mention of milestones, `JOURNEY.md`, `/qualia-milestone`,
2107
+ `/qualia-idk`, or `--auto` — the file Claude reads every session was
2108
+ still on v3 mental model.
2109
+ - `CHANGELOG.md`: add link references for v3.1.0 through v4.0.0 and
2110
+ point `[Unreleased]` at v4.0.0. Previous version headers rendered
2111
+ as plain text on GitHub / npm.
2112
+
2113
+ ### Fixed — real bugs
2114
+
2115
+ - `hooks/pre-deploy-gate.js`: exits **2** (not 1) on block, matching
2116
+ Claude Code's PreToolUse hook contract. Previous code explicitly
2117
+ acknowledged the violation in a comment. Test assertions updated in
2118
+ `tests/runner.js` and `tests/hooks.test.sh`.
2119
+ - `bin/state.js` — lock: replace 50ms CPU busy-wait with
2120
+ `Atomics.wait`-backed `sleepSync` (no CPU starvation on constrained
2121
+ CI runners). Lock fall-through now traces `state-lock/fallthrough`
2122
+ so repeated contention is visible instead of silent.
2123
+ - `bin/state.js` — `cmdTransition`: back up BOTH `STATE.md` and
2124
+ `tracking.json` before the dual write, so a failure in the second
2125
+ write can roll both files back to a consistent pre-transition state.
2126
+ - `bin/install.js`: hooks are now merged into `settings.json` instead
2127
+ of clobbered. Previous code did `settings.hooks = {...}`, silently
2128
+ destroying any user-added hook entries on every reinstall.
2129
+ Qualia-owned hook commands are matched by filename and replaced;
2130
+ everything else is preserved.
2131
+
2132
+ ### Fixed — docs / drift
2133
+
2134
+ - `agents/plan-checker.md`: Rule 2 heading "6 mandatory fields" →
2135
+ "7 mandatory fields" (list contained 7).
2136
+ - `skills/qualia-task/SKILL.md` + `skills/qualia-plan/SKILL.md`:
2137
+ legacy `Done when:` → `Acceptance Criteria:` (matches v3.7.0 story-file
2138
+ format that plan-checker validates against).
2139
+ - `docs/erp-contract.md`: add v4 fields `milestone_name` and
2140
+ `milestones[]` to the request body example and required-fields table.
2141
+ `/qualia-report` already sent these; the contract doc didn't document
2142
+ them.
2143
+ - `guide.md`: "The 10 Commands" → "The Road Commands" (table has 13 rows).
2144
+ - `skills/qualia-new/SKILL.md`: strip stale "Unlike v3" language.
2145
+
2146
+ ### Tests
2147
+
2148
+ - +3 new regression tests (156 → 159):
2149
+ · `transition --to shipped` actually increments `deploy_count`
2150
+ · `qualia-ui journey-tree` renders milestones without crashing
2151
+ · `qualia-ui journey-tree` falls back to `projectName()` when
2152
+ `JOURNEY.md` frontmatter lacks `project:`
2153
+
2154
+ ### Deferred to v4.1
2155
+
2156
+ - `allowed-tools` frontmatter sweep across 26 skills — requires
2157
+ per-skill audit to avoid accidentally blocking tool access that
2158
+ skills rely on.
2159
+ - Finer-grained per-statement `WHERE`-clause scan in
2160
+ `migration-guard.js` / `pre-deploy-gate.js`.
2161
+
2162
+ ## [4.0.0] — 2026-04-18
2163
+
2164
+ **Full Journey release.** `/qualia-new` now maps the entire project
2165
+ arc from kickoff to client handoff upfront, and the Road can chain
2166
+ itself end-to-end in `--auto` mode with only two human gates per
2167
+ project. The milestone / phase / task hierarchy is locked down so the
2168
+ ERP renders a clean tree, and the team stops improvising milestones
2169
+ after each ship.
2170
+
2171
+ ### The big shift
2172
+
2173
+ Before v4, `/qualia-new` produced a v1 ROADMAP and stopped. Each
2174
+ subsequent milestone was invented when the previous one shipped,
2175
+ leading to structural drift (milestones collapsing into single
2176
+ phases, "Phase 0" entries at milestone level, skipped milestone
2177
+ numbers). The ERP rendered a flat list of heterogeneous entries.
2178
+
2179
+ v4 treats the **Journey** as a first-class artifact:
2180
+
2181
+ ```
2182
+ Project
2183
+ └─ Journey (all milestones defined upfront)
2184
+ └─ Milestone (a release — 2-5 total, Handoff is always last)
2185
+ └─ Phase (a feature-sized deliverable, 2-5 tasks)
2186
+ └─ Task (atomic unit, one commit, verification contract)
2187
+ ```
2188
+
2189
+ ### Added
2190
+
2191
+ - **`.planning/JOURNEY.md`** — the North Star document. Lists every
2192
+ milestone with why-now, exit criteria, and phase sketches. Written
2193
+ during `/qualia-new`, updated on milestone closure. Hard rules: 2-5
2194
+ milestones, ≥ 2 phases per non-Handoff milestone, final milestone
2195
+ is always literally named "Handoff" with the fixed 4-phase template
2196
+ (Polish, Content + SEO, Final QA, Handoff).
2197
+ - **`/qualia-new` full-journey flow** — produces JOURNEY.md +
2198
+ REQUIREMENTS.md (grouped by milestone) + ROADMAP.md (M1's phase
2199
+ detail). **Research runs unconditionally** (no more `workflow.research`
2200
+ gate). **Single approval** on the whole journey replaces multiple
2201
+ mid-flow gates.
2202
+ - **`--auto` flag on `/qualia-new`, `/qualia-plan`, `/qualia-build`,
2203
+ `/qualia-verify`, `/qualia-milestone`** — chains the Road end-to-end.
2204
+ Two human gates per project total: journey approval at kickoff, and
2205
+ one pause at each milestone boundary ("Continue to M{N+1}?"). One
2206
+ halt case: gap-cycle limit exceeded on a failed phase.
2207
+ - **Milestone readiness guards** in `state.js close-milestone`:
2208
+ `MILESTONE_NOT_READY` (any phase not verified) and `MILESTONE_TOO_SMALL`
2209
+ (< 2 phases), both bypassable with `--force`.
2210
+ - **`tracking.json.milestones[]`** — array of closed milestone summaries
2211
+ (num, name, total_phases, phases_completed, tasks_completed,
2212
+ shipped_url, closed_at). The ERP uses this to render the project
2213
+ tree without replaying git history.
2214
+ - **`tracking.json.milestone_name`** — human name of the current
2215
+ milestone ("Foundation", "Core Features", etc.). Appears in status
2216
+ bar and ERP.
2217
+ - **`build_count` and `deploy_count` bump automatically** on every
2218
+ `built` and `shipped` transition. Previously always zero.
2219
+ - **Pre-inline context at builder dispatch.**
2220
+ `/qualia-build` reads PROJECT.md, DESIGN.md, and every `@file`
2221
+ referenced in the task's Context BEFORE spawning the builder subagent.
2222
+ Inlines them under `<pre-loaded-context>`. Saves 3-5 Read tool calls
2223
+ per task; builder starts already oriented.
2224
+ - **`qualia-ui.js journey-tree`** — ASCII ladder visualization of
2225
+ JOURNEY.md. Shipped milestones = green dot, current = teal diamond,
2226
+ future = dim open circle, Handoff = [FINAL] tag. Shown by
2227
+ `/qualia` router and at `/qualia-milestone` confirmation step.
2228
+ - **`qualia-ui.js milestone-complete`** — celebration banner on
2229
+ milestone closure. Distinguishes Handoff closure ("PROJECT SHIPPED")
2230
+ from intermediate milestones ("Next: {name}").
2231
+ - **5 new banner actions:** milestone ◆, journey ◯, auto ⚡,
2232
+ research ◱, roadmap ◐.
2233
+ - **`qualia-report` ERP payload updated** — now sends all v4 fields
2234
+ (project_id, team_id, git_remote, milestone_name, milestones[],
2235
+ build_count, deploy_count, session_started_at, last_pushed_at) so
2236
+ the ERP renders tree and dedupes correctly.
2237
+ - **`/qualia-idk` is now a real diagnostic skill**, not a `/qualia` alias.
2238
+ When the user's confusion is about *understanding the situation*
2239
+ (not picking the next command), it spawns two parallel isolated
2240
+ `Explore` subagents: one scans `.planning/` only, the other scans
2241
+ source code only. Each produces a 250-word view of its side. The
2242
+ main skill synthesizes both views + the user's stated confusion
2243
+ into a structured "What I see / What I think is happening / What
2244
+ to do next" diagnosis in plain language. Catches plan↔code drift
2245
+ that a state-only router can't see.
2246
+
2247
+ ### Changed
2248
+
2249
+ - **`/qualia-handoff` is now explicit about the 4 deliverables** —
2250
+ verified production URL, updated documentation, client assets archive,
2251
+ ERP finalization. Halts if URL is down or latency > 1s, or if
2252
+ `.planning/archive/` is empty (project bypassed `/qualia-milestone`
2253
+ and has no archived milestones).
2254
+ - **`/qualia-milestone` reads next milestone from JOURNEY.md** instead
2255
+ of asking the user to name it. Dedicated `journey-tree` visualization
2256
+ at confirmation + `milestone-complete` banner at close.
2257
+ - **`roadmapper` agent rewritten** to produce JOURNEY + REQUIREMENTS +
2258
+ ROADMAP. **Dropped** the old "no review/deploy/handoff phases" rule —
2259
+ the Handoff milestone is now a first-class feature milestone with
2260
+ the 4 standard phases and their own requirements (HAND-01..HAND-15
2261
+ in REQUIREMENTS.md).
2262
+ - **`plan-checker` Rule 2** — task story-file fields are mandatory
2263
+ (Why / Depends on / Acceptance Criteria / Validation). Inherited
2264
+ from v3.7.0's story-file format.
2265
+ - **`/qualia` description scoped back to mechanical state routing.**
2266
+ Previously claimed "idk / stuck / lost / confused" triggers; those
2267
+ interpretive shades now route to `/qualia-idk`. `/qualia` stays the
2268
+ fast mechanical router ("what's my next command").
2269
+ - **`templates/requirements.md`** — multi-milestone format with fixed
2270
+ Handoff section.
2271
+ - **`templates/roadmap.md`** — scoped to current milestone only, with
2272
+ pointer to JOURNEY.md for the full arc.
2273
+
2274
+ ### Tests
2275
+
2276
+ 150 → 156 green. +6 covering: MILESTONE_NOT_READY, MILESTONE_TOO_SMALL,
2277
+ milestones[] append idempotency, check-output exposure of milestones +
2278
+ milestone_name, milestone summary cumulative task count (not current-
2279
+ phase only), build_count bump on `built`.
2280
+
2281
+ ### Migration
2282
+
2283
+ Fully additive. Projects created on v3.x continue to work:
2284
+ - Plans without story-file fields: `state.js` accepts both legacy
2285
+ `Done when:` and v3.7.0 `Acceptance Criteria:` anchors.
2286
+ - tracking.json missing `milestones[]` or `milestone_name`: `ensureLifetime`
2287
+ hydrates them to `[]` and `""` with zero risk.
2288
+ - Projects without JOURNEY.md (legacy): `/qualia-milestone` falls back
2289
+ to asking the user for the next milestone name. Recommended migration:
2290
+ run `/qualia-map` then regenerate JOURNEY.md via the roadmapper, but
2291
+ not required.
2292
+
2293
+ ### Lineage of patterns
2294
+
2295
+ - **Story-file plan format** — embedded rationale and acceptance
2296
+ criteria per task (arrived in v3.7.0).
2297
+ - **State-machine auto-advance** — the `--auto` loop (arrived in v4.0.0).
2298
+ - **Pre-inline context at dispatch** — the builder `<pre-loaded-context>`
2299
+ block (arrived in v4.0.0).
2300
+ - **Journey-as-first-class-artifact** — JOURNEY.md (arrived in v4.0.0).
2301
+
2302
+ ---
2303
+
2304
+ _v2.x and v3.x history archived at [docs/archive/CHANGELOG-pre-v4.md](docs/archive/CHANGELOG-pre-v4.md)._