qualia-framework 6.8.1 → 6.9.2

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 (85) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/bin/install.js +184 -9
  3. package/bin/report-payload.js +12 -0
  4. package/bin/state.js +70 -5
  5. package/docs/EMPLOYEE-QUICKSTART.md +164 -0
  6. package/docs/erp-contract.md +10 -1
  7. package/docs/qualia-manual.html +396 -0
  8. package/hooks/session-start.js +24 -4
  9. package/hooks/usage-capture.js +108 -0
  10. package/package.json +3 -1
  11. package/skills/qualia-doctor/SKILL.md +62 -0
  12. package/skills/qualia-new/REFERENCE.md +7 -0
  13. package/skills/qualia-new/SKILL.md +42 -0
  14. package/skills/qualia-report/SKILL.md +16 -0
  15. package/templates/planning.gitignore +3 -0
  16. package/templates/stacks/README.md +110 -0
  17. package/templates/stacks/ai-agent/env.required.json +44 -0
  18. package/templates/stacks/ai-agent/phases.md +53 -0
  19. package/templates/stacks/ai-agent/scaffold/.env.example +12 -0
  20. package/templates/stacks/ai-agent/scaffold/README.md +31 -0
  21. package/templates/stacks/ai-agent/scaffold/app/api/chat/route.ts +33 -0
  22. package/templates/stacks/ai-agent/scaffold/app/globals.css +13 -0
  23. package/templates/stacks/ai-agent/scaffold/app/layout.tsx +19 -0
  24. package/templates/stacks/ai-agent/scaffold/app/page.tsx +12 -0
  25. package/templates/stacks/ai-agent/scaffold/evals/cases.json +23 -0
  26. package/templates/stacks/ai-agent/scaffold/lib/openrouter/client.ts +51 -0
  27. package/templates/stacks/ai-agent/scaffold/lib/prompts/system.ts +6 -0
  28. package/templates/stacks/ai-agent/scaffold/lib/supabase/client.ts +10 -0
  29. package/templates/stacks/ai-agent/scaffold/lib/supabase/server.ts +28 -0
  30. package/templates/stacks/ai-agent/scaffold/next.config.mjs +7 -0
  31. package/templates/stacks/ai-agent/scaffold/package.json +29 -0
  32. package/templates/stacks/ai-agent/scaffold/postcss.config.mjs +7 -0
  33. package/templates/stacks/ai-agent/scaffold/supabase/migrations/0001_init.sql +41 -0
  34. package/templates/stacks/ai-agent/scaffold/tsconfig.json +21 -0
  35. package/templates/stacks/ai-agent/stack.json +9 -0
  36. package/templates/stacks/ai-agent/verify-checklist.md +31 -0
  37. package/templates/stacks/full-app/env.required.json +20 -0
  38. package/templates/stacks/full-app/phases.md +45 -0
  39. package/templates/stacks/full-app/scaffold/.env.example +7 -0
  40. package/templates/stacks/full-app/scaffold/README.md +28 -0
  41. package/templates/stacks/full-app/scaffold/app/globals.css +14 -0
  42. package/templates/stacks/full-app/scaffold/app/layout.tsx +19 -0
  43. package/templates/stacks/full-app/scaffold/app/page.tsx +20 -0
  44. package/templates/stacks/full-app/scaffold/lib/supabase/client.ts +10 -0
  45. package/templates/stacks/full-app/scaffold/lib/supabase/server.ts +31 -0
  46. package/templates/stacks/full-app/scaffold/next.config.mjs +7 -0
  47. package/templates/stacks/full-app/scaffold/package.json +29 -0
  48. package/templates/stacks/full-app/scaffold/postcss.config.mjs +7 -0
  49. package/templates/stacks/full-app/scaffold/supabase/migrations/0001_init.sql +27 -0
  50. package/templates/stacks/full-app/scaffold/tsconfig.json +21 -0
  51. package/templates/stacks/full-app/stack.json +9 -0
  52. package/templates/stacks/full-app/verify-checklist.md +32 -0
  53. package/templates/stacks/internal-tool/env.required.json +20 -0
  54. package/templates/stacks/internal-tool/phases.md +45 -0
  55. package/templates/stacks/internal-tool/scaffold/.env.example +7 -0
  56. package/templates/stacks/internal-tool/scaffold/README.md +29 -0
  57. package/templates/stacks/internal-tool/scaffold/app/globals.css +13 -0
  58. package/templates/stacks/internal-tool/scaffold/app/layout.tsx +20 -0
  59. package/templates/stacks/internal-tool/scaffold/app/page.tsx +22 -0
  60. package/templates/stacks/internal-tool/scaffold/lib/supabase/client.ts +9 -0
  61. package/templates/stacks/internal-tool/scaffold/lib/supabase/server.ts +28 -0
  62. package/templates/stacks/internal-tool/scaffold/next.config.mjs +6 -0
  63. package/templates/stacks/internal-tool/scaffold/package.json +29 -0
  64. package/templates/stacks/internal-tool/scaffold/postcss.config.mjs +7 -0
  65. package/templates/stacks/internal-tool/scaffold/supabase/migrations/0001_init.sql +28 -0
  66. package/templates/stacks/internal-tool/scaffold/tsconfig.json +21 -0
  67. package/templates/stacks/internal-tool/stack.json +9 -0
  68. package/templates/stacks/internal-tool/verify-checklist.md +31 -0
  69. package/templates/stacks/landing-page/env.required.json +8 -0
  70. package/templates/stacks/landing-page/phases.md +42 -0
  71. package/templates/stacks/landing-page/scaffold/.env.example +3 -0
  72. package/templates/stacks/landing-page/scaffold/README.md +25 -0
  73. package/templates/stacks/landing-page/scaffold/app/globals.css +14 -0
  74. package/templates/stacks/landing-page/scaffold/app/layout.tsx +19 -0
  75. package/templates/stacks/landing-page/scaffold/app/page.tsx +21 -0
  76. package/templates/stacks/landing-page/scaffold/next.config.mjs +7 -0
  77. package/templates/stacks/landing-page/scaffold/package.json +26 -0
  78. package/templates/stacks/landing-page/scaffold/postcss.config.mjs +7 -0
  79. package/templates/stacks/landing-page/scaffold/tsconfig.json +21 -0
  80. package/templates/stacks/landing-page/stack.json +9 -0
  81. package/templates/stacks/landing-page/verify-checklist.md +28 -0
  82. package/tests/bin.test.sh +8 -7
  83. package/tests/hooks.test.sh +32 -0
  84. package/tests/install-smoke.test.sh +4 -3
  85. package/tests/state.test.sh +83 -0
