qualia-framework 4.1.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1488 @@
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 v4.1.0 — Production Review</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" />
10
+ <style>
11
+ :root {
12
+ color-scheme: dark;
13
+ --brand: #00ced1;
14
+ --brand-dim: #008c91;
15
+ --brand-glow: rgba(0, 206, 209, 0.15);
16
+ --bg: #0a0d14;
17
+ --surface: #111621;
18
+ --surface-2: #161c2a;
19
+ --surface-3: #1d2536;
20
+ --border: #232b3d;
21
+ --border-hi: #2d3850;
22
+ --text: #e6eaf2;
23
+ --text-dim: #8892a6;
24
+ --text-mute: #5a6478;
25
+ --crit: #ef4444;
26
+ --high: #f59e0b;
27
+ --med: #60a5fa;
28
+ --low: #6b7280;
29
+ --pass: #10b981;
30
+ --content-w: min(1280px, 92vw);
31
+ --radius: 12px;
32
+ --radius-sm: 8px;
33
+ --ease: cubic-bezier(0.4, 0, 0.2, 1);
34
+ }
35
+
36
+ * { box-sizing: border-box; margin: 0; padding: 0; }
37
+
38
+ html { scroll-behavior: smooth; }
39
+
40
+ body {
41
+ font-family: 'Inter', system-ui, sans-serif;
42
+ background: var(--bg);
43
+ color: var(--text);
44
+ line-height: 1.6;
45
+ font-size: 15px;
46
+ -webkit-font-smoothing: antialiased;
47
+ min-height: 100vh;
48
+ background-image:
49
+ radial-gradient(ellipse 80% 50% at 50% -20%, var(--brand-glow), transparent 60%),
50
+ radial-gradient(ellipse 60% 40% at 100% 100%, rgba(245, 158, 11, 0.05), transparent 60%);
51
+ }
52
+
53
+ @media (prefers-reduced-motion: reduce) {
54
+ *, *::before, *::after {
55
+ animation-duration: 0.01ms !important;
56
+ transition-duration: 0.01ms !important;
57
+ }
58
+ }
59
+
60
+ h1, h2, h3, h4 {
61
+ font-family: 'Outfit', sans-serif;
62
+ font-weight: 600;
63
+ letter-spacing: -0.02em;
64
+ line-height: 1.2;
65
+ color: var(--text);
66
+ }
67
+
68
+ code, pre, .mono {
69
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
70
+ font-size: 0.88em;
71
+ }
72
+
73
+ a { color: var(--brand); text-decoration: none; transition: opacity 150ms var(--ease); }
74
+ a:hover { opacity: 0.8; }
75
+
76
+ /* ============== LAYOUT ============== */
77
+
78
+ .wrap {
79
+ max-width: var(--content-w);
80
+ margin: 0 auto;
81
+ padding-inline: clamp(1rem, 4vw, 3rem);
82
+ }
83
+
84
+ /* ============== NAV ============== */
85
+
86
+ nav.topbar {
87
+ position: sticky;
88
+ top: 0;
89
+ z-index: 50;
90
+ background: rgba(10, 13, 20, 0.85);
91
+ backdrop-filter: blur(12px);
92
+ -webkit-backdrop-filter: blur(12px);
93
+ border-bottom: 1px solid var(--border);
94
+ }
95
+
96
+ .topbar-inner {
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: space-between;
100
+ padding-block: 0.75rem;
101
+ gap: 2rem;
102
+ }
103
+
104
+ .brand-lock {
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 0.6rem;
108
+ font-family: 'Outfit', sans-serif;
109
+ font-weight: 700;
110
+ font-size: 1.05rem;
111
+ letter-spacing: -0.01em;
112
+ }
113
+
114
+ .brand-mark {
115
+ width: 10px; height: 10px;
116
+ background: var(--brand);
117
+ transform: rotate(45deg);
118
+ box-shadow: 0 0 12px var(--brand-glow);
119
+ }
120
+
121
+ .brand-sep {
122
+ color: var(--text-mute);
123
+ font-weight: 400;
124
+ }
125
+
126
+ .brand-sub {
127
+ color: var(--text-dim);
128
+ font-weight: 500;
129
+ }
130
+
131
+ .nav-links {
132
+ display: flex;
133
+ gap: 1.5rem;
134
+ list-style: none;
135
+ font-size: 0.85rem;
136
+ }
137
+
138
+ .nav-links a {
139
+ color: var(--text-dim);
140
+ transition: color 150ms var(--ease);
141
+ }
142
+
143
+ .nav-links a:hover { color: var(--brand); opacity: 1; }
144
+
145
+ @media (max-width: 780px) {
146
+ .nav-links { display: none; }
147
+ }
148
+
149
+ /* ============== HERO ============== */
150
+
151
+ .hero {
152
+ padding-block: clamp(3rem, 8vw, 5rem);
153
+ border-bottom: 1px solid var(--border);
154
+ }
155
+
156
+ .hero-tag {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ gap: 0.5rem;
160
+ padding: 0.35rem 0.75rem;
161
+ background: var(--surface-2);
162
+ border: 1px solid var(--border);
163
+ border-radius: 999px;
164
+ font-size: 0.75rem;
165
+ color: var(--text-dim);
166
+ letter-spacing: 0.08em;
167
+ text-transform: uppercase;
168
+ margin-bottom: 1.5rem;
169
+ }
170
+
171
+ .hero-tag::before {
172
+ content: '';
173
+ width: 6px; height: 6px;
174
+ background: var(--crit);
175
+ border-radius: 50%;
176
+ box-shadow: 0 0 8px var(--crit);
177
+ animation: pulse 2s ease-in-out infinite;
178
+ }
179
+
180
+ @keyframes pulse {
181
+ 0%, 100% { opacity: 1; }
182
+ 50% { opacity: 0.4; }
183
+ }
184
+
185
+ .hero h1 {
186
+ font-size: clamp(2.25rem, 5vw, 3.75rem);
187
+ font-weight: 700;
188
+ max-width: 20ch;
189
+ margin-bottom: 1rem;
190
+ }
191
+
192
+ .hero h1 .accent {
193
+ color: var(--brand);
194
+ }
195
+
196
+ .hero-meta {
197
+ color: var(--text-dim);
198
+ font-size: 1rem;
199
+ max-width: 65ch;
200
+ margin-bottom: 2.5rem;
201
+ }
202
+
203
+ .hero-meta strong { color: var(--text); font-weight: 500; }
204
+
205
+ /* ============== SCORECARD ============== */
206
+
207
+ .scorecard {
208
+ display: grid;
209
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
210
+ gap: 1rem;
211
+ margin-top: 2rem;
212
+ }
213
+
214
+ .score {
215
+ background: var(--surface);
216
+ border: 1px solid var(--border);
217
+ border-radius: var(--radius);
218
+ padding: 1.25rem;
219
+ position: relative;
220
+ overflow: hidden;
221
+ transition: border-color 200ms var(--ease), transform 200ms var(--ease);
222
+ }
223
+
224
+ .score:hover {
225
+ border-color: var(--border-hi);
226
+ transform: translateY(-2px);
227
+ }
228
+
229
+ .score::before {
230
+ content: '';
231
+ position: absolute;
232
+ top: 0; left: 0;
233
+ width: 3px;
234
+ height: 100%;
235
+ background: var(--score-color, var(--brand));
236
+ }
237
+
238
+ .score[data-score="1"], .score[data-score="2"] { --score-color: var(--crit); }
239
+ .score[data-score="3"] { --score-color: var(--high); }
240
+ .score[data-score="4"] { --score-color: var(--med); }
241
+ .score[data-score="5"] { --score-color: var(--pass); }
242
+
243
+ .score-label {
244
+ font-size: 0.75rem;
245
+ color: var(--text-dim);
246
+ letter-spacing: 0.08em;
247
+ text-transform: uppercase;
248
+ margin-bottom: 0.5rem;
249
+ }
250
+
251
+ .score-value {
252
+ font-family: 'Outfit', sans-serif;
253
+ font-size: 2.5rem;
254
+ font-weight: 700;
255
+ color: var(--text);
256
+ line-height: 1;
257
+ }
258
+
259
+ .score-value .of { font-size: 1rem; color: var(--text-mute); font-weight: 400; }
260
+
261
+ .score-breakdown {
262
+ display: flex;
263
+ gap: 0.75rem;
264
+ margin-top: 0.75rem;
265
+ font-size: 0.78rem;
266
+ color: var(--text-dim);
267
+ }
268
+
269
+ .score-breakdown .chip {
270
+ font-variant-numeric: tabular-nums;
271
+ }
272
+
273
+ .chip-crit { color: var(--crit); }
274
+ .chip-high { color: var(--high); }
275
+ .chip-med { color: var(--med); }
276
+ .chip-low { color: var(--text-mute); }
277
+
278
+ .verdict-row {
279
+ display: flex;
280
+ flex-wrap: wrap;
281
+ align-items: center;
282
+ gap: 1rem;
283
+ margin-top: 2.5rem;
284
+ padding: 1.25rem 1.5rem;
285
+ background: linear-gradient(to right, rgba(239, 68, 68, 0.08), transparent);
286
+ border: 1px solid rgba(239, 68, 68, 0.3);
287
+ border-left: 3px solid var(--crit);
288
+ border-radius: var(--radius);
289
+ }
290
+
291
+ .verdict-tag {
292
+ font-family: 'Outfit', sans-serif;
293
+ font-weight: 700;
294
+ font-size: 1.25rem;
295
+ color: var(--crit);
296
+ letter-spacing: 0.02em;
297
+ }
298
+
299
+ .verdict-text { color: var(--text-dim); }
300
+ .verdict-text strong { color: var(--text); }
301
+
302
+ /* ============== SECTIONS ============== */
303
+
304
+ section.section {
305
+ padding-block: clamp(3rem, 6vw, 4.5rem);
306
+ border-bottom: 1px solid var(--border);
307
+ }
308
+
309
+ .section-head {
310
+ display: flex;
311
+ align-items: baseline;
312
+ gap: 1rem;
313
+ margin-bottom: 2rem;
314
+ }
315
+
316
+ .section-num {
317
+ font-family: 'JetBrains Mono', monospace;
318
+ color: var(--brand);
319
+ font-size: 0.85rem;
320
+ font-weight: 500;
321
+ }
322
+
323
+ .section-head h2 {
324
+ font-size: clamp(1.5rem, 3vw, 2rem);
325
+ font-weight: 600;
326
+ }
327
+
328
+ .section-lead {
329
+ color: var(--text-dim);
330
+ max-width: 75ch;
331
+ margin-bottom: 2rem;
332
+ }
333
+
334
+ /* ============== FINDING CARDS ============== */
335
+
336
+ .findings {
337
+ display: grid;
338
+ gap: 1rem;
339
+ }
340
+
341
+ .finding {
342
+ background: var(--surface);
343
+ border: 1px solid var(--border);
344
+ border-radius: var(--radius);
345
+ padding: 1.25rem 1.5rem;
346
+ transition: border-color 200ms var(--ease);
347
+ position: relative;
348
+ }
349
+
350
+ .finding:hover { border-color: var(--border-hi); }
351
+
352
+ .finding[data-sev="CRITICAL"] { border-left: 3px solid var(--crit); }
353
+ .finding[data-sev="HIGH"] { border-left: 3px solid var(--high); }
354
+ .finding[data-sev="MEDIUM"] { border-left: 3px solid var(--med); }
355
+ .finding[data-sev="LOW"] { border-left: 3px solid var(--low); }
356
+
357
+ .finding-head {
358
+ display: flex;
359
+ flex-wrap: wrap;
360
+ align-items: center;
361
+ gap: 0.75rem;
362
+ margin-bottom: 0.75rem;
363
+ }
364
+
365
+ .sev-badge {
366
+ font-family: 'JetBrains Mono', monospace;
367
+ font-size: 0.7rem;
368
+ letter-spacing: 0.1em;
369
+ padding: 0.2rem 0.5rem;
370
+ border-radius: 4px;
371
+ font-weight: 500;
372
+ }
373
+
374
+ .sev-badge[data-sev="CRITICAL"] { background: rgba(239, 68, 68, 0.15); color: var(--crit); }
375
+ .sev-badge[data-sev="HIGH"] { background: rgba(245, 158, 11, 0.15); color: var(--high); }
376
+ .sev-badge[data-sev="MEDIUM"] { background: rgba(96, 165, 250, 0.15); color: var(--med); }
377
+ .sev-badge[data-sev="LOW"] { background: rgba(107, 114, 128, 0.15); color: var(--text-dim); }
378
+
379
+ .finding-id {
380
+ font-family: 'JetBrains Mono', monospace;
381
+ font-size: 0.78rem;
382
+ color: var(--text-mute);
383
+ }
384
+
385
+ .finding-title {
386
+ font-family: 'Outfit', sans-serif;
387
+ font-size: 1.05rem;
388
+ font-weight: 600;
389
+ flex: 1 1 min(100%, 20ch);
390
+ }
391
+
392
+ .finding-body {
393
+ color: var(--text-dim);
394
+ font-size: 0.92rem;
395
+ margin-bottom: 0.75rem;
396
+ }
397
+
398
+ .finding-body strong { color: var(--text); font-weight: 500; }
399
+
400
+ .finding-meta {
401
+ display: flex;
402
+ flex-wrap: wrap;
403
+ gap: 1rem;
404
+ font-size: 0.78rem;
405
+ padding-top: 0.75rem;
406
+ border-top: 1px dashed var(--border);
407
+ }
408
+
409
+ .meta-label {
410
+ color: var(--text-mute);
411
+ margin-right: 0.4rem;
412
+ }
413
+
414
+ .meta-val {
415
+ color: var(--text-dim);
416
+ font-family: 'JetBrains Mono', monospace;
417
+ }
418
+
419
+ .meta-fix { color: var(--brand); }
420
+
421
+ /* ============== TABLES ============== */
422
+
423
+ .data-table {
424
+ width: 100%;
425
+ border-collapse: separate;
426
+ border-spacing: 0;
427
+ background: var(--surface);
428
+ border: 1px solid var(--border);
429
+ border-radius: var(--radius);
430
+ overflow: hidden;
431
+ font-size: 0.88rem;
432
+ }
433
+
434
+ .data-table th {
435
+ background: var(--surface-2);
436
+ text-align: left;
437
+ padding: 0.8rem 1rem;
438
+ font-weight: 500;
439
+ color: var(--text);
440
+ font-size: 0.8rem;
441
+ letter-spacing: 0.05em;
442
+ text-transform: uppercase;
443
+ border-bottom: 1px solid var(--border);
444
+ }
445
+
446
+ .data-table td {
447
+ padding: 0.8rem 1rem;
448
+ color: var(--text-dim);
449
+ border-bottom: 1px solid var(--border);
450
+ vertical-align: top;
451
+ }
452
+
453
+ .data-table tr:last-child td { border-bottom: none; }
454
+ .data-table tr:hover td { background: var(--surface-2); }
455
+
456
+ .data-table td code {
457
+ color: var(--text);
458
+ background: var(--surface-3);
459
+ padding: 0.15rem 0.4rem;
460
+ border-radius: 3px;
461
+ font-size: 0.82em;
462
+ }
463
+
464
+ .table-scroll {
465
+ overflow-x: auto;
466
+ border-radius: var(--radius);
467
+ }
468
+
469
+ /* ============== MEMORY TIERS ============== */
470
+
471
+ .tiers {
472
+ display: grid;
473
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
474
+ gap: 1rem;
475
+ margin-block: 2rem;
476
+ }
477
+
478
+ .tier {
479
+ background: var(--surface);
480
+ border: 1px solid var(--border);
481
+ border-radius: var(--radius);
482
+ padding: 1.5rem;
483
+ position: relative;
484
+ transition: transform 200ms var(--ease), border-color 200ms var(--ease);
485
+ }
486
+
487
+ .tier:hover {
488
+ transform: translateY(-2px);
489
+ border-color: var(--border-hi);
490
+ }
491
+
492
+ .tier-num {
493
+ font-family: 'Outfit', sans-serif;
494
+ font-size: 3rem;
495
+ font-weight: 800;
496
+ color: var(--brand);
497
+ opacity: 0.25;
498
+ position: absolute;
499
+ top: 0.5rem;
500
+ right: 1rem;
501
+ line-height: 1;
502
+ }
503
+
504
+ .tier-name {
505
+ font-family: 'Outfit', sans-serif;
506
+ font-size: 1.1rem;
507
+ font-weight: 600;
508
+ margin-bottom: 0.25rem;
509
+ color: var(--text);
510
+ }
511
+
512
+ .tier-scope {
513
+ font-size: 0.8rem;
514
+ color: var(--text-mute);
515
+ letter-spacing: 0.05em;
516
+ text-transform: uppercase;
517
+ margin-bottom: 1rem;
518
+ }
519
+
520
+ .tier-path {
521
+ font-family: 'JetBrains Mono', monospace;
522
+ font-size: 0.82rem;
523
+ color: var(--brand);
524
+ padding: 0.5rem 0.75rem;
525
+ background: var(--surface-3);
526
+ border-radius: var(--radius-sm);
527
+ margin-bottom: 1rem;
528
+ word-break: break-all;
529
+ }
530
+
531
+ .tier-files {
532
+ list-style: none;
533
+ font-size: 0.85rem;
534
+ }
535
+
536
+ .tier-files li {
537
+ padding: 0.25rem 0;
538
+ color: var(--text-dim);
539
+ display: flex;
540
+ align-items: center;
541
+ gap: 0.5rem;
542
+ }
543
+
544
+ .tier-files li::before {
545
+ content: '├─';
546
+ color: var(--text-mute);
547
+ font-family: 'JetBrains Mono', monospace;
548
+ }
549
+
550
+ .tier-files li:last-child::before { content: '└─'; }
551
+
552
+ .tier-files code {
553
+ color: var(--text);
554
+ font-size: 0.85em;
555
+ }
556
+
557
+ /* ============== CODE BLOCK ============== */
558
+
559
+ pre.code {
560
+ background: var(--surface);
561
+ border: 1px solid var(--border);
562
+ border-radius: var(--radius);
563
+ padding: 1.25rem;
564
+ overflow-x: auto;
565
+ font-size: 0.82rem;
566
+ line-height: 1.6;
567
+ color: var(--text-dim);
568
+ }
569
+
570
+ pre.code .cmt { color: var(--text-mute); }
571
+ pre.code .kw { color: var(--brand); }
572
+
573
+ /* ============== ROADMAP ============== */
574
+
575
+ .roadmap {
576
+ display: grid;
577
+ gap: 1rem;
578
+ margin-top: 1.5rem;
579
+ }
580
+
581
+ .release {
582
+ background: var(--surface);
583
+ border: 1px solid var(--border);
584
+ border-radius: var(--radius);
585
+ overflow: hidden;
586
+ }
587
+
588
+ .release-head {
589
+ display: flex;
590
+ flex-wrap: wrap;
591
+ align-items: center;
592
+ gap: 0.75rem;
593
+ padding: 1rem 1.5rem;
594
+ background: var(--surface-2);
595
+ border-bottom: 1px solid var(--border);
596
+ }
597
+
598
+ .release-tag {
599
+ font-family: 'JetBrains Mono', monospace;
600
+ font-size: 0.78rem;
601
+ background: var(--brand);
602
+ color: var(--bg);
603
+ padding: 0.25rem 0.6rem;
604
+ border-radius: 4px;
605
+ font-weight: 500;
606
+ }
607
+
608
+ .release-title {
609
+ font-family: 'Outfit', sans-serif;
610
+ font-size: 1.05rem;
611
+ font-weight: 600;
612
+ color: var(--text);
613
+ flex: 1;
614
+ }
615
+
616
+ .release-eta {
617
+ font-size: 0.8rem;
618
+ color: var(--text-mute);
619
+ }
620
+
621
+ .release-body {
622
+ padding: 1.25rem 1.5rem;
623
+ }
624
+
625
+ .release-body ol {
626
+ padding-left: 1.5rem;
627
+ color: var(--text-dim);
628
+ }
629
+
630
+ .release-body ol li {
631
+ padding: 0.3rem 0;
632
+ }
633
+
634
+ .release-body strong { color: var(--text); }
635
+
636
+ /* ============== PROPOSAL ============== */
637
+
638
+ .proposal {
639
+ display: grid;
640
+ grid-template-columns: 1fr;
641
+ gap: 1rem;
642
+ margin-top: 1rem;
643
+ }
644
+
645
+ @media (min-width: 820px) {
646
+ .proposal { grid-template-columns: 1fr 1fr; }
647
+ }
648
+
649
+ .prop-card {
650
+ background: var(--surface);
651
+ border: 1px solid var(--border);
652
+ border-radius: var(--radius);
653
+ padding: 1.5rem;
654
+ }
655
+
656
+ .prop-card h4 {
657
+ font-size: 1rem;
658
+ margin-bottom: 0.75rem;
659
+ color: var(--text);
660
+ font-weight: 600;
661
+ }
662
+
663
+ .prop-card ul {
664
+ color: var(--text-dim);
665
+ font-size: 0.9rem;
666
+ padding-left: 1.25rem;
667
+ }
668
+
669
+ .prop-card ul li { padding: 0.2rem 0; }
670
+
671
+ /* ============== FOOTER ============== */
672
+
673
+ footer {
674
+ padding-block: 3rem;
675
+ text-align: center;
676
+ color: var(--text-mute);
677
+ font-size: 0.85rem;
678
+ }
679
+
680
+ footer a { color: var(--text-dim); }
681
+
682
+ /* ============== COMMAND ROUTING TABLE ============== */
683
+
684
+ .route-badge {
685
+ display: inline-block;
686
+ padding: 0.15rem 0.5rem;
687
+ border-radius: 4px;
688
+ font-size: 0.72rem;
689
+ font-family: 'JetBrains Mono', monospace;
690
+ letter-spacing: 0.03em;
691
+ }
692
+
693
+ .route-keep { background: rgba(16, 185, 129, 0.15); color: var(--pass); }
694
+ .route-merge { background: rgba(96, 165, 250, 0.15); color: var(--med); }
695
+ .route-delete { background: rgba(239, 68, 68, 0.15); color: var(--crit); }
696
+ .route-fix { background: rgba(245, 158, 11, 0.15); color: var(--high); }
697
+
698
+ /* ============== STAGGER ============== */
699
+
700
+ .stagger > * {
701
+ opacity: 0;
702
+ transform: translateY(12px);
703
+ animation: fadeUp 400ms cubic-bezier(0, 0, 0.2, 1) forwards;
704
+ }
705
+ .stagger > *:nth-child(1) { animation-delay: 0ms; }
706
+ .stagger > *:nth-child(2) { animation-delay: 60ms; }
707
+ .stagger > *:nth-child(3) { animation-delay: 120ms; }
708
+ .stagger > *:nth-child(4) { animation-delay: 180ms; }
709
+ .stagger > *:nth-child(5) { animation-delay: 240ms; }
710
+
711
+ @keyframes fadeUp {
712
+ to { opacity: 1; transform: translateY(0); }
713
+ }
714
+
715
+ /* ============== FILTER BAR ============== */
716
+
717
+ .filter-bar {
718
+ display: flex;
719
+ flex-wrap: wrap;
720
+ gap: 0.5rem;
721
+ margin-bottom: 1.5rem;
722
+ }
723
+
724
+ .filter-btn {
725
+ background: var(--surface);
726
+ border: 1px solid var(--border);
727
+ color: var(--text-dim);
728
+ padding: 0.4rem 0.85rem;
729
+ border-radius: 999px;
730
+ font-size: 0.78rem;
731
+ cursor: pointer;
732
+ font-family: inherit;
733
+ transition: all 150ms var(--ease);
734
+ }
735
+
736
+ .filter-btn:hover {
737
+ border-color: var(--border-hi);
738
+ color: var(--text);
739
+ }
740
+
741
+ .filter-btn[aria-pressed="true"] {
742
+ background: var(--brand);
743
+ color: var(--bg);
744
+ border-color: var(--brand);
745
+ font-weight: 500;
746
+ }
747
+
748
+ .filter-btn .count {
749
+ opacity: 0.6;
750
+ margin-left: 0.3rem;
751
+ }
752
+
753
+ .finding.hidden { display: none; }
754
+
755
+ </style>
756
+ </head>
757
+ <body>
758
+
759
+ <nav class="topbar">
760
+ <div class="wrap topbar-inner">
761
+ <div class="brand-lock">
762
+ <span class="brand-mark" aria-hidden="true"></span>
763
+ <span>QUALIA</span>
764
+ <span class="brand-sep">▸</span>
765
+ <span class="brand-sub">Framework Review</span>
766
+ </div>
767
+ <ul class="nav-links">
768
+ <li><a href="#summary">Summary</a></li>
769
+ <li><a href="#top10">Critical</a></li>
770
+ <li><a href="#memory">Memory</a></li>
771
+ <li><a href="#commands">Commands</a></li>
772
+ <li><a href="#polish">Polish</a></li>
773
+ <li><a href="#roadmap">Roadmap</a></li>
774
+ </ul>
775
+ </div>
776
+ </nav>
777
+
778
+ <header class="hero">
779
+ <div class="wrap">
780
+ <div class="hero-tag">Review · 2026-04-22 · v4.1.0</div>
781
+ <h1>Production review of <span class="accent">the complete framework.</span></h1>
782
+ <p class="hero-meta">
783
+ 4 parallel specialist audits across <strong>26 skills</strong>, <strong>8 agents</strong>, <strong>7 hooks</strong>, <strong>4 bin scripts</strong>, and the HTML surfaces. <strong>142 findings total</strong>. The Road skeleton is sound — context isolation, goal-backward verification, wave parallelization all hold up. But the framework has accumulated structural debt: invisible dependencies, silent failures, orphan commands, and no per-employee scoping.
784
+ </p>
785
+
786
+ <div class="scorecard stagger" id="summary">
787
+ <article class="score" data-score="2">
788
+ <div class="score-label">Commands &amp; Skills</div>
789
+ <div class="score-value">2<span class="of">/5</span></div>
790
+ <div class="score-breakdown">
791
+ <span class="chip chip-crit">5 crit</span>
792
+ <span class="chip chip-high">14 high</span>
793
+ <span class="chip chip-med">17 med</span>
794
+ <span class="chip chip-low">9 low</span>
795
+ </div>
796
+ </article>
797
+ <article class="score" data-score="3">
798
+ <div class="score-label">Hooks &amp; State</div>
799
+ <div class="score-value">3<span class="of">/5</span></div>
800
+ <div class="score-breakdown">
801
+ <span class="chip chip-crit">0 crit</span>
802
+ <span class="chip chip-high">3 high</span>
803
+ <span class="chip chip-med">16 med</span>
804
+ <span class="chip chip-low">13 low</span>
805
+ </div>
806
+ </article>
807
+ <article class="score" data-score="2">
808
+ <div class="score-label">Memory &amp; Knowledge</div>
809
+ <div class="score-value">2<span class="of">/5</span></div>
810
+ <div class="score-breakdown">
811
+ <span class="chip chip-crit">3 crit</span>
812
+ <span class="chip chip-high">5 high</span>
813
+ <span class="chip chip-med">6 med</span>
814
+ <span class="chip chip-low">6 low</span>
815
+ </div>
816
+ </article>
817
+ <article class="score" data-score="2">
818
+ <div class="score-label">Design &amp; UX</div>
819
+ <div class="score-value">2<span class="of">/5</span></div>
820
+ <div class="score-breakdown">
821
+ <span class="chip chip-crit">0 crit</span>
822
+ <span class="chip chip-high">11 high</span>
823
+ <span class="chip chip-med">15 med</span>
824
+ <span class="chip chip-low">11 low</span>
825
+ </div>
826
+ </article>
827
+ </div>
828
+
829
+ <div class="verdict-row">
830
+ <span class="verdict-tag">FAIL</span>
831
+ <span class="verdict-text">
832
+ <strong>8 critical blockers · 33 high findings.</strong> Functional for OWNER daily use, structurally unsound for multi-employee scale. Ship v4.1.1 hotfix before onboarding the next team member; ship v4.2.0 before the next major client delivery.
833
+ </span>
834
+ </div>
835
+ </div>
836
+ </header>
837
+
838
+ <section class="section" id="top10">
839
+ <div class="wrap">
840
+ <div class="section-head">
841
+ <span class="section-num">01</span>
842
+ <h2>Top 10 Critical &amp; High Issues</h2>
843
+ </div>
844
+ <p class="section-lead">Fix-first list. Each one is load-bearing — they either silently corrupt output (1–5), create maintenance hell (6–7), or break team ergonomics (8–10).</p>
845
+
846
+ <div class="filter-bar" role="toolbar" aria-label="Severity filter">
847
+ <button class="filter-btn" aria-pressed="true" data-filter="all">All <span class="count">10</span></button>
848
+ <button class="filter-btn" aria-pressed="false" data-filter="CRITICAL">Critical <span class="count">5</span></button>
849
+ <button class="filter-btn" aria-pressed="false" data-filter="HIGH">High <span class="count">5</span></button>
850
+ </div>
851
+
852
+ <div class="findings">
853
+
854
+ <article class="finding" data-sev="CRITICAL">
855
+ <div class="finding-head">
856
+ <span class="sev-badge" data-sev="CRITICAL">CRITICAL</span>
857
+ <span class="finding-id">#01</span>
858
+ <h3 class="finding-title">grounding.md is a phantom for existing installs</h3>
859
+ </div>
860
+ <div class="finding-body">
861
+ The file exists in the repo at <code>rules/grounding.md</code> but is <strong>missing from the installed</strong> <code>~/.claude/rules/</code> for users who upgraded from v4.0.x. Every planner, builder, plan-checker, and verifier spawn references <code>@~/.claude/rules/grounding.md</code> and silently gets nothing. The Grounding Protocol and Severity Rubric are improvised. Every 1–5 score is ungrounded.
862
+ </div>
863
+ <div class="finding-meta">
864
+ <span><span class="meta-label">Where:</span> <code class="meta-val">8 skills/agents</code></span>
865
+ <span><span class="meta-label">Impact:</span> <span class="meta-val">Every verified phase, every project, silently</span></span>
866
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">install.js post-upgrade routine — diff rules/, copy missing</span></span>
867
+ </div>
868
+ </article>
869
+
870
+ <article class="finding" data-sev="CRITICAL">
871
+ <div class="finding-head">
872
+ <span class="sev-badge" data-sev="CRITICAL">CRITICAL</span>
873
+ <span class="finding-id">#02</span>
874
+ <h3 class="finding-title">Builder agent never reads the knowledge base</h3>
875
+ </div>
876
+ <div class="finding-body">
877
+ <code>agents/builder.md</code> has zero references to <code>~/.claude/knowledge/</code>. Patterns like <em>"Always use <code>lib/supabase/server.ts</code> for mutations"</em> reach the planner but not the agent that writes code. Patterns exist and don't affect output.
878
+ </div>
879
+ <div class="finding-meta">
880
+ <span><span class="meta-label">Where:</span> <code class="meta-val">agents/builder.md</code></span>
881
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">Add @-reference to knowledge in builder preamble</span></span>
882
+ </div>
883
+ </article>
884
+
885
+ <article class="finding" data-sev="CRITICAL">
886
+ <div class="finding-head">
887
+ <span class="sev-badge" data-sev="CRITICAL">CRITICAL</span>
888
+ <span class="finding-id">#03</span>
889
+ <h3 class="finding-title">11 of 14 knowledge files are invisible to every skill</h3>
890
+ </div>
891
+ <div class="finding-body">
892
+ <code>~/.claude/knowledge/</code> contains <code>qualia-context.md</code>, <code>deployment-map.md</code>, <code>supabase-patterns.md</code>, <code>voice-agent-patterns.md</code>, <code>employees.md</code>, and 6 more — grepping the framework for these filenames returns <strong>zero hits</strong>. Dead weight. <code>session-digest.md</code> hasn't updated since Apr 12 (the hook that wrote it was deleted).
893
+ </div>
894
+ <div class="finding-meta">
895
+ <span><span class="meta-label">Impact:</span> <span class="meta-val">Knowledge is write-only; no skill discovers new files</span></span>
896
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">bin/knowledge.js — discovery + 3-tier merge</span></span>
897
+ </div>
898
+ </article>
899
+
900
+ <article class="finding" data-sev="CRITICAL">
901
+ <div class="finding-head">
902
+ <span class="sev-badge" data-sev="CRITICAL">CRITICAL</span>
903
+ <span class="finding-id">#04</span>
904
+ <h3 class="finding-title">No per-employee memory scoping</h3>
905
+ </div>
906
+ <div class="finding-body">
907
+ All memory lives in global <code>~/.claude/knowledge/</code>. Hasan, Fawzi, Moayad share the same files. <code>employees.md</code> is a flat roster, not a scoping mechanism. Personal preferences mix with universal patterns, with no filtering.
908
+ </div>
909
+ <div class="finding-meta">
910
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">3-tier architecture — Framework / Employee / Project</span></span>
911
+ </div>
912
+ </article>
913
+
914
+ <article class="finding" data-sev="CRITICAL">
915
+ <div class="finding-head">
916
+ <span class="sev-badge" data-sev="CRITICAL">CRITICAL</span>
917
+ <span class="finding-id">#05</span>
918
+ <h3 class="finding-title">qualia-report ERP upload: silent injection &amp; auth failures</h3>
919
+ </div>
920
+ <div class="finding-body">
921
+ <strong>Empty API key</strong> → sends <code>Authorization: Bearer </code> (blank); 401 handler says "Ask Fawzi" without diagnosing.<br />
922
+ <strong>SUBMITTED_BY</strong> shell-interpolated into <code>node -e</code> → a single quote in git user.name breaks silently.<br />
923
+ <strong>report_id</strong> fallback to empty string on state.js failure → commit message loses ID, ERP payload corrupted.
924
+ </div>
925
+ <div class="finding-meta">
926
+ <span><span class="meta-label">Where:</span> <code class="meta-val">skills/qualia-report/SKILL.md:84, 114-163</code></span>
927
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">Guard empty key; env-var pass; validate report_id</span></span>
928
+ </div>
929
+ </article>
930
+
931
+ <article class="finding" data-sev="HIGH">
932
+ <div class="finding-head">
933
+ <span class="sev-badge" data-sev="HIGH">HIGH</span>
934
+ <span class="finding-id">#06</span>
935
+ <h3 class="finding-title">Triple overlap: qualia-optimize / qualia-review / qualia-polish</h3>
936
+ </div>
937
+ <div class="finding-body">
938
+ All three run the same grep patterns (fonts, max-width, gradients, service_role, empty catches, sequential awaits, <code>&lt;img&gt;</code> without next/image). Three output files, three severity scales, one underlying issue. User gets three reports on the same problems.
939
+ </div>
940
+ <div class="finding-meta">
941
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">qualia-review = detect, qualia-polish = fix, delete qualia-optimize</span></span>
942
+ </div>
943
+ </article>
944
+
945
+ <article class="finding" data-sev="HIGH">
946
+ <div class="finding-head">
947
+ <span class="sev-badge" data-sev="HIGH">HIGH</span>
948
+ <span class="finding-id">#07</span>
949
+ <h3 class="finding-title">4 skills are orphans — never invoked by the Road</h3>
950
+ </div>
951
+ <div class="finding-body">
952
+ <code>qualia-test</code>, <code>qualia-debug</code>, <code>qualia-task</code>, <code>qualia-quick</code> are never auto-triggered by any Road step. <strong>The Road has no automated test gate</strong> between build and verify. If verification fails, the Road routes to <code>/qualia-plan --gaps</code>, not <code>/qualia-debug</code>.
953
+ </div>
954
+ <div class="finding-meta">
955
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">Integrate /qualia-test post-build, /qualia-debug on verify-fail</span></span>
956
+ </div>
957
+ </article>
958
+
959
+ <article class="finding" data-sev="HIGH">
960
+ <div class="finding-head">
961
+ <span class="sev-badge" data-sev="HIGH">HIGH</span>
962
+ <span class="finding-id">#08</span>
963
+ <h3 class="finding-title">Color palette drift across 5 surfaces</h3>
964
+ </div>
965
+ <div class="finding-body">
966
+ <code>TEAL_DIM</code> differs <code>rgb(0,130,135)</code> (statusline) vs <code>rgb(0,140,145)</code> (qualia-ui). <code>DIM</code> differs across 3 files. Brand teal in demo.html <code>#00ced9</code> vs help.html <code>#00ced1</code>. Display fonts split: Fraunces vs Outfit. DIM fails WCAG AA at ~3.2:1 on dark terminals.
967
+ </div>
968
+ <div class="finding-meta">
969
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">bin/colors.js — single source of truth</span></span>
970
+ </div>
971
+ </article>
972
+
973
+ <article class="finding" data-sev="HIGH">
974
+ <div class="finding-head">
975
+ <span class="sev-badge" data-sev="HIGH">HIGH</span>
976
+ <span class="finding-id">#09</span>
977
+ <h3 class="finding-title">Statusline shows installer name, not current operator</h3>
978
+ </div>
979
+ <div class="finding-body">
980
+ <code>bin/statusline.js:292</code> reads <code>.qualia-config.json</code> set at install time. On a shared machine, every operator sees the installer's name. Says <em>"Qualia member: Hasan"</em> even when Fawzi is driving.
981
+ </div>
982
+ <div class="finding-meta">
983
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">Session-scoped identity via git user.name or env var</span></span>
984
+ </div>
985
+ </article>
986
+
987
+ <article class="finding" data-sev="HIGH">
988
+ <div class="finding-head">
989
+ <span class="sev-badge" data-sev="HIGH">HIGH</span>
990
+ <span class="finding-id">#10</span>
991
+ <h3 class="finding-title">/qualia-ship has no state guard and shallow security</h3>
992
+ </div>
993
+ <div class="finding-body">
994
+ No <code>state.js check</code> at start — can invoke from any state. Security check only greps <code>service_role</code>; misses hardcoded keys, tracked <code>.env</code>, <code>dangerouslySetInnerHTML</code>. Post-deploy uses literal <code>{domain}</code> placeholder — expects LLM to hallucinate the URL.
995
+ </div>
996
+ <div class="finding-meta">
997
+ <span class="meta-fix"><span class="meta-label">Fix:</span> <span class="meta-val">State precondition + full qualia-review CRITICAL checks + read deployed_url from tracking.json</span></span>
998
+ </div>
999
+ </article>
1000
+
1001
+ </div>
1002
+ </div>
1003
+ </section>
1004
+
1005
+ <section class="section" id="silent-fails">
1006
+ <div class="wrap">
1007
+ <div class="section-head">
1008
+ <span class="section-num">02</span>
1009
+ <h2>15 Most Dangerous Silent Fails</h2>
1010
+ </div>
1011
+ <p class="section-lead">Places where users see a green "ok" while the underlying operation produced garbage. These are the ones most likely to damage trust when team members discover them.</p>
1012
+
1013
+ <div class="table-scroll">
1014
+ <table class="data-table">
1015
+ <thead>
1016
+ <tr>
1017
+ <th style="width:60px">Sev</th>
1018
+ <th>File:line</th>
1019
+ <th>Silent behavior</th>
1020
+ </tr>
1021
+ </thead>
1022
+ <tbody>
1023
+ <tr><td><span class="sev-badge" data-sev="CRITICAL">CRIT</span></td><td><code>qualia-report/SKILL.md:84</code></td><td>Empty pipe → report_id becomes <code>""</code>, commit loses ID</td></tr>
1024
+ <tr><td><span class="sev-badge" data-sev="CRITICAL">CRIT</span></td><td><code>qualia-report/SKILL.md:114</code></td><td>Empty API key → blank Bearer sent to ERP, generic 401</td></tr>
1025
+ <tr><td><span class="sev-badge" data-sev="CRITICAL">CRIT</span></td><td><code>qualia-handoff/SKILL.md:39</code></td><td>Malformed tracking.json → empty URL; curl hits blank target</td></tr>
1026
+ <tr><td><span class="sev-badge" data-sev="HIGH">HIGH</span></td><td><code>state.js:107</code></td><td>Lock timeout falls through silently — concurrent writes possible</td></tr>
1027
+ <tr><td><span class="sev-badge" data-sev="HIGH">HIGH</span></td><td><code>pre-push.js:22,47</code></td><td>No lock coord with state.js; cwd assumed to be repo root</td></tr>
1028
+ <tr><td><span class="sev-badge" data-sev="HIGH">HIGH</span></td><td><code>qualia-help/SKILL.md:44</code></td><td>Missing template → sed writes empty file → "ok" printed anyway</td></tr>
1029
+ <tr><td><span class="sev-badge" data-sev="HIGH">HIGH</span></td><td><code>qualia-verify/SKILL.md:65</code></td><td><code>FRONTEND=true</code> never set — browser QA never spawns</td></tr>
1030
+ <tr><td><span class="sev-badge" data-sev="HIGH">HIGH</span></td><td><code>cli.js:827</code></td><td>ERP ping uses <code>curl</code> — unavailable on older Windows</td></tr>
1031
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>state.js:179,229</code></td><td>readTracking/readState swallow corrupt JSON as "missing"</td></tr>
1032
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>state.js:59</code></td><td>Corrupt journal silently cleared, no log</td></tr>
1033
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>pre-deploy-gate.js:51</code></td><td>package.json missing → ALL gates silently skipped</td></tr>
1034
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>pre-deploy-gate.js:146</code></td><td>File read failure → security scan silently skips that file</td></tr>
1035
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>migration-guard.js:96</code></td><td>DROP TABLE check is file-global — one IF EXISTS masks another DROP</td></tr>
1036
+ <tr><td><span class="sev-badge" data-sev="MEDIUM">MED</span></td><td><code>state.js:329</code></td><td>Progress bar: phase 5/5 = 80% — never reaches 100%</td></tr>
1037
+ <tr><td><span class="sev-badge" data-sev="LOW">LOW</span></td><td><code>session-start.js:128</code></td><td>Top-level catch; crash → no banner, trace records "allow" anyway</td></tr>
1038
+ </tbody>
1039
+ </table>
1040
+ </div>
1041
+ </div>
1042
+ </section>
1043
+
1044
+ <section class="section" id="memory">
1045
+ <div class="wrap">
1046
+ <div class="section-head">
1047
+ <span class="section-num">03</span>
1048
+ <h2>Memory Architecture — 3-Tier Proposal</h2>
1049
+ </div>
1050
+ <p class="section-lead">
1051
+ Current state is flat, untiered, and half-invisible. Proposed architecture gives every finding a single home and makes discovery mechanical, not hardcoded.
1052
+ </p>
1053
+
1054
+ <div class="tiers">
1055
+ <article class="tier">
1056
+ <span class="tier-num">1</span>
1057
+ <h3 class="tier-name">Framework</h3>
1058
+ <p class="tier-scope">Universal · ships with installer</p>
1059
+ <div class="tier-path">~/.claude/knowledge/framework/</div>
1060
+ <ul class="tier-files">
1061
+ <li><code>stack-patterns.md</code></li>
1062
+ <li><code>voice-patterns.md</code></li>
1063
+ <li><code>security-patterns.md</code></li>
1064
+ <li><code>common-fixes.md</code></li>
1065
+ <li><code>KNOWLEDGE-INDEX.md</code></li>
1066
+ </ul>
1067
+ </article>
1068
+
1069
+ <article class="tier">
1070
+ <span class="tier-num">2</span>
1071
+ <h3 class="tier-name">Employee</h3>
1072
+ <p class="tier-scope">Per-user · scoped by team code</p>
1073
+ <div class="tier-path">~/.claude/knowledge/employee/</div>
1074
+ <ul class="tier-files">
1075
+ <li><code>preferences.md</code></li>
1076
+ <li><code>my-patterns.md</code></li>
1077
+ <li><code>my-fixes.md</code></li>
1078
+ <li><code>KNOWLEDGE-INDEX.md</code></li>
1079
+ </ul>
1080
+ </article>
1081
+
1082
+ <article class="tier">
1083
+ <span class="tier-num">3</span>
1084
+ <h3 class="tier-name">Project</h3>
1085
+ <p class="tier-scope">Per-repo · version controlled</p>
1086
+ <div class="tier-path">.planning/knowledge/</div>
1087
+ <ul class="tier-files">
1088
+ <li><code>client-prefs.md</code></li>
1089
+ <li><code>project-patterns.md</code></li>
1090
+ <li><code>deployment.md</code></li>
1091
+ <li><code>KNOWLEDGE-INDEX.md</code></li>
1092
+ </ul>
1093
+ </article>
1094
+ </div>
1095
+
1096
+ <h3 style="margin-top:2rem;font-size:1rem;color:var(--text-dim);font-weight:500">Discovery utility — <code>bin/knowledge.js</code></h3>
1097
+ <pre class="code"><span class="cmt"># Merge all 3 tiers — project overrides employee overrides framework</span>
1098
+ <span class="kw">knowledge.js</span> load --type patterns
1099
+
1100
+ <span class="cmt"># Search across tiers, labels source</span>
1101
+ <span class="kw">knowledge.js</span> search "supabase RLS"
1102
+
1103
+ <span class="cmt"># Regenerate INDEX files with last_verified timestamps</span>
1104
+ <span class="kw">knowledge.js</span> index
1105
+
1106
+ <span class="cmt"># Promote a Claude-native memory entry into Qualia structured tier</span>
1107
+ <span class="kw">knowledge.js</span> promote --from employee --to framework</pre>
1108
+
1109
+ <p style="color:var(--text-dim);margin-top:1.5rem;font-size:0.92rem">
1110
+ <strong style="color:var(--text)">Staleness:</strong> INDEX tracks <code>last_verified</code> per file. Entries over 30 days are tagged <code>[STALE]</code> in merge output — skills can warn before using.
1111
+ <strong style="color:var(--text)">Conflict:</strong> Project overrides Employee overrides Framework. Within a tier, newer timestamp wins.
1112
+ <strong style="color:var(--text)">Claude native memory:</strong> Keep enabled. Native captures conversational context; Qualia captures structured patterns. Statusline shows both counts: <code>K:14 M:4</code>.
1113
+ </p>
1114
+ </div>
1115
+ </section>
1116
+
1117
+ <section class="section" id="commands">
1118
+ <div class="wrap">
1119
+ <div class="section-head">
1120
+ <span class="section-num">04</span>
1121
+ <h2>Commands That Don't Fit the Road</h2>
1122
+ </div>
1123
+ <p class="section-lead">14 skills rated against the Road. Verdict in the right column: keep, merge, delete, or fix integration.</p>
1124
+
1125
+ <div class="table-scroll">
1126
+ <table class="data-table">
1127
+ <thead>
1128
+ <tr><th style="width:200px">Skill</th><th>Status</th><th style="width:200px">Action</th></tr>
1129
+ </thead>
1130
+ <tbody>
1131
+ <tr><td><code>qualia-task</code></td><td>Orphan · overlaps qualia-quick</td><td><span class="route-badge route-delete">DELETE</span> fold into /qualia-quick --proper</td></tr>
1132
+ <tr><td><code>qualia-quick</code></td><td>Orphan</td><td><span class="route-badge route-fix">EXTEND</span> add --proper flag</td></tr>
1133
+ <tr><td><code>qualia-test</code></td><td>Orphan · never auto-invoked</td><td><span class="route-badge route-fix">INTEGRATE</span> hard gate post-/qualia-build</td></tr>
1134
+ <tr><td><code>qualia-debug</code></td><td>Orphan · only suggested</td><td><span class="route-badge route-fix">INTEGRATE</span> auto-invoke on verify-fail</td></tr>
1135
+ <tr><td><code>qualia-design</code></td><td>~90% duplicate of qualia-polish</td><td><span class="route-badge route-merge">MERGE</span> into /qualia-polish</td></tr>
1136
+ <tr><td><code>qualia-optimize</code></td><td>Overlaps review + polish</td><td><span class="route-badge route-delete">DELETE</span> or repurpose as parallel wrapper</td></tr>
1137
+ <tr><td><code>qualia-review</code></td><td>Orphan · no state guard</td><td><span class="route-badge route-fix">INTEGRATE</span> between build and verify</td></tr>
1138
+ <tr><td><code>qualia-map</code></td><td>Optional brownfield</td><td><span class="route-badge route-keep">KEEP</span> auto-trigger on brownfield /qualia-new</td></tr>
1139
+ <tr><td><code>qualia-research</code></td><td>Optional phase depth</td><td><span class="route-badge route-keep">KEEP</span></td></tr>
1140
+ <tr><td><code>qualia-discuss</code></td><td>Optional phase depth</td><td><span class="route-badge route-keep">KEEP</span></td></tr>
1141
+ <tr><td><code>qualia-idk</code></td><td>Alternate router · genuine diagnostic</td><td><span class="route-badge route-keep">KEEP</span> fix help.html:410 mis-description</td></tr>
1142
+ <tr><td><code>qualia-learn</code></td><td>Meta</td><td><span class="route-badge route-fix">EXTEND</span> tier promotion</td></tr>
1143
+ <tr><td><code>qualia-help</code></td><td>Reference page</td><td><span class="route-badge route-keep">KEEP</span></td></tr>
1144
+ <tr><td><code>qualia-skill-new</code></td><td>Authoring</td><td><span class="route-badge route-keep">KEEP</span></td></tr>
1145
+ </tbody>
1146
+ </table>
1147
+ </div>
1148
+
1149
+ <div class="section-head" style="margin-top:3rem">
1150
+ <span class="section-num">04.1</span>
1151
+ <h2>Gaps — Missing from the Road</h2>
1152
+ </div>
1153
+
1154
+ <div class="proposal">
1155
+ <article class="prop-card">
1156
+ <h4>Automated test gate</h4>
1157
+ <ul>
1158
+ <li>No skill runs tests after build, before verify</li>
1159
+ <li>Current verifier greps code; never executes test suites</li>
1160
+ <li><strong>Fix:</strong> Invoke <code>/qualia-test</code> as hard gate inside <code>/qualia-build</code> post-wave</li>
1161
+ </ul>
1162
+ </article>
1163
+ <article class="prop-card">
1164
+ <h4>Inter-phase code review</h4>
1165
+ <ul>
1166
+ <li>Goal-backward verify doesn't check code quality</li>
1167
+ <li>A project can pass verify with poor code if acceptance criteria hold</li>
1168
+ <li><strong>Fix:</strong> Run <code>/qualia-review</code> between build and verify</li>
1169
+ </ul>
1170
+ </article>
1171
+ <article class="prop-card">
1172
+ <h4>Adversarial build loop</h4>
1173
+ <ul>
1174
+ <li>Per harness-engineering research (Anthropic GAN, Archon adversarial-dev)</li>
1175
+ <li>Generator ↔ evaluator with pre-negotiated sprint contract</li>
1176
+ <li><strong>Fix:</strong> <code>/qualia-build --adversarial</code> wraps builder in generator/evaluator loop</li>
1177
+ </ul>
1178
+ </article>
1179
+ <article class="prop-card">
1180
+ <h4>Continuous reviewer agents</h4>
1181
+ <ul>
1182
+ <li>No background persona reviewers on each commit</li>
1183
+ <li>Stripe Minion / Lopopolo "every push" pattern</li>
1184
+ <li><strong>Fix:</strong> Pre-push hook spawns security + reliability + frontend-architect reviewers</li>
1185
+ </ul>
1186
+ </article>
1187
+ </div>
1188
+ </div>
1189
+ </section>
1190
+
1191
+ <section class="section" id="components">
1192
+ <div class="wrap">
1193
+ <div class="section-head">
1194
+ <span class="section-num">05</span>
1195
+ <h2>Component Freshness — Fetching Latest</h2>
1196
+ </div>
1197
+ <p class="section-lead">No current mechanism in the framework. Grep for <code>shadcn</code>, <code>radix</code>, <code>component.*fetch</code> returns zero hits. Proposed skill below.</p>
1198
+
1199
+ <pre class="code"><span class="cmt"># Pulls latest shadcn components via official CLI</span>
1200
+ <span class="kw">/qualia-components</span> add button card dialog
1201
+
1202
+ <span class="cmt"># Bumps all components to latest; writes .planning/component-changelog.md</span>
1203
+ <span class="kw">/qualia-components</span> update
1204
+
1205
+ <span class="cmt"># Reports N components &gt; X days stale</span>
1206
+ <span class="kw">/qualia-components</span> check</pre>
1207
+
1208
+ <div class="proposal" style="margin-top:1.5rem">
1209
+ <article class="prop-card">
1210
+ <h4>Implementation details</h4>
1211
+ <ul>
1212
+ <li>Wraps <code>npx shadcn@latest add</code> for shadcn operations</li>
1213
+ <li>Integrates with existing <code>vercel-plugin:shadcn</code> skill</li>
1214
+ <li>WebFetch pulls latest docs (<code>ui.shadcn.com/docs/components/{name}</code>)</li>
1215
+ <li>For Radix: <code>npm info @radix-ui/react-{name} version</code> → compares with installed</li>
1216
+ <li>Writes diff summary so planner knows what changed</li>
1217
+ </ul>
1218
+ </article>
1219
+ <article class="prop-card">
1220
+ <h4>Integration points</h4>
1221
+ <ul>
1222
+ <li>Add component-version check to <code>/qualia-verify</code>: flag components &gt; 1 major behind</li>
1223
+ <li><strong>Do NOT auto-update</strong> during builds — component breaks should be explicit + versioned</li>
1224
+ <li>Add "component health" panel to statusline for active frontend projects</li>
1225
+ <li>On <code>/qualia-new</code> frontend project, offer to scaffold with latest shadcn</li>
1226
+ </ul>
1227
+ </article>
1228
+ </div>
1229
+ </div>
1230
+ </section>
1231
+
1232
+ <section class="section" id="polish">
1233
+ <div class="wrap">
1234
+ <div class="section-head">
1235
+ <span class="section-num">06</span>
1236
+ <h2>Design Polish Roadmap</h2>
1237
+ </div>
1238
+ <p class="section-lead">5 phases. Execute top to bottom. Each phase is atomic and independently shippable.</p>
1239
+
1240
+ <div class="roadmap">
1241
+ <article class="release">
1242
+ <div class="release-head">
1243
+ <span class="release-tag">PHASE 1</span>
1244
+ <span class="release-title">Color unification</span>
1245
+ <span class="release-eta">~1 day</span>
1246
+ </div>
1247
+ <div class="release-body">
1248
+ <ol>
1249
+ <li>Create <code>bin/colors.js</code> as single source of truth for all ANSI palettes</li>
1250
+ <li>Delete inline color definitions in statusline, qualia-ui, session-start, install, cli</li>
1251
+ <li>Fix TEAL_DIM mismatch (standardize on <code>rgb(0,135,140)</code>)</li>
1252
+ <li>Fix DIM mismatch — <strong>must pass WCAG AA</strong> on dark terminals (currently ~3.2:1)</li>
1253
+ <li>Unify brand teal: <code>#00ced1</code> (matches ANSI <code>rgb(0,206,209)</code>) across all HTML surfaces</li>
1254
+ </ol>
1255
+ </div>
1256
+ </article>
1257
+
1258
+ <article class="release">
1259
+ <div class="release-head">
1260
+ <span class="release-tag">PHASE 2</span>
1261
+ <span class="release-title">Statusline ergonomics</span>
1262
+ <span class="release-eta">~1 day</span>
1263
+ </div>
1264
+ <div class="release-body">
1265
+ <ol>
1266
+ <li>Terminal-width guard on Line 1 — progressive truncation (identity → memory → worktree → agent)</li>
1267
+ <li>Milestone indicator alongside phase: <code>M2 P3/5 T2/4</code></li>
1268
+ <li>Last-error from <code>tracking.json.last_error</code></li>
1269
+ <li>Duration format <code>Xh Ym</code> above 60min (currently <code>90m</code>, <code>120m</code>)</li>
1270
+ <li>Burn rate: <code>$/min</code> (more actionable than cumulative)</li>
1271
+ <li>Per-operator identity — session-scoped, not installer-name</li>
1272
+ </ol>
1273
+ </div>
1274
+ </article>
1275
+
1276
+ <article class="release">
1277
+ <div class="release-head">
1278
+ <span class="release-tag">PHASE 3</span>
1279
+ <span class="release-title">HTML modernization</span>
1280
+ <span class="release-eta">~1 day</span>
1281
+ </div>
1282
+ <div class="release-body">
1283
+ <ol>
1284
+ <li>Replace <code>@import</code> with <code>&lt;link rel="preconnect"&gt;&lt;link rel="stylesheet"&gt;</code> in help.html</li>
1285
+ <li>Unify design tokens across help.html and demo.html (shared <code>:root</code>)</li>
1286
+ <li>Pick one display font — recommend <strong>Outfit</strong> (geometric, matches brand)</li>
1287
+ <li><strong>Fix demo.html:506</strong> — <code>&lt;/span&gt;</code> should be <code>&lt;/div&gt;</code> (broken DOM)</li>
1288
+ <li><strong>Fix help.html:410</strong> — <code>/qualia-idk</code> mis-described as alias</li>
1289
+ <li>Adopt <code>@container</code> queries for card grids</li>
1290
+ <li>Add <code>color-scheme: dark</code> to both HTML pages</li>
1291
+ </ol>
1292
+ </div>
1293
+ </article>
1294
+
1295
+ <article class="release">
1296
+ <div class="release-head">
1297
+ <span class="release-tag">PHASE 4</span>
1298
+ <span class="release-title">Skill descriptions</span>
1299
+ <span class="release-eta">~half day</span>
1300
+ </div>
1301
+ <div class="release-body">
1302
+ <ol>
1303
+ <li>Trim 10 descriptions &gt; 30 words (autocomplete truncates)</li>
1304
+ <li>Add trigger phrases to 4 skills with none (report, ship, verify, build)</li>
1305
+ <li>Cap at 20 words + triggers</li>
1306
+ <li>Move flag documentation out of frontmatter into skill body</li>
1307
+ </ol>
1308
+ </div>
1309
+ </article>
1310
+
1311
+ <article class="release">
1312
+ <div class="release-head">
1313
+ <span class="release-tag">PHASE 5</span>
1314
+ <span class="release-title">Component fetching</span>
1315
+ <span class="release-eta">1–2 days</span>
1316
+ </div>
1317
+ <div class="release-body">
1318
+ <ol>
1319
+ <li>Build <code>/qualia-components</code> skill</li>
1320
+ <li>Integrate with <code>vercel-plugin:shadcn</code></li>
1321
+ <li>Add version-staleness check to <code>/qualia-verify</code></li>
1322
+ <li>Document pattern in <code>guide.md</code></li>
1323
+ </ol>
1324
+ </div>
1325
+ </article>
1326
+ </div>
1327
+ </div>
1328
+ </section>
1329
+
1330
+ <section class="section" id="roadmap">
1331
+ <div class="wrap">
1332
+ <div class="section-head">
1333
+ <span class="section-num">07</span>
1334
+ <h2>Release Roadmap</h2>
1335
+ </div>
1336
+ <p class="section-lead">Priority-ordered. v4.1.1 hotfix unblocks team scaling. v4.2.0 is the structural release.</p>
1337
+
1338
+ <div class="roadmap">
1339
+ <article class="release">
1340
+ <div class="release-head">
1341
+ <span class="release-tag">v4.1.1</span>
1342
+ <span class="release-title">Hotfix — ship this week</span>
1343
+ <span class="release-eta">~2 hours</span>
1344
+ </div>
1345
+ <div class="release-body">
1346
+ <ol>
1347
+ <li>Auto-copy missing rules on version bump (fixes <strong>grounding.md phantom</strong>)</li>
1348
+ <li>Guard empty API_KEY in <code>qualia-report</code></li>
1349
+ <li>Fix broken <code>&lt;/span&gt;</code> in demo.html:506</li>
1350
+ <li>Fix help.html:410 <code>/qualia-idk</code> description</li>
1351
+ <li>Add state guard to <code>/qualia-ship</code></li>
1352
+ </ol>
1353
+ </div>
1354
+ </article>
1355
+
1356
+ <article class="release">
1357
+ <div class="release-head">
1358
+ <span class="release-tag">v4.2.0</span>
1359
+ <span class="release-title">Structural — 2 weeks</span>
1360
+ <span class="release-eta">next sprint</span>
1361
+ </div>
1362
+ <div class="release-body">
1363
+ <ol>
1364
+ <li>3-tier memory architecture + <code>bin/knowledge.js</code></li>
1365
+ <li>Merge <code>qualia-design</code> into <code>qualia-polish</code>; delete orphan <code>qualia-task</code></li>
1366
+ <li>Unified <code>bin/colors.js</code></li>
1367
+ <li>Builder agent loads knowledge</li>
1368
+ <li>Integrate <code>/qualia-test</code> as build gate; <code>/qualia-debug</code> on verify-fail</li>
1369
+ <li>cwd → git root resolution for state.js, pre-push, pre-compact (fixes 3 MED findings at once)</li>
1370
+ </ol>
1371
+ </div>
1372
+ </article>
1373
+
1374
+ <article class="release">
1375
+ <div class="release-head">
1376
+ <span class="release-tag">v4.3.0</span>
1377
+ <span class="release-title">Harness patterns — 4 weeks</span>
1378
+ <span class="release-eta">month out</span>
1379
+ </div>
1380
+ <div class="release-body">
1381
+ <ol>
1382
+ <li>Adversarial build mode (generator ↔ evaluator GAN-style)</li>
1383
+ <li>Continuous reviewer agents (security/reliability/frontend personas on every push)</li>
1384
+ <li>Source-code structural tests (file&lt;350 lines, schema dedup, no-unknown)</li>
1385
+ <li><code>/qualia-components</code> skill</li>
1386
+ </ol>
1387
+ </div>
1388
+ </article>
1389
+
1390
+ <article class="release">
1391
+ <div class="release-head">
1392
+ <span class="release-tag">v4.4.0</span>
1393
+ <span class="release-title">Team-scale — ongoing</span>
1394
+ <span class="release-eta">quarter</span>
1395
+ </div>
1396
+ <div class="release-body">
1397
+ <ol>
1398
+ <li>Per-operator identity on statusline</li>
1399
+ <li>Shared-state coordination lock for multi-agent projects</li>
1400
+ <li>Token burn rate + milestone progress indicators</li>
1401
+ <li>Knowledge staleness tracking + auto-prune</li>
1402
+ </ol>
1403
+ </div>
1404
+ </article>
1405
+ </div>
1406
+ </div>
1407
+ </section>
1408
+
1409
+ <section class="section" id="verdict">
1410
+ <div class="wrap">
1411
+ <div class="section-head">
1412
+ <span class="section-num">08</span>
1413
+ <h2>Final Verdict</h2>
1414
+ </div>
1415
+
1416
+ <div class="proposal">
1417
+ <article class="prop-card" style="border-left:3px solid var(--pass)">
1418
+ <h4 style="color:var(--pass)">Strengths</h4>
1419
+ <p style="color:var(--text-dim);font-size:0.92rem">
1420
+ The Road skeleton is sound. Context isolation, goal-backward verification, story-file plans, wave-based parallelization, and the state machine hold up against current research (Anthropic, OpenAI, Archon). The harness pattern is <strong>genuinely good</strong> — these are the right primitives.
1421
+ </p>
1422
+ </article>
1423
+
1424
+ <article class="prop-card" style="border-left:3px solid var(--crit)">
1425
+ <h4 style="color:var(--crit)">Structural debt — three clusters</h4>
1426
+ <ul>
1427
+ <li><strong>Invisible dependencies</strong> — grounding.md, 11 knowledge files, builder↔knowledge disconnect. The framework believes things are loaded that aren't.</li>
1428
+ <li><strong>Silent failures</strong> — 15 high-impact silent-fail paths where users get "ok" while operations produced garbage.</li>
1429
+ <li><strong>Orphan skills</strong> — 4 commands never touch the Road; 3 triple-overlap. Real mental overhead for the team.</li>
1430
+ </ul>
1431
+ </article>
1432
+ </div>
1433
+
1434
+ <div class="verdict-row" style="margin-top:2rem">
1435
+ <span class="verdict-tag" style="color:var(--high)">SHIPPING BAR</span>
1436
+ <span class="verdict-text">
1437
+ This review would <strong>FAIL <code>/qualia-ship</code></strong> on a client project. The framework needs v4.1.1 hotfix <strong>before onboarding the next employee</strong>, and v4.2.0 before the next major client delivery.
1438
+ </span>
1439
+ </div>
1440
+ </div>
1441
+ </section>
1442
+
1443
+ <footer>
1444
+ <div class="wrap">
1445
+ Qualia Framework v4.1.0 · Production Review · 2026-04-22 · Generated by <a href="#top10">/qualia-review</a> · 142 findings across 4 specialist audits
1446
+ </div>
1447
+ </footer>
1448
+
1449
+ <script>
1450
+ // Severity filter
1451
+ const buttons = document.querySelectorAll('.filter-btn');
1452
+ const findings = document.querySelectorAll('#top10 .finding');
1453
+ buttons.forEach(btn => {
1454
+ btn.addEventListener('click', () => {
1455
+ buttons.forEach(b => b.setAttribute('aria-pressed', 'false'));
1456
+ btn.setAttribute('aria-pressed', 'true');
1457
+ const filter = btn.dataset.filter;
1458
+ findings.forEach(f => {
1459
+ if (filter === 'all' || f.dataset.sev === filter) {
1460
+ f.classList.remove('hidden');
1461
+ } else {
1462
+ f.classList.add('hidden');
1463
+ }
1464
+ });
1465
+ });
1466
+ });
1467
+
1468
+ // Reveal on scroll
1469
+ const io = new IntersectionObserver((entries) => {
1470
+ entries.forEach(e => {
1471
+ if (e.isIntersecting) {
1472
+ e.target.style.opacity = '1';
1473
+ e.target.style.transform = 'translateY(0)';
1474
+ io.unobserve(e.target);
1475
+ }
1476
+ });
1477
+ }, { threshold: 0.08 });
1478
+
1479
+ document.querySelectorAll('.finding, .score, .tier, .release, .prop-card').forEach(el => {
1480
+ el.style.opacity = '0';
1481
+ el.style.transform = 'translateY(12px)';
1482
+ el.style.transition = 'opacity 500ms cubic-bezier(0, 0, 0.2, 1), transform 500ms cubic-bezier(0, 0, 0.2, 1)';
1483
+ io.observe(el);
1484
+ });
1485
+ </script>
1486
+
1487
+ </body>
1488
+ </html>