qualia-framework 5.9.1 → 6.2.7

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 (81) hide show
  1. package/AGENTS.md +2 -1
  2. package/CLAUDE.md +2 -1
  3. package/README.md +45 -29
  4. package/agents/builder.md +1 -5
  5. package/agents/plan-checker.md +1 -1
  6. package/agents/planner.md +2 -6
  7. package/agents/qa-browser.md +3 -3
  8. package/agents/roadmapper.md +2 -2
  9. package/agents/verifier.md +7 -9
  10. package/agents/visual-evaluator.md +1 -3
  11. package/bin/cli.js +370 -205
  12. package/bin/erp-retry.js +11 -3
  13. package/bin/install.js +383 -55
  14. package/bin/knowledge-flush.js +25 -13
  15. package/bin/knowledge.js +11 -1
  16. package/bin/project-snapshot.js +293 -0
  17. package/bin/qualia-ui.js +13 -2
  18. package/bin/report-payload.js +137 -0
  19. package/bin/slop-detect.mjs +81 -9
  20. package/bin/state.js +8 -1
  21. package/bin/statusline.js +14 -2
  22. package/docs/archive/CHANGELOG-pre-v4.md +855 -0
  23. package/docs/changelog-v6.html +864 -0
  24. package/docs/ecosystem-operating-model.md +121 -0
  25. package/docs/erp-contract.md +74 -21
  26. package/docs/onboarding.html +2 -2
  27. package/docs/release.md +44 -0
  28. package/docs/reviews/v6.2.1-revival-audit.md +53 -0
  29. package/docs/reviews/v6.2.2-memory-erp-audit.md +41 -0
  30. package/docs/reviews/v6.2.3-erp-id-guard.md +15 -0
  31. package/guide.md +28 -3
  32. package/hooks/auto-update.js +20 -10
  33. package/hooks/branch-guard.js +10 -2
  34. package/hooks/env-empty-guard.js +15 -5
  35. package/hooks/git-guardrails.js +10 -1
  36. package/hooks/migration-guard.js +4 -1
  37. package/hooks/pre-deploy-gate.js +11 -1
  38. package/hooks/pre-push.js +43 -106
  39. package/hooks/session-start.js +22 -14
  40. package/hooks/stop-session-log.js +11 -3
  41. package/hooks/supabase-destructive-guard.js +11 -1
  42. package/hooks/vercel-account-guard.js +12 -3
  43. package/package.json +4 -3
  44. package/qualia-design/design-reference.md +2 -1
  45. package/qualia-design/frontend.md +4 -4
  46. package/rules/one-opinion.md +59 -0
  47. package/rules/trust-boundary.md +35 -0
  48. package/skills/qualia-feature/SKILL.md +5 -5
  49. package/skills/qualia-flush/SKILL.md +5 -7
  50. package/skills/qualia-hook-gen/SKILL.md +1 -1
  51. package/skills/qualia-learn/SKILL.md +1 -0
  52. package/skills/qualia-map/SKILL.md +2 -1
  53. package/skills/qualia-milestone/SKILL.md +2 -2
  54. package/skills/qualia-new/SKILL.md +6 -6
  55. package/skills/qualia-optimize/SKILL.md +1 -1
  56. package/skills/qualia-plan/SKILL.md +1 -1
  57. package/skills/qualia-polish/REFERENCE.md +8 -6
  58. package/skills/qualia-polish/SKILL.md +11 -9
  59. package/skills/qualia-polish/scripts/loop.mjs +18 -6
  60. package/skills/qualia-postmortem/SKILL.md +1 -1
  61. package/skills/qualia-report/SKILL.md +6 -42
  62. package/skills/qualia-road/SKILL.md +17 -5
  63. package/skills/qualia-verify/SKILL.md +3 -3
  64. package/skills/qualia-vibe/SKILL.md +226 -0
  65. package/skills/qualia-vibe/scripts/extract.mjs +141 -0
  66. package/skills/qualia-vibe/scripts/tokens.mjs +342 -0
  67. package/templates/help.html +10 -3
  68. package/templates/knowledge/agents.md +3 -3
  69. package/templates/knowledge/index.md +1 -1
  70. package/templates/tracking.json +3 -0
  71. package/templates/work-packet.md +46 -0
  72. package/tests/bin.test.sh +423 -25
  73. package/tests/hooks.test.sh +1 -8
  74. package/tests/install-smoke.test.sh +137 -0
  75. package/tests/published-install-smoke.test.sh +126 -0
  76. package/tests/refs.test.sh +43 -1
  77. package/tests/run-all.sh +49 -0
  78. package/tests/runner.js +19 -33
  79. package/tests/slop-detect.test.sh +11 -5
  80. package/tests/state.test.sh +4 -1
  81. package/hooks/pre-compact.js +0 -125