@@ -377,6 +377,8 @@ Snapshot shape:
377
377
  | last_pushed_at | string | optional (v3.6+) | ISO 8601 — distinct from `last_updated` (which fires on local writes too). |
378
378
  | build_count | number | optional (v3.6+) | Lifetime build counter. |
379
379
  | deploy_count | number | optional (v3.6+) | Lifetime deploy counter. |
380
+ | command_usage | object | optional (v6.9+) | Per-session qualia slash-command histogram, e.g. `{ "qualia-build": 3, "qualia-fix": 1 }`. Captured by the `usage-capture` UserPromptSubmit hook into `.planning/.session-usage.json` and cleared at clock-out. Drives the ERP performance audit's command-usage signal. Defaults to `{}`. |
381
+ | prompt_samples | string[] | optional (v6.9+) | Sampled real engineer prompts for the session (opt-in via `erp.capturePrompts`, default on; internal-only). Fed to the ERP prompt-quality judge. Capped at 60 entries / 8000 chars each. Defaults to `[]`. |
380
382
  | client_report_id | string | recommended (v4.0.4+) | Client-side sequential identifier: `QS-REPORT-01`, `QS-REPORT-02`, … per-project. Stable across retries. Preferred dedupe key over the ERP-generated `report_id`; safe to adopt as the ERP's primary report key. |
381
383
  | dry_run | boolean | optional (v4.0.4+) | `true` marks a synthetic ping (from `qualia-framework erp-ping`). Receivers should filter these out of production report views. |
382
384
 
@@ -393,4 +395,11 @@ All other fields are optional but recommended for complete reporting.
393
395
  - API keys are per-user, not per-project
394
396
  - Keys expire after 90 days (re-issue via Fawzi)
395
397
  - All traffic is HTTPS-only