@@ -0,0 +1,864 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Qualia Framework v6 — What changed</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,700&family=Newsreader:opsz,wght@6..72,400;6..72,500;6..72,600&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --bg: oklch(96.5% 0.012 78);
13
+ --bg-soft: oklch(94% 0.014 78);
14
+ --ink: oklch(22% 0.025 245);
15
+ --ink-soft: oklch(40% 0.025 245);
16
+ --muted: oklch(58% 0.018 245);
17
+ --rule: oklch(85% 0.02 78);
18
+ --rule-soft: oklch(90% 0.014 78);
19
+ --accent: oklch(52% 0.12 195);
20
+ --accent-d: oklch(38% 0.10 195);
21
+ --warn: oklch(58% 0.14 50);
22
+ --new: oklch(55% 0.14 145);
23
+ --fix: oklch(52% 0.14 25);
24
+ --tweak: oklch(48% 0.05 245);
25
+ --space-1: clamp(.25rem, .2rem + .25vw, .375rem);
26
+ --space-2: clamp(.5rem, .4rem + .5vw, .75rem);
27
+ --space-3: clamp(.75rem, .6rem + .75vw, 1.125rem);
28
+ --space-4: clamp(1rem, .8rem + 1vw, 1.5rem);
29
+ --space-5: clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem);
30
+ --space-6: clamp(2.25rem, 1.8rem + 2.25vw, 3.5rem);
31
+ --space-7: clamp(3.5rem, 2.8rem + 3.5vw, 5.25rem);
32
+ --display: "Fraunces", "Newsreader", Georgia, serif;
33
+ --body: "Newsreader", Georgia, serif;
34
+ --mono: "JetBrains Mono", ui-monospace, "SF Mono", monospace;
35
+ }
36
+ * { box-sizing: border-box; }
37
+ html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
38
+ body {
39
+ margin: 0;
40
+ background: var(--bg);
41
+ color: var(--ink);
42
+ font-family: var(--body);
43
+ font-size: clamp(15px, 14px + .25vw, 17px);
44
+ line-height: 1.55;
45
+ font-feature-settings: "kern", "liga", "ss01", "ss02";
46
+ }
47
+ main {
48
+ max-width: 64rem;
49
+ margin: 0 auto;
50
+ padding: var(--space-6) var(--space-4) var(--space-7);
51
+ }
52
+
53
+ /* Header */
54
+ .marque {
55
+ display: flex;
56
+ align-items: baseline;
57
+ gap: var(--space-3);
58
+ border-bottom: 1px solid var(--rule);
59
+ padding-bottom: var(--space-3);
60
+ margin-bottom: var(--space-6);
61
+ }
62
+ .marque .mark {
63
+ font-family: var(--mono);
64
+ font-size: .75rem;
65
+ letter-spacing: .14em;
66
+ text-transform: uppercase;
67
+ color: var(--accent);
68
+ }
69
+ .marque .title {
70
+ font-family: var(--mono);
71
+ font-size: .75rem;
72
+ letter-spacing: .14em;
73
+ text-transform: uppercase;
74
+ color: var(--ink-soft);
75
+ }
76
+ .marque .meta {
77
+ font-family: var(--mono);
78
+ font-size: .75rem;
79
+ color: var(--muted);
80
+ margin-left: auto;
81
+ }
82
+
83
+ /* Hero */
84
+ .hero { margin-bottom: var(--space-7); }
85
+ .hero h1 {
86
+ font-family: var(--display);
87
+ font-weight: 500;
88
+ font-size: clamp(2.5rem, 1.5rem + 5vw, 5.25rem);
89
+ line-height: .95;
90
+ letter-spacing: -.025em;
91
+ margin: 0 0 var(--space-3);
92
+ font-variation-settings: "opsz" 144;
93
+ }
94
+ .hero h1 em {
95
+ font-style: italic;
96
+ color: var(--accent);
97
+ font-weight: 400;
98
+ }
99
+ .hero .lede {
100
+ font-family: var(--display);
101
+ font-weight: 400;
102
+ font-size: clamp(1.125rem, 1rem + .5vw, 1.5rem);
103
+ line-height: 1.45;
104
+ max-width: 50ch;
105
+ color: var(--ink-soft);
106
+ margin: 0;
107
+ }
108
+ .hero .stats {
109
+ display: flex;
110
+ gap: var(--space-5);
111
+ margin-top: var(--space-5);
112
+ flex-wrap: wrap;
113
+ }
114
+ .stat {
115
+ font-family: var(--mono);
116
+ font-size: .8rem;
117
+ color: var(--muted);
118
+ }
119
+ .stat strong {
120
+ display: block;
121
+ font-family: var(--display);
122
+ font-weight: 500;
123
+ font-size: 1.75rem;
124
+ color: var(--ink);
125
+ margin-bottom: .15em;
126
+ }
127
+
128
+ /* Release */
129
+ .release {
130
+ border-top: 1px solid var(--rule);
131
+ padding-top: var(--space-5);
132
+ margin-top: var(--space-6);
133
+ }
134
+ .release-head {
135
+ display: flex;
136
+ align-items: baseline;
137
+ gap: var(--space-3);
138
+ margin-bottom: var(--space-4);
139
+ flex-wrap: wrap;
140
+ }
141
+ .release-version {
142
+ font-family: var(--display);
143
+ font-weight: 500;
144
+ font-size: clamp(1.75rem, 1.4rem + 1.5vw, 2.75rem);
145
+ line-height: 1;
146
+ letter-spacing: -.02em;
147
+ color: var(--ink);
148
+ margin: 0;
149
+ }
150
+ .release-tagline {
151
+ font-family: var(--display);
152
+ font-style: italic;
153
+ color: var(--accent);
154
+ font-size: clamp(1rem, .9rem + .4vw, 1.25rem);
155
+ }
156
+ .release-date {
157
+ font-family: var(--mono);
158
+ font-size: .75rem;
159
+ color: var(--muted);
160
+ margin-left: auto;
161
+ letter-spacing: .08em;
162
+ }
163
+ .release-intro {
164
+ font-family: var(--display);
165
+ font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
166
+ line-height: 1.55;
167
+ color: var(--ink-soft);
168
+ max-width: 60ch;
169
+ margin: 0 0 var(--space-5);
170
+ }
171
+
172
+ /* Sections within a release */
173
+ .change-group { margin-bottom: var(--space-5); }
174
+ .change-group h3 {
175
+ font-family: var(--mono);
176
+ font-size: .7rem;
177
+ letter-spacing: .14em;
178
+ text-transform: uppercase;
179
+ color: var(--muted);
180
+ margin: 0 0 var(--space-3);
181
+ padding-bottom: var(--space-2);
182
+ border-bottom: 1px solid var(--rule-soft);
183
+ }
184
+
185
+ /* Change card */
186
+ .change {
187
+ padding: var(--space-3) 0;
188
+ border-bottom: 1px solid var(--rule-soft);
189
+ }
190
+ .change:last-child { border-bottom: none; }
191
+ .change-head {
192
+ display: flex;
193
+ align-items: baseline;
194
+ gap: var(--space-2);
195
+ margin-bottom: var(--space-2);
196
+ flex-wrap: wrap;
197
+ }
198
+ .badge {
199
+ font-family: var(--mono);
200
+ font-size: .65rem;
201
+ letter-spacing: .12em;
202
+ text-transform: uppercase;
203
+ padding: .15em .55em;
204
+ border: 1px solid currentColor;
205
+ border-radius: 2px;
206
+ flex-shrink: 0;
207
+ }
208
+ .badge.new { color: var(--new); }
209
+ .badge.fix { color: var(--fix); }
210
+ .badge.tweak { color: var(--tweak); }
211
+ .change-title {
212
+ font-family: var(--display);
213
+ font-weight: 500;
214
+ font-size: clamp(1.125rem, 1rem + .35vw, 1.35rem);
215
+ line-height: 1.25;
216
+ color: var(--ink);
217
+ margin: 0;
218
+ }
219
+ .change-body {
220
+ font-family: var(--body);
221
+ line-height: 1.55;
222
+ color: var(--ink-soft);
223
+ margin: 0 0 var(--space-2);
224
+ }
225
+ .change-body code {
226
+ font-family: var(--mono);
227
+ font-size: .85em;
228
+ background: var(--bg-soft);
229
+ padding: .1em .35em;
230
+ border-radius: 2px;
231
+ color: var(--ink);
232
+ }
233
+ .change pre {
234
+ font-family: var(--mono);
235
+ font-size: .8rem;
236
+ line-height: 1.5;
237
+ background: var(--ink);
238
+ color: oklch(92% 0.012 78);
239
+ padding: var(--space-3) var(--space-4);
240
+ border-radius: 4px;
241
+ margin: var(--space-3) 0 0;
242
+ overflow-x: auto;
243
+ }
244
+ .change pre .comment { color: oklch(58% 0.018 245); }
245
+
246
+ /* Migration */
247
+ .migration {
248
+ margin-top: var(--space-6);
249
+ padding: var(--space-5);
250
+ background: var(--bg-soft);
251
+ border-left: 3px solid var(--accent);
252
+ }
253
+ .migration h2 {
254
+ font-family: var(--display);
255
+ font-weight: 500;
256
+ font-size: clamp(1.5rem, 1.3rem + .8vw, 2rem);
257
+ margin: 0 0 var(--space-3);
258
+ color: var(--ink);
259
+ }
260
+ .migration p {
261
+ font-family: var(--display);
262
+ color: var(--ink-soft);
263
+ margin: 0 0 var(--space-3);
264
+ }
265
+ .migration pre {
266
+ font-family: var(--mono);
267
+ font-size: .85rem;
268
+ line-height: 1.6;
269
+ background: var(--ink);
270
+ color: oklch(92% 0.012 78);
271
+ padding: var(--space-3) var(--space-4);
272
+ border-radius: 4px;
273
+ margin: 0;
274
+ overflow-x: auto;
275
+ }
276
+
277
+ /* Footer */
278
+ footer {
279
+ margin-top: var(--space-7);
280
+ padding-top: var(--space-4);
281
+ border-top: 1px solid var(--rule);
282
+ font-family: var(--mono);
283
+ font-size: .75rem;
284
+ color: var(--muted);
285
+ display: flex;
286
+ justify-content: space-between;
287
+ flex-wrap: wrap;
288
+ gap: var(--space-3);
289
+ }
290
+ footer a {
291
+ color: var(--accent);
292
+ text-decoration: none;
293
+ }
294
+ footer a:hover { text-decoration: underline; }
295
+ </style>
296
+ </head>
297
+ <body>
298
+ <main>
299
+
300
+ <header class="marque">
301
+ <span class="mark">Qualia Framework</span>
302
+ <span class="title">Changelog · v6</span>
303
+ <span class="meta">2026-05-21</span>
304
+ </header>
305
+
306
+ <section class="hero">
307
+ <h1>v6.2.6 <em>Project snapshot upload.</em></h1>
308
+ <p class="lede">
309
+ Nine v6 releases. Zero new flagship feature in v6.0 (audit + cleanup of the whole surface).
310
+ One real new tool in v6.1 (<code>/qualia-vibe</code> for fast aesthetic pivots).
311
+ v6.2 removes hook-created bot commits. v6.2.1 guards the active surfaces so stale claims cannot return.
312
+ v6.2.2 makes the Framework/Memory/ERP boundary explicit for admin and employee tracking.
313
+ v6.2.3 guards ERP UUID fields so slug-like local IDs cannot break report uploads.
314
+ v6.2.4 turns that payload contract into a shipped, tested script.
315
+ v6.2.5 adds an explicit project-level snapshot for ERP/admin 0-to-100 tracking.
316
+ v6.2.6 uploads that snapshot to ERP's project intake.
317
+ </p>
318
+ <div class="stats">
319
+ <div class="stat"><strong>33</strong>skills (was 32)</div>
320
+ <div class="stat"><strong>8</strong>rules (was 6)</div>
321
+ <div class="stat"><strong>513</strong>tests passing (was 489)</div>
322
+ <div class="stat"><strong>~500</strong>tokens saved per phase</div>
323
+ <div class="stat"><strong>851</strong>changelog lines archived</div>
324
+ </div>
325
+ </section>
326
+
327
+ <!-- ─────────────── v6.2.6 ─────────────── -->
328
+ <section class="release">
329
+ <div class="release-head">
330
+ <h2 class="release-version">v6.2.6</h2>
331
+ <span class="release-tagline">project snapshot upload</span>
332
+ <span class="release-date">2026-05-21</span>
333
+ </div>
334
+ <p class="release-intro">
335
+ <code>qualia-framework project-snapshot --upload</code> sends the current 0-to-100
336
+ project snapshot to ERP's <code>/api/v1/project-snapshots</code> intake so admin
337
+ dashboards can show the latest Framework progress without manual import.
338
+ </p>
339
+ </section>
340
+
341
+ <!-- ─────────────── v6.2.5 ─────────────── -->
342
+ <section class="release">
343
+ <div class="release-head">
344
+ <h2 class="release-version">v6.2.5</h2>
345
+ <span class="release-tagline">project snapshot export</span>
346
+ <span class="release-date">2026-05-21</span>
347
+ </div>
348
+ <p class="release-intro">
349
+ <code>qualia-framework project-snapshot --write</code> creates a single
350
+ <code>.planning/snapshots/project-snapshot-*.json</code> rollup for ERP/admin import,
351
+ including shared IDs, current milestone/phase, closed milestones, lifetime counters, and
352
+ a 0-to-100 progress percentage.
353
+ </p>
354
+ </section>
355
+
356
+ <!-- ─────────────── v6.2.4 ─────────────── -->
357
+ <section class="release">
358
+ <div class="release-head">
359
+ <h2 class="release-version">v6.2.4</h2>
360
+ <span class="release-tagline">report payload contract</span>
361
+ <span class="release-date">2026-05-21</span>
362
+ </div>
363
+ <p class="release-intro">
364
+ <code>/qualia-report</code> now calls the shipped <code>report-payload.js</code> builder.
365
+ Tests prove ERP UUID fields are sent only when canonical, while local slugs stay in
366
+ <code>project_id</code> and <code>team_id</code>.
367
+ </p>
368
+ </section>
369
+
370
+ <!-- ─────────────── v6.2.3 ─────────────── -->
371
+ <section class="release">
372
+ <div class="release-head">
373
+ <h2 class="release-version">v6.2.3</h2>
374
+ <span class="release-tagline">ERP ID guard</span>
375
+ <span class="release-date">2026-05-21</span>
376
+ </div>
377
+ <p class="release-intro">
378
+ <code>/qualia-report</code> now sends ERP-native IDs only when they are UUID-shaped.
379
+ Local slugs stay in <code>project_id</code> and <code>team_id</code>.
380
+ </p>
381
+ </section>
382
+
383
+ <!-- ─────────────── v6.2.2 ─────────────── -->
384
+ <section class="release">
385
+ <div class="release-head">
386
+ <h2 class="release-version">v6.2.2</h2>
387
+ <span class="release-tagline">memory / ERP operating model</span>
388
+ <span class="release-date">2026-05-21</span>
389
+ </div>
390
+ <p class="release-intro">
391
+ The framework now documents the clean operating model: Framework builds, Memory remembers,
392
+ ERP operates. ERP work packets seed sessions; reports can carry ERP-native IDs.
393
+ </p>
394
+
395
+ <div class="change-group">
396
+ <h3>Added</h3>
397
+ <article class="change">
398
+ <header class="change-head">
399
+ <span class="badge new">New</span>
400
+ <h4 class="change-title">Ecosystem operating model and work packet</h4>
401
+ </header>
402
+ <p class="change-body">
403
+ <code>docs/ecosystem-operating-model.md</code> records the Framework/Memory/ERP boundary.
404
+ <code>templates/work-packet.md</code> gives ERP/admins an approved context handoff into Claude or Codex.
405
+ </p>
406
+ </article>
407
+ <article class="change">
408
+ <header class="change-head">
409
+ <span class="badge fix">Changed</span>
410
+ <h4 class="change-title">ERP-native IDs flow through reports when present</h4>
411
+ </header>
412
+ <p class="change-body">
413
+ <code>tracking.json</code> now preserves <code>erp_project_id</code>, <code>client_id</code>, and
414
+ <code>workspace_id</code>. <code>/qualia-report</code> sends them only when populated.
415
+ </p>
416
+ </article>
417
+ </div>
418
+ </section>
419
+
420
+ <!-- ─────────────── v6.2.1 ─────────────── -->
421
+ <section class="release">
422
+ <div class="release-head">
423
+ <h2 class="release-version">v6.2.1</h2>
424
+ <span class="release-tagline">revival audit guard</span>
425
+ <span class="release-date">2026-05-21</span>
426
+ </div>
427
+ <p class="release-intro">
428
+ v6.2 removed the bot commits. v6.2.1 makes the visible framework surface tell the same truth:
429
+ ERP sync is explicit through <code>/qualia-report</code>, <code>tracking.json</code> is local/report
430
+ telemetry, <code>INSUFFICIENT EVIDENCE</code> is fail-closed, and the package now identifies as 6.2.1.
431
+ </p>
432
+
433
+ <div class="change-group">
434
+ <h3>Changed</h3>
435
+
436
+ <article class="change">
437
+ <header class="change-head">
438
+ <span class="badge fix">Fixed</span>
439
+ <h4 class="change-title">Active surfaces no longer describe the old ERP model</h4>
440
+ </header>
441
+ <p class="change-body">
442
+ README, guide, onboarding, ERP contract, road, milestone, and roadmapper wording now describe
443
+ <code>tracking.json</code> as local/report telemetry. No active surface claims that the ERP passively
444
+ reads it from git.
445
+ </p>
446
+ </article>
447
+
448
+ <article class="change">
449
+ <header class="change-head">
450
+ <span class="badge fix">Fixed</span>
451
+ <h4 class="change-title">Verification language is fail-closed</h4>
452
+ </header>
453
+ <p class="change-body">
454
+ <code>/qualia-verify</code> no longer repeats the old false-pass wording. Any
455
+ <code>INSUFFICIENT EVIDENCE</code> line downgrades verification to FAIL before the phase can pass.
456
+ </p>
457
+ </article>
458
+
459
+ <article class="change">
460
+ <header class="change-head">
461
+ <span class="badge new">New guard</span>
462
+ <h4 class="change-title">refs.test.sh now catches stale operational claims</h4>
463
+ </header>
464
+ <p class="change-body">
465
+ The surface-drift guard now fails on passive ERP-tracking claims, removed pre-compact guidance,
466
+ stale skill counts, stale README version, old <code>INSUFFICIENT EVIDENCE</code> wording, and
467
+ silent optional gate language.
468
+ </p>
469
+ </article>
470
+ </div>
471
+ </section>
472
+
473
+ <!-- ─────────────── v6.2 ─────────────── -->
474
+ <section class="release">
475
+ <div class="release-head">
476
+ <h2 class="release-version">v6.2.0</h2>
477
+ <span class="release-tagline">no bot commits</span>
478
+ <span class="release-date">2026-05-20</span>
479
+ </div>
480
+ <p class="release-intro">
481
+ Two hooks were creating bot commits to feed a phantom consumer. The ERP does not read
482
+ <code>tracking.json</code> from GitHub, and <code>state.js</code> already protects disk state with
483
+ atomic writes plus a journal. v6.2 strips the false machinery.
484
+ </p>
485
+
486
+ <div class="change-group">
487
+ <h3>Removed</h3>
488
+
489
+ <article class="change">
490
+ <header class="change-head">
491
+ <span class="badge fix">Removed</span>
492
+ <h4 class="change-title">pre-push no longer creates tracking commits</h4>
493
+ </header>
494
+ <p class="change-body">
495
+ <code>pre-push.js</code> still stamps local telemetry for statusline, stop-session-log, and
496
+ <code>/qualia-report</code>, but it does not run <code>git add</code> or create bot commits.
497
+ </p>
498
+ </article>
499
+
500
+ <article class="change">
501
+ <header class="change-head">
502
+ <span class="badge fix">Removed</span>
503
+ <h4 class="change-title">pre-compact hook deleted</h4>
504
+ </header>
505
+ <p class="change-body">
506
+ Context compaction is in-memory. Disk state survives through <code>state.js</code> atomic writes and
507
+ write-ahead journal recovery, so committing on compaction was noisy and redundant.
508
+ </p>
509
+ </article>
510
+ </div>
511
+ </section>
512
+
513
+ <!-- ─────────────── v6.1 ─────────────── -->
514
+ <section class="release">
515
+ <div class="release-head">
516
+ <h2 class="release-version">v6.1.0</h2>
517
+ <span class="release-tagline">design pivot path</span>
518
+ <span class="release-date">2026-05-17</span>
519
+ </div>
520
+ <p class="release-intro">
521
+ The design path was missing a fast pivot. <code>/qualia-polish</code> polishes within the current vibe;
522
+ <code>/qualia-polish --redesign</code> rebuilds from scratch (~30 min). When a client says "different vibe"
523
+ and the right move is a 3-minute token swap, neither fit. v6.1 adds the impeccable middle path.
524
+ </p>
525
+
526
+ <div class="change-group">
527
+ <h3>New</h3>
528
+
529
+ <article class="change">
530
+ <header class="change-head">
531
+ <span class="badge new">New skill</span>
532
+ <h4 class="change-title">/qualia-vibe — layout-preserving aesthetic pivot</h4>
533
+ </header>
534
+ <p class="change-body">
535
+ Swap design tokens (color, type, depth, motion) without touching component structure.
536
+ Default mode proposes ONE direction with justification — never a menu.
537
+ Hard contract: vibe NEVER touches JSX, routing, data flow, or layout grid. Tokens only.
538
+ If a pivot needs structural change, it routes you to <code>--redesign</code> and stops.
539
+ </p>
540
+ <pre>/qualia-vibe <span class="comment"># propose ONE pivot, apply on approval</span>
541
+ /qualia-vibe brutalist <span class="comment"># explicit named direction</span>
542
+ /qualia-vibe --variants 3 <span class="comment"># opt-in A/B/C menu (rare)</span>
543
+ /qualia-vibe --extract https://stripe.com <span class="comment"># reverse-engineer DESIGN.md from a reference</span>
544
+ /qualia-vibe --extract ./inspo.png <span class="comment"># same, from a local screenshot</span>
545
+ /qualia-vibe --sync <span class="comment"># show drift between code and DESIGN.md</span>
546
+ /qualia-vibe --sync --write <span class="comment"># patch DESIGN.md to match code, commit</span></pre>
547
+ </article>
548
+
549
+ <article class="change">
550
+ <header class="change-head">
551
+ <span class="badge new">New rule</span>
552
+ <h4 class="change-title">rules/one-opinion.md — the EventMaster discipline</h4>
553
+ </header>
554
+ <p class="change-body">
555
+ Codified the canonical session lesson (user pivoted aesthetic 3 times in one block and finally said
556
+ <em>"ANYTHING JUST CHANGE IT STOP ASKING"</em>). When proposing a design decision the user hasn't named,
557
+ propose ONE direction with justification — never a menu. If rejected, ask what didn't fit and propose
558
+ ONE replacement. Lazy-loaded by design-adjacent skills only.
559
+ </p>
560
+ </article>
561
+ </div>
562
+
563
+ <div class="change-group">
564
+ <h3>Slop-detect upgrades</h3>
565
+
566
+ <article class="change">
567
+ <header class="change-head">
568
+ <span class="badge tweak">Enhanced</span>
569
+ <h4 class="change-title">More banned fonts caught</h4>
570
+ </header>
571
+ <p class="change-body">
572
+ Added Montserrat, Poppins, Lato, Open Sans — already banned in <code>design-brand.md</code> but missed
573
+ by the linter. These are the "looks AI-generated" font giveaways.
574
+ </p>
575
+ </article>
576
+
577
+ <article class="change">
578
+ <header class="change-head">
579
+ <span class="badge new">New flag</span>
580
+ <h4 class="change-title">slop-detect --watch for live editing</h4>
581
+ </header>
582
+ <p class="change-body">
583
+ Proactive single-file mode with 200ms debounce. Watches tracked extensions
584
+ (<code>tsx, jsx, ts, js, css, scss, html, svelte, vue, astro</code>) and re-scans on change.
585
+ Default scan paths also extended to <code>packages/</code> and <code>apps/</code> for monorepo conventions.
586
+ </p>
587
+ </article>
588
+ </div>
589
+
590
+ <div class="change-group">
591
+ <h3>Design-surface bugs from v6.0 audit</h3>
592
+
593
+ <article class="change">
594
+ <header class="change-head">
595
+ <span class="badge fix">Fixed</span>
596
+ <h4 class="change-title">Polish loop desktop viewport — 1280 → 1440</h4>
597
+ </header>
598
+ <p class="change-body">
599
+ SKILL.md Stage 4 said 1280px. Scripts, REFERENCE.md, and the visual evaluator all use 1440. Aligned to 1440 — file-not-found errors gone.
600
+ </p>
601
+ </article>
602
+
603
+ <article class="change">
604
+ <header class="change-head">
605
+ <span class="badge fix">Fixed</span>
606
+ <h4 class="change-title">Polish loop slop-detect path</h4>
607
+ </header>
608
+ <p class="change-body">
609
+ Was hardcoded to <code>~/.claude/bin/slop-detect.mjs</code> and silently skipped the gate if missing.
610
+ Now searches env var, home, then framework-relative path. Miss is logged, not silent.
611
+ </p>
612
+ </article>
613
+
614
+ <article class="change">
615
+ <header class="change-head">
616
+ <span class="badge fix">Fixed</span>
617
+ <h4 class="change-title">Polish loop commit-fix on fresh clones</h4>
618
+ </header>
619
+ <p class="change-body">
620
+ Was failing with <em>"Please tell me who you are"</em> when global git config wasn't set.
621
+ Now sets <code>user.name</code> / <code>user.email</code> inline so the commit always works.
622
+ </p>
623
+ </article>
624
+
625
+ <article class="change">
626
+ <header class="change-head">
627
+ <span class="badge fix">Fixed</span>
628
+ <h4 class="change-title">Dead /qualia-design references removed</h4>
629
+ </header>
630
+ <p class="change-body">
631
+ That command was deleted in v4.5 but <code>qualia-design/frontend.md</code> still listed it as active.
632
+ Replaced with <code>/qualia-polish</code> + <code>/qualia-vibe</code>.
633
+ </p>
634
+ </article>
635
+
636
+ <article class="change">
637
+ <header class="change-head">
638
+ <span class="badge fix">Fixed</span>
639
+ <h4 class="change-title">--ease-spring bounce token removed</h4>
640
+ </header>
641
+ <p class="change-body">
642
+ <code>design-reference.md</code> shipped <code>--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1)</code>
643
+ as a generic token — but <code>design-laws.md</code> §6 and slop-detect's MED-BOUNCE-EASING rule
644
+ ban that exact curve. Self-contradicting. Removed.
645
+ </p>
646
+ </article>
647
+
648
+ <article class="change">
649
+ <header class="change-head">
650
+ <span class="badge fix">Fixed</span>
651
+ <h4 class="change-title">Polish brief no longer offers a menu</h4>
652
+ </header>
653
+ <p class="change-body">
654
+ Stage 0 brief format listed <code>{editorial · brutalist · luxury · maximalist · …}</code> as options.
655
+ Per <code>rules/one-opinion.md</code>, agent now proposes ONE direction inferred from <code>PRODUCT.md</code>.
656
+ Pushback routes to <code>/qualia-vibe</code>, not enumeration.
657
+ </p>
658
+ </article>
659
+ </div>
660
+ </section>
661
+
662
+ <!-- ─────────────── v6.0 ─────────────── -->
663
+ <section class="release">
664
+ <div class="release-head">
665
+ <h2 class="release-version">v6.0.0</h2>
666
+ <span class="release-tagline">audit, cleanup, reliability</span>
667
+ <span class="release-date">2026-05-17</span>
668
+ </div>
669
+ <p class="release-intro">
670
+ Wide-surface audit pass. No new flagship feature. Every change is a real bug, a silent failure surfaced into a trace,
671
+ an outdated reference replaced, or a token-budget reduction. Same 32 skills (at the time), same road, same behavior —
672
+ just the broken edges fixed.
673
+ </p>
674
+
675
+ <div class="change-group">
676
+ <h3>Engine bugs</h3>
677
+
678
+ <article class="change">
679
+ <header class="change-head">
680
+ <span class="badge fix">Fixed</span>
681
+ <h4 class="change-title">Uninstall + migrate manifests now match what ships</h4>
682
+ </header>
683
+ <p class="change-body">
684
+ Uninstall used to leave 3 hooks + 1 agent orphaned on disk
685
+ (<code>env-empty-guard</code>, <code>supabase-destructive-guard</code>, <code>vercel-account-guard</code>,
686
+ <code>visual-evaluator</code>). Migrate silently skipped wiring the same 3 hooks. Both flows now
687
+ match the 12-hooks + 9-agents that actually ship.
688
+ </p>
689
+ </article>
690
+
691
+ <article class="change">
692
+ <header class="change-head">
693
+ <span class="badge fix">Fixed</span>
694
+ <h4 class="change-title">Silent catches in hooks now write traces</h4>
695
+ </header>
696
+ <p class="change-body">
697
+ <code>auto-update.js</code> had two bare <code>catch {}</code> blocks. <code>pre-compact.js</code>
698
+ had one around the commit logic. All three swallowed errors invisibly. Now each writes to
699
+ <code>~/.claude/.qualia-traces/</code> so failures are debuggable instead of vanishing.
700
+ </p>
701
+ </article>
702
+
703
+ <article class="change">
704
+ <header class="change-head">
705
+ <span class="badge fix">Fixed</span>
706
+ <h4 class="change-title">env-empty-guard no longer false-blocks</h4>
707
+ </header>
708
+ <p class="change-body">
709
+ Was exiting 2 (BLOCK) on any unparseable stdin payload — a malformed JSON from an unrelated tool call
710
+ could block the user from running <code>vercel env</code>. Now allows on parse error and only blocks
711
+ when the command actually matched a <code>vercel env add</code> with an empty value.
712
+ </p>
713
+ </article>
714
+
715
+ <article class="change">
716
+ <header class="change-head">
717
+ <span class="badge fix">Fixed</span>
718
+ <h4 class="change-title">Four broken skills</h4>
719
+ </header>
720
+ <p class="change-body">
721
+ <code>/qualia-learn</code> declared the wrong tools and couldn't run its own <code>node</code> + <code>git</code> calls (missing Bash).
722
+ <code>/qualia-map</code> described an <code>AskUserQuestion</code> prompt it couldn't render.
723
+ <code>/qualia-plan</code> Rule 2 said "max 3 revision cycles" while the process said "max 2." Reconciled.
724
+ <code>/qualia-postmortem</code> referenced <code>skills/qualia-design/SKILL.md</code> — that path was deleted long ago.
725
+ </p>
726
+ </article>
727
+
728
+ <article class="change">
729
+ <header class="change-head">
730
+ <span class="badge fix">Fixed</span>
731
+ <h4 class="change-title">Agent MCP tool frontmatter gaps</h4>
732
+ </header>
733
+ <p class="change-body">
734
+ <code>planner.md</code> used <code>mcp__context7__*</code> tools without declaring them.
735
+ <code>qa-browser.md</code> used <code>mcp__playwright__*</code> tools without declaring them.
736
+ Both would have failed silently. Both now declared.
737
+ </p>
738
+ </article>
739
+
740
+ <article class="change">
741
+ <header class="change-head">
742
+ <span class="badge fix">Fixed</span>
743
+ <h4 class="change-title">Hardcoded /tmp paths replaced</h4>
744
+ </header>
745
+ <p class="change-body">
746
+ Verifier drift audit used <code>/tmp/used-tokens</code> + <code>/tmp/declared</code> directly
747
+ (Windows-incompatible, symlink-attackable on multi-user systems). QA-browser dev-server log
748
+ had the same issue. Now uses <code>mktemp</code> / <code>$TMPDIR/qualia-dev-server-$$.log</code>.
749
+ </p>
750
+ </article>
751
+ </div>
752
+
753
+ <div class="change-group">
754
+ <h3>Token efficiency</h3>
755
+
756
+ <article class="change">
757
+ <header class="change-head">
758
+ <span class="badge new">Extracted</span>
759
+ <h4 class="change-title">rules/trust-boundary.md — shared injection-defence</h4>
760
+ </header>
761
+ <p class="change-body">
762
+ The trust-boundary security block was copy-pasted into 4 agents (builder, planner, verifier,
763
+ visual-evaluator) — ~150 tokens each, ~600 tokens duplicated total. Extracted to a single rule file.
764
+ Agents reference it with one line plus role-specific reporting shape. <strong>Net: ~500 tokens
765
+ saved per phase that spawns the full agent set.</strong>
766
+ </p>
767
+ </article>
768
+
769
+ <article class="change">
770
+ <header class="change-head">
771
+ <span class="badge tweak">Cleaned</span>
772
+ <h4 class="change-title">Stale version stamps stripped</h4>
773
+ </header>
774
+ <p class="change-body">
775
+ User-facing skill surfaces had "v4.5+" / "v5.0+" / "v5.1+" / "v5.3+" annotations everywhere
776
+ (<code>/qualia-road</code>, <code>/qualia-new</code>, <code>/qualia-polish</code>,
777
+ <code>/qualia-verify</code>, <code>/qualia-flush</code>, <code>/qualia-milestone</code>,
778
+ <code>/qualia-hook-gen</code>, <code>/qualia-feature</code>). At v6 they were noise.
779
+ </p>
780
+ </article>
781
+ </div>
782
+
783
+ <div class="change-group">
784
+ <h3>Tests + docs</h3>
785
+
786
+ <article class="change">
787
+ <header class="change-head">
788
+ <span class="badge new">New runner</span>
789
+ <h4 class="change-title">tests/run-all.sh — fail-collect orchestrator</h4>
790
+ </header>
791
+ <p class="change-body">
792
+ Old runner chained 8 suites with <code>&amp;&amp;</code> — first failure aborted everything, so you only ever saw
793
+ the failure of the earliest-failing suite. New runner collects all failures and reports which suites failed.
794
+ Also stripped silent <code>|| true</code> from slop-detect tests so real crashes can't pass invisibly.
795
+ </p>
796
+ </article>
797
+
798
+ <article class="change">
799
+ <header class="change-head">
800
+ <span class="badge fix">Fixed</span>
801
+ <h4 class="change-title">Phantom rules/frontend.md references</h4>
802
+ </header>
803
+ <p class="change-body">
804
+ <code>CLAUDE.md</code>, <code>AGENTS.md</code>, and <code>/qualia-feature</code> all pointed at
805
+ <code>rules/frontend.md</code> — which has not existed since the design substrate moved to
806
+ <code>qualia-design/</code> in v4.5. Agents loading these references hit a dead end. Now points
807
+ at <code>qualia-design/frontend.md</code>. Also added <code>rules/architecture.md</code> to the
808
+ discoverable substrate list.
809
+ </p>
810
+ </article>
811
+
812
+ <article class="change">
813
+ <header class="change-head">
814
+ <span class="badge tweak">Cleaned</span>
815
+ <h4 class="change-title">help.html + onboarding.html version drift</h4>
816
+ </header>
817
+ <p class="change-body">
818
+ <code>templates/help.html</code> showed "28 skills" (actual 32) and was missing 6 newer skill entries
819
+ (<code>qualia-hook-gen</code>, <code>qualia-issues</code>, <code>qualia-road</code>,
820
+ <code>qualia-triage</code>, <code>qualia-zoom</code>, <code>zoho-workflow</code>).
821
+ <code>docs/onboarding.html</code> was stamped v5.5. Both updated.
822
+ </p>
823
+ </article>
824
+
825
+ <article class="change">
826
+ <header class="change-head">
827
+ <span class="badge tweak">Archived</span>
828
+ <h4 class="change-title">Pre-v4 CHANGELOG entries moved out of the main file</h4>
829
+ </header>
830
+ <p class="change-body">
831
+ CHANGELOG was 2,726 lines going back to v2.0.0. Pre-v4.0.0 entries (851 lines of archaeological history)
832
+ moved to <code>docs/archive/CHANGELOG-pre-v4.md</code>. Main CHANGELOG dropped to 1,875 lines.
833
+ </p>
834
+ </article>
835
+ </div>
836
+ </section>
837
+
838
+ <!-- ─────────────── Migration ─────────────── -->
839
+ <section class="migration">
840
+ <h2>What you need to do</h2>
841
+ <p>
842
+ Update on your machine. Restart Claude Code. That is the whole migration. No code change required in any project.
843
+ ERP integration is explicit through the same <code>/qualia-report</code> contract. <code>tracking.json</code>
844
+ remains local/report telemetry, not a passive git feed.
845
+ </p>
846
+ <pre>npx qualia-framework@latest install <span class="comment"># also remembers your team code</span>
847
+ <span class="comment"># then quit Claude Code and open a new terminal</span>
848
+ npx qualia-framework@latest version <span class="comment"># verify shows 6.2.6</span></pre>
849
+ <p style="margin-top: var(--space-3); font-size: .9rem;">
850
+ If you had a previous uninstall leave orphan files, re-run uninstall to clean them up cleanly.
851
+ If you still see old commands (<code>/qualia-quick</code>, <code>/qualia-task</code>, <code>/qualia-prd</code>,
852
+ <code>/qualia-polish-loop</code>) in your skill list after install, those are stale folders on disk —
853
+ delete with <code>rm -rf ~/.claude/skills/qualia-{quick,task,prd,polish-loop}</code> then restart.
854
+ </p>
855
+ </section>
856
+
857
+ <footer>
858
+ <span>Qualia Framework v6.2.7 · Plan, build, verify, ship.</span>
859
+ <span><a href="https://github.com/Qualiasolutions/qualia-framework">github.com/Qualiasolutions/qualia-framework</a></span>
860
+ </footer>
861
+
862
+ </main>
863
+ </body>
864
+ </html>