396
- - No PII beyond team member names is transmitted
398
+ - **Free-form content:** beyond team member names, the only free-form content
399
+ transmitted is `prompt_samples` — the engineer's real prompts — and only when
400
+ `erp.capturePrompts` is enabled (default on). This is disclosed to engineers
401
+ at install, in their own `.qualia-config.json`, and via a once-per-shift
402
+ runtime notice; they may opt out at any time. Treat `prompt_samples` as
403
+ data that **may contain PII**: store it access-controlled, keep it out of
404
+ third-party sub-processors that aren't covered by the team's data agreement,
405
+ and honor deletion requests. Every other field is non-PII project metadata.
@@ -0,0 +1,396 @@
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.0">
6
+ <title>Qualia Framework · Field Manual</title>
7
+ <style>
8
+ :root{
9
+ --bg:#0a0e12; --panel:#11161d; --panel2:#161d26; --border:#1f2937;
10
+ --text:#d7dee8; --dim:#8b98a8; --faint:#5b6675;
11
+ --teal:#00FFD1; --teal-dim:#0b8f7d; --amber:#f5b942; --red:#ff5c5c; --green:#4ade80;
12
+ --mono:'SF Mono',ui-monospace,Consolas,monospace;
13
+ --sans:-apple-system,'Segoe UI',Roboto,sans-serif;
14
+ --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 30px rgba(0,0,0,.25);
15
+ --nav-w:240px;
16
+ }
17
+ *{box-sizing:border-box;margin:0;padding:0}
18
+ html{scroll-behavior:smooth}
19
+ body{
20
+ background:
21
+ radial-gradient(900px 500px at 85% -5%,rgba(0,255,209,.06),transparent 60%),
22
+ radial-gradient(700px 400px at 0% 0%,rgba(0,255,209,.04),transparent 55%),
23
+ var(--bg);
24
+ color:var(--text);font:15.5px/1.65 var(--sans);
25
+ -webkit-font-smoothing:antialiased;
26
+ }
27
+ a{color:var(--teal);text-decoration:none}
28
+ a:hover{text-decoration:underline}
29
+
30
+ /* skip link (a11y) */
31
+ .skip{position:absolute;left:-999px;top:0;background:var(--teal);color:#04110e;padding:10px 16px;border-radius:0 0 8px 0;font-weight:700;z-index:100}
32
+ .skip:focus{left:0}
33
+
34
+ /* layout */
35
+ .shell{display:grid;grid-template-columns:var(--nav-w) 1fr;max-width:1180px;margin:0 auto;gap:0}
36
+ nav.side{
37
+ position:sticky;top:0;align-self:start;height:100vh;overflow-y:auto;
38
+ padding:30px 18px 40px;border-right:1px solid var(--border);
39
+ }
40
+ nav.side .brand{display:flex;align-items:center;gap:9px;margin-bottom:6px}
41
+ nav.side .hex{color:var(--teal);font-size:20px;line-height:1}
42
+ nav.side .brand b{font-size:15px;letter-spacing:.5px}
43
+ nav.side .brand small{display:block;color:var(--faint);font-size:10.5px;letter-spacing:2px;text-transform:uppercase;margin-top:2px}
44
+ nav.side ol{list-style:none;margin-top:24px;counter-reset:s}
45
+ nav.side li{margin:1px 0}
46
+ nav.side a{
47
+ display:flex;gap:10px;align-items:baseline;color:var(--dim);font-size:13.5px;
48
+ padding:7px 10px;border-radius:7px;border-left:2px solid transparent;transition:.15s;
49
+ }
50
+ nav.side a .n{counter-increment:s;color:var(--faint);font-family:var(--mono);font-size:11px;min-width:14px}
51
+ nav.side a:hover{color:var(--text);background:var(--panel);text-decoration:none}
52
+ nav.side a.active{color:var(--teal);background:var(--panel2);border-left-color:var(--teal)}
53
+ nav.side a.active .n{color:var(--teal)}
54
+
55
+ main{padding:54px 48px 120px;min-width:0}
56
+
57
+ /* hero */
58
+ .hero{margin-bottom:14px}
59
+ .eyebrow{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:11.5px;color:var(--teal);letter-spacing:1.5px;text-transform:uppercase;border:1px solid var(--teal-dim);background:rgba(0,255,209,.05);padding:4px 12px;border-radius:30px;margin-bottom:20px}
60
+ .eyebrow .dot{width:6px;height:6px;border-radius:50%;background:var(--teal);box-shadow:0 0 10px var(--teal)}
61
+ h1{font-size:clamp(30px,5vw,46px);line-height:1.05;letter-spacing:-1.2px;font-weight:800}
62
+ h1 .g{color:var(--teal)}
63
+ .lede{color:var(--dim);font-size:clamp(15px,2vw,18px);max-width:62ch;margin-top:16px;line-height:1.55}
64
+
65
+ /* sections */
66
+ section{padding-top:64px;scroll-margin-top:24px}
67
+ h2{font-size:24px;letter-spacing:-.4px;font-weight:700;display:flex;align-items:center;gap:12px;margin-bottom:6px}
68
+ h2 .bar{width:26px;height:3px;border-radius:3px;background:var(--teal)}
69
+ .sec-sub{color:var(--dim);margin-bottom:22px;max-width:64ch}
70
+ h3{font-size:16px;font-weight:650;color:#fff;margin:26px 0 10px}
71
+ p{margin:10px 0}
72
+ .dim{color:var(--dim)}
73
+
74
+ /* panels */
75
+ .panel{background:var(--panel);border:1px solid var(--border);border-radius:14px;padding:22px 24px;margin:16px 0;box-shadow:var(--shadow)}
76
+ .grid{display:grid;gap:16px}
77
+ .g2{grid-template-columns:1fr 1fr}
78
+ .g3{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
79
+
80
+ /* command chip w/ copy */
81
+ code{font-family:var(--mono);font-size:.88em;background:var(--panel2);padding:2px 7px;border-radius:5px;color:var(--teal);border:1px solid var(--border)}
82
+ .cmd{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:13px;background:var(--panel2);border:1px solid var(--border);border-radius:8px;padding:6px 8px 6px 12px;color:#cfe;cursor:pointer;transition:.15s;user-select:none}
83
+ .cmd:hover{border-color:var(--teal-dim);background:#13202a}
84
+ .cmd .ico{font-size:11px;color:var(--faint);border-left:1px solid var(--border);padding-left:8px}
85
+ .cmd.copied{border-color:var(--teal);color:var(--teal)}
86
+ .cmd.copied .ico{color:var(--teal)}
87
+
88
+ pre{background:#0c1218;border:1px solid var(--border);border-left:3px solid var(--teal-dim);border-radius:0 10px 10px 0;padding:16px 18px;margin:14px 0;overflow-x:auto;font-family:var(--mono);font-size:13px;line-height:1.7;color:#b8c4d4}
89
+ pre .c{color:var(--faint)}
90
+ pre .t{color:var(--teal)}
91
+
92
+ /* lifecycle flow */
93
+ .flow{display:flex;flex-wrap:wrap;gap:10px;align-items:stretch;margin:20px 0}
94
+ .step{flex:1 1 130px;background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:14px 14px;position:relative;transition:.18s;min-width:120px}
95
+ .step:hover{border-color:var(--teal-dim);transform:translateY(-3px)}
96
+ .step .k{font-family:var(--mono);font-size:11px;color:var(--teal);letter-spacing:.5px}
97
+ .step .cmdname{font-weight:700;font-size:14px;margin:6px 0 4px}
98
+ .step .d{font-size:12px;color:var(--dim);line-height:1.45}
99
+ .flow .arrow{display:flex;align-items:center;color:var(--faint);font-size:18px}
100
+
101
+ /* command reference cards */
102
+ .cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px;margin-top:14px}
103
+ .card{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:16px 18px;transition:.18s}
104
+ .card:hover{border-color:var(--teal-dim);box-shadow:var(--shadow)}
105
+ .card h4{font-family:var(--mono);font-size:14px;color:var(--teal);margin-bottom:6px}
106
+ .card p{font-size:13px;color:var(--dim);margin:0}
107
+ .group-label{font-family:var(--mono);font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--faint);margin:26px 0 4px}
108
+
109
+ /* rules */
110
+ .rule{display:flex;gap:14px;padding:14px 0;border-bottom:1px solid var(--border)}
111
+ .rule:last-child{border-bottom:none}
112
+ .rule .num{flex:0 0 30px;height:30px;border-radius:9px;background:rgba(0,255,209,.08);border:1px solid var(--teal-dim);color:var(--teal);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;font-family:var(--mono)}
113
+ .rule b{color:#fff}
114
+ .rule .why{color:var(--dim);font-size:13.5px;font-style:italic}
115
+
116
+ /* table */
117
+ table{width:100%;border-collapse:collapse;margin:14px 0;font-size:13.5px}
118
+ th{text-align:left;color:var(--faint);font-weight:600;padding:9px 12px;border-bottom:1px solid var(--border);text-transform:uppercase;font-size:10.5px;letter-spacing:.8px}
119
+ td{padding:10px 12px;border-bottom:1px solid #131a22;vertical-align:top}
120
+ tr:hover td{background:rgba(255,255,255,.012)}
121
+
122
+ /* callout */
123
+ .note{border-left:3px solid var(--amber);background:rgba(245,185,66,.05);border-radius:0 10px 10px 0;padding:14px 18px;margin:16px 0;font-size:14px}
124
+ .note.teal{border-left-color:var(--teal);background:rgba(0,255,209,.05)}
125
+ .note b{color:#fff}
126
+
127
+ /* walkthrough */
128
+ .walk{counter-reset:w;margin-top:10px}
129
+ .walk .w{display:flex;gap:16px;padding:16px 0;border-bottom:1px dashed var(--border)}
130
+ .walk .w:last-child{border-bottom:none}
131
+ .walk .wn{counter-increment:w;flex:0 0 36px;height:36px;border-radius:50%;background:var(--panel2);border:1px solid var(--teal-dim);color:var(--teal);display:flex;align-items:center;justify-content:center;font-weight:700;font-family:var(--mono)}
132
+ .walk .wn::before{content:counter(w)}
133
+ .walk .wbody{flex:1}
134
+ .walk .wbody h4{font-size:15px;color:#fff;margin-bottom:3px}
135
+
136
+ footer{margin-top:80px;padding-top:24px;border-top:1px solid var(--border);color:var(--faint);font-size:12.5px}
137
+
138
+ /* reveal animation */
139
+ .reveal{opacity:0;transform:translateY(14px);transition:opacity .5s ease,transform .5s ease}
140
+ .reveal.in{opacity:1;transform:none}
141
+ @media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}html{scroll-behavior:auto}}
142
+
143
+ /* mobile */
144
+ .menu-btn{display:none}
145
+ @media(max-width:860px){
146
+ .shell{grid-template-columns:1fr}
147
+ nav.side{position:fixed;inset:0 auto 0 0;width:260px;background:var(--bg);z-index:50;transform:translateX(-100%);transition:transform .25s;border-right:1px solid var(--border)}
148
+ nav.side.open{transform:none;box-shadow:0 0 60px rgba(0,0,0,.6)}
149
+ main{padding:70px 22px 90px}
150
+ .menu-btn{display:inline-flex;position:fixed;top:14px;left:14px;z-index:60;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--border);color:var(--teal);font-family:var(--mono);font-size:13px;padding:8px 14px;border-radius:10px;cursor:pointer}
151
+ .g2,.g3{grid-template-columns:1fr}
152
+ }
153
+ </style>
154
+ </head>
155
+ <body>
156
+ <a class="skip" href="#what">Skip to content</a>
157
+ <button class="menu-btn" aria-label="Toggle navigation" onclick="document.querySelector('nav.side').classList.toggle('open')">☰ Menu</button>
158
+
159
+ <div class="shell">
160
+ <nav class="side" aria-label="Manual sections">
161
+ <div class="brand">
162
+ <span class="hex">⬢</span>
163
+ <div><b>QUALIA</b><small>Field Manual</small></div>
164
+ </div>
165
+ <ol>
166
+ <li><a href="#what" class="active"><span class="n"></span> What it is</a></li>
167
+ <li><a href="#loop"><span class="n"></span> The loop</a></li>
168
+ <li><a href="#install"><span class="n"></span> Install</a></li>
169
+ <li><a href="#commands"><span class="n"></span> Command map</a></li>
170
+ <li><a href="#first"><span class="n"></span> Your first project</a></li>
171
+ <li><a href="#rules"><span class="n"></span> The hard rules</a></li>
172
+ <li><a href="#keys"><span class="n"></span> Credentials</a></li>
173
+ <li><a href="#lost"><span class="n"></span> When you're lost</a></li>
174
+ </ol>
175
+ </nav>
176
+
177
+ <main id="top">
178
+ <header class="hero reveal">
179
+ <span class="eyebrow"><span class="dot"></span> Getting started · v6.9</span>
180
+ <h1>The Qualia <span class="g">Framework</span>,<br>in one sitting.</h1>
181
+ <p class="lede">A set of commands that takes you from an <b style="color:#fff">idea</b> to a <b style="color:#fff">shipped, reported</b> piece of work, without needing to memorise how Qualia builds software. You type one command, it tells you the next. This manual is the human-friendly tour of that path.</p>
182
+ </header>
183
+
184
+ <!-- WHAT -->
185
+ <section id="what" class="reveal">
186
+ <h2><span class="bar"></span> What it is</h2>
187
+ <p class="sec-sub">Qualia is an opinionated workflow that lives inside Claude Code (and Codex). It ships a lifecycle of <code>/qualia-*</code> slash commands, plus the guardrails (hooks, rules, and a shared brain) that keep every project consistent and safe.</p>
188
+ <div class="grid g3">
189
+ <div class="panel"><h3>🧭 It routes you</h3><p class="dim">Never wonder what's next. <code>/qualia</code> reads your project's state and hands you the exact next command. The framework keeps the map; you keep moving.</p></div>
190
+ <div class="panel"><h3>🛟 It guards you</h3><p class="dim">Deterministic hooks block the dangerous stuff (pushing to <code>main</code>, leaking secrets, destructive DB ops) before it happens. Rules aren't suggestions; they're enforced.</p></div>
191
+ <div class="panel"><h3>🧠 It remembers</h3><p class="dim">Lessons from every project flow into a shared knowledge base. A fix one person discovered shows up in everyone's install, so the team gets smarter over time.</p></div>
192
+ </div>
193
+ <div class="note teal"><b>The one-line mental model:</b> you describe <em>what</em> you want; the framework owns <em>how</em> Qualia builds it: the stack, the phases, the quality bar, the deploy steps.</div>
194
+ </section>
195
+
196
+ <!-- LOOP -->
197
+ <section id="loop" class="reveal">
198
+ <h2><span class="bar"></span> The loop</h2>
199
+ <p class="sec-sub">Every project walks the same path. You don't have to remember it (<code>/qualia</code> always points to the right step), but seeing it once makes everything click.</p>
200
+ <div class="flow">
201
+ <div class="step"><div class="k">START</div><div class="cmdname">/qualia-new</div><div class="d">Kickoff interview → pick a project preset → planning files written.</div></div>
202
+ <div class="arrow">→</div>
203
+ <div class="step"><div class="k">PLAN</div><div class="cmdname">/qualia-plan</div><div class="d">Break the current phase into small, wave-grouped tasks.</div></div>
204
+ <div class="arrow">→</div>
205
+ <div class="step"><div class="k">BUILD</div><div class="cmdname">/qualia-build</div><div class="d">Fresh builder agents execute the tasks, one atomic commit each.</div></div>
206
+ <div class="arrow">→</div>
207
+ <div class="step"><div class="k">VERIFY</div><div class="cmdname">/qualia-verify</div><div class="d">Goal-backward check that it actually works, not just that code ran.</div></div>
208
+ <div class="arrow">→</div>
209
+ <div class="step"><div class="k">SHIP</div><div class="cmdname">/qualia-ship</div><div class="d">Quality gates → commit → deploy to Vercel → verify live.</div></div>
210
+ <div class="arrow">→</div>
211
+ <div class="step"><div class="k">REPORT</div><div class="cmdname">/qualia-report</div><div class="d">Clock out, then generate your shift report and file it.</div></div>
212
+ </div>
213
+ <p class="dim">Plan → Build → Verify repeats per phase until the milestone is done. <code>/qualia-polish</code> slots in before shipping when the work is visual.</p>
214
+ </section>
215
+
216
+ <!-- INSTALL -->
217
+ <section id="install" class="reveal">
218
+ <h2><span class="bar"></span> Install in employee mode</h2>
219
+ <p class="sec-sub">You can install and do real work <b>today</b>, with no credentials. Employee mode gives you the full framework at the safest privilege level: feature branches only, no pushes to <code>main</code>.</p>
220
+ <pre><span class="c"># one command, works on a fresh machine</span>
221
+ npx qualia-framework@latest install</pre>
222
+ <p>At the prompt <code>Install code or "EMPLOYEE":</code></p>
223
+ <table>
224
+ <tr><th>If you…</th><th>Type</th><th>You get</th></tr>
225
+ <tr><td>Have a team code</td><td><code>QS-NAME-##</code></td><td>Install as that team member (ERP reporting on, with the key)</td></tr>
226
+ <tr><td>Have no code yet</td><td><code>EMPLOYEE</code></td><td>Full framework, EMPLOYEE role, ERP reporting off until a code is set</td></tr>
227
+ </table>
228
+ <div class="note"><b>Nothing is missing in employee mode.</b> Skills, agents, hooks, and knowledge are installed identically. The only differences: you can't push to <code>main</code> (the <code>branch-guard</code> hook blocks it), and <code>/qualia-report</code> saves a <em>local</em> report instead of uploading to the ERP. Ask Fawzi for a <code>QS-NAME-##</code> code when you're ready to upgrade.</div>
229
+ <h3>Then confirm it's healthy</h3>
230
+ <p>Run the doctor before real work. It checks the install, hooks, project state, and the ERP queue, and prints PASS/FAIL with the exact fix for anything wrong.</p>
231
+ <p><span class="cmd" data-copy="/qualia-doctor">/qualia-doctor<span class="ico">copy</span></span> <span class="dim">in employee mode it reports ERP as disabled; that's expected, not an error.</span></p>
232
+ </section>
233
+
234
+ <!-- COMMANDS -->
235
+ <section id="commands" class="reveal">
236
+ <h2><span class="bar"></span> The command map</h2>
237
+ <p class="sec-sub">You won't use all of these on day one. The lifecycle six (the loop above) cover most work; the rest are there when you need them. Click any command to copy it.</p>
238
+
239
+ <div class="group-label">◆ Orient · where am I, what now</div>
240
+ <div class="cards">
241
+ <div class="card"><h4 data-copy="/qualia">/qualia</h4><p>The router. Reads your state, tells you the single next command. When in doubt, run this.</p></div>
242
+ <div class="card"><h4 data-copy="/qualia-idk">/qualia-idk</h4><p>Deep "I don't know what's going on" diagnostic. Plain-language guidance + a paste-ready command sequence.</p></div>
243
+ <div class="card"><h4 data-copy="/qualia-map">/qualia-map</h4><p>Inherited an existing codebase? Map it first (architecture, stack, conventions) before <code>/qualia-new</code>.</p></div>
244
+ </div>
245
+
246
+ <div class="group-label">◆ Build · idea to working code</div>
247
+ <div class="cards">
248
+ <div class="card"><h4 data-copy="/qualia-new">/qualia-new</h4><p>Start a project. Interview, research, planning substrate, pick a preset.</p></div>
249
+ <div class="card"><h4 data-copy="/qualia-scope">/qualia-scope</h4><p>Adversarial intake that grills the requirements before you plan, so v1 is the right v1.</p></div>
250
+ <div class="card"><h4 data-copy="/qualia-plan">/qualia-plan</h4><p>Break the current phase into wave-grouped, verifiable tasks.</p></div>
251
+ <div class="card"><h4 data-copy="/qualia-build">/qualia-build</h4><p>Execute the plan with fresh builder agents and atomic per-task commits.</p></div>
252
+ <div class="card"><h4 data-copy="/qualia-feature">/qualia-feature</h4><p>One small thing (1–5 files), auto-scoped. Skips the full phase machinery.</p></div>
253
+ <div class="card"><h4 data-copy="/qualia-fix">/qualia-fix</h4><p>Something's broken. Root-cause investigation, then a targeted repair.</p></div>
254
+ </div>
255
+
256
+ <div class="group-label">◆ Check & ship · make it real</div>
257
+ <div class="cards">
258
+ <div class="card"><h4 data-copy="/qualia-verify">/qualia-verify</h4><p>Goal-backward verification against acceptance criteria + design rubric.</p></div>
259
+ <div class="card"><h4 data-copy="/qualia-test">/qualia-test</h4><p>Write or run tests; <code>--tdd</code> drives a feature test-first.</p></div>
260
+ <div class="card"><h4 data-copy="/qualia-polish">/qualia-polish</h4><p>Visual quality pass: component, route, whole app, or a vibe pivot.</p></div>
261
+ <div class="card"><h4 data-copy="/qualia-review">/qualia-review</h4><p>Read-only production audit, severity-scored.</p></div>
262
+ <div class="card"><h4 data-copy="/qualia-ship">/qualia-ship</h4><p>Full deploy pipeline: gates → commit → deploy → verify live.</p></div>
263
+ </div>
264
+
265
+ <div class="group-label">◆ Maintain · close the loop</div>
266
+ <div class="cards">
267
+ <div class="card"><h4 data-copy="/qualia-report">/qualia-report</h4><p>Clock out. Generate and file your shift report (uploads to ERP when configured).</p></div>
268
+ <div class="card"><h4 data-copy="/qualia-learn">/qualia-learn</h4><p>Save a lesson, pattern, or client preference to the shared brain.</p></div>
269
+ <div class="card"><h4 data-copy="/qualia-milestone">/qualia-milestone</h4><p>Close the current milestone and open the next from the journey map.</p></div>
270
+ <div class="card"><h4 data-copy="/qualia-doctor">/qualia-doctor</h4><p>Health check the framework when something feels off.</p></div>
271
+ </div>
272
+ </section>
273
+
274
+ <!-- FIRST PROJECT -->
275
+ <section id="first" class="reveal">
276
+ <h2><span class="bar"></span> Your first project</h2>
277
+ <p class="sec-sub">A landing page, start to finish. The same shape works for anything bigger: just more Plan → Build → Verify loops.</p>
278
+ <div class="walk">
279
+ <div class="w"><span class="wn"></span><div class="wbody">
280
+ <h4>Install &amp; check</h4>
281
+ <p class="dim">Run <code>npx qualia-framework@latest install</code> (type <code>EMPLOYEE</code>), then <span class="cmd" data-copy="/qualia-doctor">/qualia-doctor<span class="ico">copy</span></span>. Green across the board? Go.</p>
282
+ </div></div>
283
+ <div class="w"><span class="wn"></span><div class="wbody">
284
+ <h4>Start the project</h4>
285
+ <p class="dim"><span class="cmd" data-copy="/qualia-new">/qualia-new<span class="ico">copy</span></span>: answer the short interview, and when asked, pick the <b>landing-page</b> preset. You now have a running skeleton and a phase plan, not a blank page.</p>
286
+ </div></div>
287
+ <div class="w"><span class="wn"></span><div class="wbody">
288
+ <h4>Plan → Build → Verify</h4>
289
+ <p class="dim">Walk the phase: <span class="cmd" data-copy="/qualia-plan">/qualia-plan<span class="ico">copy</span></span> <span class="cmd" data-copy="/qualia-build">/qualia-build<span class="ico">copy</span></span> <span class="cmd" data-copy="/qualia-verify">/qualia-verify<span class="ico">copy</span></span>. Repeat until verify passes. Stuck between steps? <code>/qualia</code>.</p>
290
+ </div></div>
291
+ <div class="w"><span class="wn"></span><div class="wbody">
292
+ <h4>Polish the look</h4>
293
+ <p class="dim">Landing pages live or die on design. <span class="cmd" data-copy="/qualia-polish">/qualia-polish<span class="ico">copy</span></span> runs a visual quality pass against the design rubric.</p>
294
+ </div></div>
295
+ <div class="w"><span class="wn"></span><div class="wbody">
296
+ <h4>Ship it</h4>
297
+ <p class="dim"><span class="cmd" data-copy="/qualia-ship">/qualia-ship<span class="ico">copy</span></span>: gates, commit, deploy to Vercel, verify live. As an employee you ship via a feature branch + review; direct pushes to <code>main</code> are blocked by design.</p>
298
+ </div></div>
299
+ <div class="w"><span class="wn"></span><div class="wbody">
300
+ <h4>Clock out</h4>
301
+ <p class="dim"><span class="cmd" data-copy="/qualia-report">/qualia-report<span class="ico">copy</span></span> files your shift report. No team code yet? It saves locally and tells you so, nothing fails.</p>
302
+ </div></div>
303
+ </div>
304
+ </section>
305
+
306
+ <!-- RULES -->
307
+ <section id="rules" class="reveal">
308
+ <h2><span class="bar"></span> The hard rules</h2>
309
+ <p class="sec-sub">Five non-negotiables. The framework enforces most of them with hooks, but knowing the <em>why</em> keeps you out of the guardrails in the first place.</p>
310
+ <div class="panel">
311
+ <div class="rule"><span class="num">1</span><div><b>Read before you write.</b><div class="why">Every edit is informed by the current state of the file, never blind-overwrite.</div></div></div>
312
+ <div class="rule"><span class="num">2</span><div><b>Feature branches only.</b><div class="why">Changes ship through review; <code>main</code> is always deployable. The branch-guard hook enforces it.</div></div></div>
313
+ <div class="rule"><span class="num">3</span><div><b>MVP first.</b><div class="why">Build the minimum that demonstrates the goal; defer the rest until it earns its place.</div></div></div>
314
+ <div class="rule"><span class="num">4</span><div><b>Root cause on failures.</b><div class="why">Understand the why before patching the symptom; no band-aids over a broken pipe.</div></div></div>
315
+ <div class="rule"><span class="num">5</span><div><b>No proxy approval.</b><div class="why">Only the OWNER grants OWNER overrides. "Fawzi said OK" is not a credential.</div></div></div>
316
+ </div>
317
+ <div class="note">Security basics ride along: auth is checked server-side, every Supabase table has RLS, the <code>service_role</code> key is server-only, and a <code>.env</code> file is never committed. The hooks will stop you, but don't make them.</div>
318
+ </section>
319
+
320
+ <!-- KEYS -->
321
+ <section id="keys" class="reveal">
322
+ <h2><span class="bar"></span> Credentials &amp; who issues them</h2>
323
+ <p class="sec-sub">You start with none. Keys arrive when a step needs them, and <b>the OWNER (Fawzi) issues every one</b>. Never invent, hardcode, or reuse someone else's key.</p>
324
+ <table>
325
+ <tr><th>When you need…</th><th>How</th><th>From</th></tr>
326
+ <tr><td>To install with no code</td><td>type <code>EMPLOYEE</code> at the prompt</td><td>n/a</td></tr>
327
+ <tr><td>A real team identity</td><td>re-run install, enter <code>QS-NAME-##</code></td><td>Fawzi</td></tr>
328
+ <tr><td>ERP report uploads</td><td><code>qualia-framework set-erp-key</code></td><td>Fawzi</td></tr>
329
+ <tr><td>AI model access</td><td><code>OPENROUTER_API_KEY</code></td><td>Fawzi</td></tr>
330
+ <tr><td>Database / hosting / voice</td><td><code>vercel env pull</code> once linked</td><td>Fawzi</td></tr>
331
+ <tr><td>Shared team knowledge</td><td><code>QUALIA_KNOWLEDGE_SOURCE=… install</code></td><td>repo access from Fawzi</td></tr>
332
+ </table>
333
+ <p class="dim">If a step says "ask Fawzi", that's who to ask. The framework degrades gracefully when a key is missing: it tells you what it needs rather than failing silently.</p>
334
+ </section>
335
+
336
+ <!-- LOST -->
337
+ <section id="lost" class="reveal">
338
+ <h2><span class="bar"></span> When you're lost</h2>
339
+ <p class="sec-sub">There is exactly one command to remember when nothing else makes sense.</p>
340
+ <div class="panel" style="text-align:center;padding:34px">
341
+ <span class="cmd" data-copy="/qualia" style="font-size:18px;padding:12px 16px 12px 22px">/qualia<span class="ico" style="font-size:13px">copy</span></span>
342
+ <p class="dim" style="margin-top:16px;max-width:52ch;margin-inline:auto">It reads where your project is and tells you the precise next move. If you only ever memorise one thing from this manual, memorise this. For a deeper "something feels off" read, use <code>/qualia-idk</code>.</p>
343
+ </div>
344
+ </section>
345
+
346
+ <footer>
347
+ <p>Qualia Framework · Field Manual · Qualia Solutions, Nicosia 🇨🇾 · a web/AI agency.<br>
348
+ The framework is the source of truth; if this manual and a command ever disagree, the command wins. Built to be read once and kept nearby.</p>
349
+ </footer>
350
+ </main>
351
+ </div>
352
+
353
+ <script>
354
+ (function(){
355
+ // ── copy-to-clipboard on any [data-copy] (command chips & cards) ──
356
+ function flash(el, label){
357
+ var prev = el.querySelector('.ico');
358
+ el.classList.add('copied');
359
+ if(prev){ var t=prev.textContent; prev.textContent='copied ✓'; setTimeout(function(){prev.textContent=t;el.classList.remove('copied');},1100); }
360
+ else { setTimeout(function(){el.classList.remove('copied');},1100); }
361
+ }
362
+ document.querySelectorAll('[data-copy]').forEach(function(el){
363
+ el.style.cursor='pointer';
364
+ el.setAttribute('title','Click to copy');
365
+ el.addEventListener('click',function(){
366
+ var txt = el.getAttribute('data-copy');
367
+ navigator.clipboard && navigator.clipboard.writeText(txt).then(function(){flash(el);}).catch(function(){flash(el);});
368
+ });
369
+ });
370
+
371
+ // ── scroll-spy: highlight the active nav link ──
372
+ var links = Array.prototype.slice.call(document.querySelectorAll('nav.side a'));
373
+ var map = {};
374
+ links.forEach(function(a){ map[a.getAttribute('href').slice(1)] = a; });
375
+ var spy = new IntersectionObserver(function(entries){
376
+ entries.forEach(function(e){
377
+ if(e.isIntersecting){
378
+ links.forEach(function(a){a.classList.remove('active');});
379
+ var a = map[e.target.id]; if(a) a.classList.add('active');
380
+ }
381
+ });
382
+ },{rootMargin:'-45% 0px -50% 0px',threshold:0});
383
+ document.querySelectorAll('section[id]').forEach(function(s){spy.observe(s);});
384
+
385
+ // close mobile nav on link tap
386
+ links.forEach(function(a){a.addEventListener('click',function(){document.querySelector('nav.side').classList.remove('open');});});
387
+
388
+ // ── reveal on scroll ──
389
+ var rev = new IntersectionObserver(function(entries){
390
+ entries.forEach(function(e){ if(e.isIntersecting){ e.target.classList.add('in'); rev.unobserve(e.target);} });
391
+ },{rootMargin:'0px 0px -10% 0px',threshold:.08});
392
+ document.querySelectorAll('.reveal').forEach(function(el){rev.observe(el);});
393
+ })();
394
+ </script>
395
+ </body>
396
+ </html>
@@ -167,17 +167,37 @@ function maybeDrainErpQueue() {
167
167
  } catch {}
168
168
  }
169
169
 
170
+ function cmpVersions(a, b) {
171
+ // Returns >0 if a>b, <0 if a<b, 0 if equal. Tolerates missing/non-numeric
172
+ // segments by treating them as 0. Pure semver-major.minor.patch compare.
173
+ const pa = String(a || "0").split(".").map((n) => parseInt(n, 10) || 0);
174
+ const pb = String(b || "0").split(".").map((n) => parseInt(n, 10) || 0);
175
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
176
+ const d = (pa[i] || 0) - (pb[i] || 0);
177
+ if (d !== 0) return d;
178
+ }
179
+ return 0;
180
+ }
181
+
170
182
  function maybeRenderUpdateBanner() {
171
183
  // EMPLOYEE-only sticky banner. auto-update.js writes NOTIF_FILE when a new
172
184
  // version is detected; we render it every session until the user actually
173
- // runs `npx qualia-framework@latest install`. The file is cleared by
174
- // auto-update.js once the install completes or the version catches up.
185
+ // runs `npx qualia-framework@latest install`. auto-update.js clears the file
186
+ // when it next runs and finds the version caught up — but it is throttled, so
187
+ // between an install and that next run the notif can be stale. We therefore
188
+ // self-validate here against the installed version (.qualia-config.json) and
189
+ // clear+skip a stale notice rather than show a false "update available".
175
190
  if (!fs.existsSync(NOTIF_FILE) || !fs.existsSync(UI)) return;
176
191
  try {
177
192
  const notif = JSON.parse(fs.readFileSync(NOTIF_FILE, "utf8"));
178
- if (notif && notif.current && notif.latest) {
179
- runUi("update", notif.current, notif.latest);
193
+ if (!notif || !notif.current || !notif.latest) return;
194
+ const installed = readConfig().version;
195
+ if (installed && cmpVersions(installed, notif.latest) >= 0) {
196
+ // Already at or past the advertised latest — the notice is stale.
197
+ try { fs.unlinkSync(NOTIF_FILE); } catch {}
198
+ return;
180
199
  }
200
+ runUi("update", notif.current, notif.latest);
181
201
  } catch {}
182
202
  }
183
203
 
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * UserPromptSubmit hook — per-session framework-usage capture.
4
+ *
5
+ * Records, into `.planning/.session-usage.json` of the active project:
6
+ * - command_usage : a histogram of qualia slash-commands the engineer fired
7
+ * - prompt_samples: the engineer's real prompts (opt-in), for the ERP
8
+ * prompt-quality judge
9
+ *
10
+ * `report-payload.js` folds both into the /qualia-report clock-out payload, and
11
+ * `/qualia-report` clears the file after a successful upload. This is what feeds
12
+ * the ERP performance audit's "framework usage & prompting" pillar (command
13
+ * volume + diversity, and LLM-judged prompt quality).
14
+ *
15
+ * Privacy: prompt capture is opt-in via `erp.capturePrompts` in
16
+ * ~/.claude/.qualia-config.json (default ON for the internal team; set to false
17
+ * to record command counts only). The file is a .planning dotfile and is
18
+ * deleted at clock-out — it must never be committed.
19
+ *
20
+ * Never blocks: any error exits 0 with no stdout (adds no context to the prompt).
21
+ */
22
+ const fs = require('fs');
23
+ const os = require('os');
24
+ const path = require('path');
25
+
26
+ const MAX_SAMPLES = 60;
27
+ const MAX_SAMPLE_LEN = 8000;
28
+
29
+ function readJson(file, fallback) {
30
+ try {
31
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
32
+ } catch {
33
+ return fallback;
34
+ }
35
+ }
36
+
37
+ function capturePromptsEnabled(home) {
38
+ const cfg =
39
+ readJson(path.join(home, '.claude', '.qualia-config.json'), null) ||
40
+ readJson(path.join(home, '.codex', '.qualia-config.json'), {});
41
+ return !cfg || !cfg.erp || cfg.erp.capturePrompts !== false;
42
+ }
43
+
44
+ function main() {
45
+ let raw = '';
46
+ try {
47
+ raw = fs.readFileSync(0, 'utf8');
48
+ } catch {
49
+ process.exit(0);
50
+ }
51
+ let input = {};
52
+ try {
53
+ input = JSON.parse(raw);
54
+ } catch {
55
+ process.exit(0);
56
+ }
57
+
58
+ const prompt = typeof input.prompt === 'string' ? input.prompt : '';
59
+ const cwd = input.cwd || input.cwd_path || process.cwd();
60
+ if (!prompt.trim()) process.exit(0);
61
+
62
+ // Only record inside a Qualia project (has .planning/).
63
+ const planningDir = path.join(cwd, '.planning');
64
+ if (!fs.existsSync(planningDir)) process.exit(0);
65
+
66
+ const usageFile = path.join(planningDir, '.session-usage.json');
67
+ const usage = readJson(usageFile, { command_usage: {}, prompt_samples: [] });
68
+ if (!usage.command_usage || typeof usage.command_usage !== 'object') usage.command_usage = {};
69
+ if (!Array.isArray(usage.prompt_samples)) usage.prompt_samples = [];
70
+
71
+ // Count a qualia slash-command if one appears as a token in the prompt.
72
+ const m = prompt.match(/(?:^|\s)\/(qualia[a-z0-9-]*)/i);
73
+ if (m) {
74
+ const cmd = m[1].toLowerCase();
75
+ usage.command_usage[cmd] = (usage.command_usage[cmd] || 0) + 1;
76
+ }
77
+
78
+ // Sample the real prompt for the prompt-quality judge (opt-in, disclosed).
79
+ if (capturePromptsEnabled(os.homedir())) {
80
+ // Transparency: tell the engineer once per shift that prompts are recorded
81
+ // and how to turn it off. stderr so it's seen but never enters model
82
+ // context. The flag rides in the usage file, which is cleared at clock-out,
83
+ // so the notice reappears each new shift. Best-effort — never blocks.
84
+ if (!usage.notice_shown) {
85
+ try {
86
+ process.stderr.write(
87
+ '\x1b[38;2;80;90;100m[qualia] This session records your /qualia command usage and ' +
88
+ 'prompt samples for the team performance audit. Opt out anytime: set ' +
89
+ 'erp.capturePrompts=false in ~/.claude/.qualia-config.json\x1b[0m\n'
90
+ );
91
+ } catch { /* never block the prompt */ }
92
+ usage.notice_shown = true;
93
+ }
94
+ usage.prompt_samples.push(prompt.trim().slice(0, MAX_SAMPLE_LEN));
95
+ if (usage.prompt_samples.length > MAX_SAMPLES) {
96
+ usage.prompt_samples = usage.prompt_samples.slice(-MAX_SAMPLES);
97
+ }
98
+ }
99
+
100
+ try {
101
+ fs.writeFileSync(usageFile, JSON.stringify(usage));
102
+ } catch {
103
+ /* best-effort; never block the prompt */
104
+ }
105
+ process.exit(0);
106
+ }
107
+
108
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qualia-framework",
3
- "version": "6.8.1",
3
+ "version": "6.9.2",
4
4
  "description": "Claude Code and Codex workflow framework by Qualia Solutions. Plan, build, verify, ship.",
5
5
  "bin": {
6
6
  "qualia-framework": "./bin/cli.js"
@@ -52,6 +52,8 @@
52
52
  "docs/release.md",
53
53
  "docs/changelog-v6.html",
54
54
  "docs/onboarding.html",
55
+ "docs/qualia-manual.html",
56
+ "docs/EMPLOYEE-QUICKSTART.md",
55
57
  "CLAUDE.md",
56
58
  "AGENTS.md",
57
59
  "guide.md",