qualia-framework 6.8.0 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/bin/install.js +212 -17
  3. package/bin/state.js +70 -5
  4. package/docs/EMPLOYEE-QUICKSTART.md +162 -0
  5. package/package.json +2 -1
  6. package/skills/qualia-doctor/SKILL.md +62 -0
  7. package/skills/qualia-new/REFERENCE.md +7 -0
  8. package/skills/qualia-new/SKILL.md +42 -0
  9. package/skills/qualia-report/SKILL.md +13 -0
  10. package/templates/stacks/README.md +110 -0
  11. package/templates/stacks/ai-agent/env.required.json +44 -0
  12. package/templates/stacks/ai-agent/phases.md +53 -0
  13. package/templates/stacks/ai-agent/scaffold/.env.example +12 -0
  14. package/templates/stacks/ai-agent/scaffold/README.md +31 -0
  15. package/templates/stacks/ai-agent/scaffold/app/api/chat/route.ts +33 -0
  16. package/templates/stacks/ai-agent/scaffold/app/globals.css +13 -0
  17. package/templates/stacks/ai-agent/scaffold/app/layout.tsx +19 -0
  18. package/templates/stacks/ai-agent/scaffold/app/page.tsx +12 -0
  19. package/templates/stacks/ai-agent/scaffold/evals/cases.json +23 -0
  20. package/templates/stacks/ai-agent/scaffold/lib/openrouter/client.ts +51 -0
  21. package/templates/stacks/ai-agent/scaffold/lib/prompts/system.ts +6 -0
  22. package/templates/stacks/ai-agent/scaffold/lib/supabase/client.ts +10 -0
  23. package/templates/stacks/ai-agent/scaffold/lib/supabase/server.ts +28 -0
  24. package/templates/stacks/ai-agent/scaffold/next.config.mjs +7 -0
  25. package/templates/stacks/ai-agent/scaffold/package.json +29 -0
  26. package/templates/stacks/ai-agent/scaffold/postcss.config.mjs +7 -0
  27. package/templates/stacks/ai-agent/scaffold/supabase/migrations/0001_init.sql +41 -0
  28. package/templates/stacks/ai-agent/scaffold/tsconfig.json +21 -0
  29. package/templates/stacks/ai-agent/stack.json +9 -0
  30. package/templates/stacks/ai-agent/verify-checklist.md +31 -0
  31. package/templates/stacks/full-app/env.required.json +20 -0
  32. package/templates/stacks/full-app/phases.md +45 -0
  33. package/templates/stacks/full-app/scaffold/.env.example +7 -0
  34. package/templates/stacks/full-app/scaffold/README.md +28 -0
  35. package/templates/stacks/full-app/scaffold/app/globals.css +14 -0
  36. package/templates/stacks/full-app/scaffold/app/layout.tsx +19 -0
  37. package/templates/stacks/full-app/scaffold/app/page.tsx +20 -0
  38. package/templates/stacks/full-app/scaffold/lib/supabase/client.ts +10 -0
  39. package/templates/stacks/full-app/scaffold/lib/supabase/server.ts +31 -0
  40. package/templates/stacks/full-app/scaffold/next.config.mjs +7 -0
  41. package/templates/stacks/full-app/scaffold/package.json +29 -0
  42. package/templates/stacks/full-app/scaffold/postcss.config.mjs +7 -0
  43. package/templates/stacks/full-app/scaffold/supabase/migrations/0001_init.sql +27 -0
  44. package/templates/stacks/full-app/scaffold/tsconfig.json +21 -0
  45. package/templates/stacks/full-app/stack.json +9 -0
  46. package/templates/stacks/full-app/verify-checklist.md +32 -0
  47. package/templates/stacks/internal-tool/env.required.json +20 -0
  48. package/templates/stacks/internal-tool/phases.md +45 -0
  49. package/templates/stacks/internal-tool/scaffold/.env.example +7 -0
  50. package/templates/stacks/internal-tool/scaffold/README.md +29 -0
  51. package/templates/stacks/internal-tool/scaffold/app/globals.css +13 -0
  52. package/templates/stacks/internal-tool/scaffold/app/layout.tsx +20 -0
  53. package/templates/stacks/internal-tool/scaffold/app/page.tsx +22 -0
  54. package/templates/stacks/internal-tool/scaffold/lib/supabase/client.ts +9 -0
  55. package/templates/stacks/internal-tool/scaffold/lib/supabase/server.ts +28 -0
  56. package/templates/stacks/internal-tool/scaffold/next.config.mjs +6 -0
  57. package/templates/stacks/internal-tool/scaffold/package.json +29 -0
  58. package/templates/stacks/internal-tool/scaffold/postcss.config.mjs +7 -0
  59. package/templates/stacks/internal-tool/scaffold/supabase/migrations/0001_init.sql +28 -0
  60. package/templates/stacks/internal-tool/scaffold/tsconfig.json +21 -0
  61. package/templates/stacks/internal-tool/stack.json +9 -0
  62. package/templates/stacks/internal-tool/verify-checklist.md +31 -0
  63. package/templates/stacks/landing-page/env.required.json +8 -0
  64. package/templates/stacks/landing-page/phases.md +42 -0
  65. package/templates/stacks/landing-page/scaffold/.env.example +3 -0
  66. package/templates/stacks/landing-page/scaffold/README.md +25 -0
  67. package/templates/stacks/landing-page/scaffold/app/globals.css +14 -0
  68. package/templates/stacks/landing-page/scaffold/app/layout.tsx +19 -0
  69. package/templates/stacks/landing-page/scaffold/app/page.tsx +21 -0
  70. package/templates/stacks/landing-page/scaffold/next.config.mjs +7 -0
  71. package/templates/stacks/landing-page/scaffold/package.json +26 -0
  72. package/templates/stacks/landing-page/scaffold/postcss.config.mjs +7 -0
  73. package/templates/stacks/landing-page/scaffold/tsconfig.json +21 -0
  74. package/templates/stacks/landing-page/stack.json +9 -0
  75. package/templates/stacks/landing-page/verify-checklist.md +28 -0
  76. package/tests/bin.test.sh +3 -3
  77. package/tests/state.test.sh +83 -0
@@ -0,0 +1,162 @@
1
+ # Qualia Framework — Employee Quickstart
2
+
3
+ A five-minute path from a fresh machine to a shipped, reported day of work. This is the route for a **new employee who does not have a team install code yet**. You can install and do real work in employee mode today; the OWNER (Fawzi) issues the keys that unlock ERP reporting and any direct provider integrations.
4
+
5
+ Who issues credentials: **the OWNER (Fawzi) issues every key** — team install codes, the ERP API key, OpenRouter / Supabase / Vercel / Retell / ElevenLabs / Telnyx credentials. If a step says "ask Fawzi", that is who to ask. Never share or reuse another person's key.
6
+
7
+ ---
8
+
9
+ ## The path
10
+
11
+ ```
12
+ install (employee mode) → /qualia-doctor → /qualia-new (pick preset) → build/verify loop → /qualia-ship → report
13
+ ```
14
+
15
+ ---
16
+
17
+ ## 1. Install — employee mode (no team code needed)
18
+
19
+ ```bash
20
+ npx qualia-framework@latest install
21
+ ```
22
+
23
+ At the prompt:
24
+
25
+ ```
26
+ Install code or "EMPLOYEE":
27
+ ```
28
+
29
+ - Have a team code (`QS-NAME-##`)? Enter it — you install as that team member.
30
+ - **No code yet?** Type **`EMPLOYEE`**. You install at the least-privilege role: feature branches only, no pushes to `main` (enforced by the `branch-guard` hook). The full framework — skills, agents, hooks, knowledge — is installed exactly the same.
31
+
32
+ What employee mode changes vs. a coded install:
33
+
34
+ | | Coded install (team member) | Employee mode (no code) |
35
+ |---|---|---|
36
+ | Role | OWNER or EMPLOYEE per code | EMPLOYEE |
37
+ | Skills / agents / hooks | full | full |
38
+ | Push to `main` | OWNER only | blocked |
39
+ | ERP reporting | on (with API key) | **off** until a code/key is set |
40
+ | `/qualia-report` | uploads to ERP | saves a **local** report file |
41
+
42
+ **Credentials this step needs:** none. That's the point — you can start immediately.
43
+
44
+ To upgrade to a real team identity later: ask Fawzi for your `QS-NAME-##` code, then re-run `npx qualia-framework install` and enter it. That flips ERP reporting back on (you'll also need the ERP API key — see step 6).
45
+
46
+ ### Optional: shared team knowledge mirror
47
+
48
+ The installer can pull a **read-only** copy of the team's shared knowledge wiki (`qualia-memory`) into `~/.claude/knowledge/shared/` so you start with the team's accumulated patterns and fixes. It is **opt-in and copy-on-install only** — not a live sync.
49
+
50
+ ```bash
51
+ # Local checkout of the knowledge repo:
52
+ QUALIA_KNOWLEDGE_SOURCE=/path/to/qualia-memory npx qualia-framework@latest install
53
+
54
+ # Or a git URL (ask Fawzi for access if the repo is private):
55
+ QUALIA_KNOWLEDGE_SOURCE=https://github.com/Qualiasolutions/qualia-memory.git \
56
+ npx qualia-framework@latest install
57
+ ```
58
+
59
+ - `QUALIA_KNOWLEDGE_SOURCE` — a local path **or** a git URL. Unset → the pull is skipped silently.
60
+ - `QUALIA_KNOWLEDGE_SUBPATH` — subdirectory inside the source to copy (default `wiki/_export`).
61
+ - The mirror lands at `~/.claude/knowledge/shared/` with every file marked read-only. Your own learnings still go through `/qualia-learn` into your personal knowledge files — the shared mirror is reference material, refreshed on each install/update.
62
+ - If the source is unreachable (no git, offline, missing path, private-repo auth fail) the installer **warns and continues** — it never blocks the install.
63
+
64
+ **Credentials this step needs:** read access to the `qualia-memory` repo if you use a private git URL — ask Fawzi.
65
+
66
+ ---
67
+
68
+ ## 2. `/qualia-doctor` — confirm the install is healthy
69
+
70
+ ```
71
+ /qualia-doctor
72
+ ```
73
+
74
+ Checks install integrity, hooks, project state, contracts, memory, and the ERP queue. In employee mode it will report ERP as disabled — that is expected and not an error. Fix anything it flags before starting real work.
75
+
76
+ **Credentials this step needs:** none.
77
+
78
+ ---
79
+
80
+ ## 3. `/qualia-new` — start a project (pick a preset)
81
+
82
+ ```
83
+ /qualia-new
84
+ ```
85
+
86
+ Runs the kickoff interview, researches the domain, and writes the planning substrate (`JOURNEY.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `CONTEXT.md`). When prompted, pick the project **preset / type** that matches what you're building (e.g. landing page, full app, AI agent, internal tool). The preset seeds the milestone arc so you're not planning from a blank page.
87
+
88
+ **Credentials this step may need:**
89
+ - `OPENROUTER_API_KEY` — for any AI-assisted research/generation. Ask Fawzi for one.
90
+ - Provider keys (Supabase, Vercel, etc.) are not needed yet — they come in when you wire those services.
91
+
92
+ ---
93
+
94
+ ## 4. Build / verify loop
95
+
96
+ Plan, build, and verify each phase:
97
+
98
+ ```
99
+ /qualia-plan # break the current phase into wave-grouped tasks
100
+ /qualia-build # execute the plan — builders + atomic commits
101
+ /qualia-verify # goal-backward check against acceptance criteria
102
+ ```
103
+
104
+ Iterate until the phase passes verification. Use `/qualia` at any point to ask "what's my next step?".
105
+
106
+ **Credentials this step needs:** whatever the feature touches —
107
+ - `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `SUPABASE_SERVICE_ROLE_KEY` for database work (service role key is **server-only**, never in client code).
108
+ - `OPENROUTER_API_KEY` for AI calls.
109
+ - Voice keys (`RETELL_API_KEY`, `ELEVENLABS_API_KEY`, `TELNYX_API_KEY`) for voice work.
110
+
111
+ Pull these into a project with `vercel env pull` once the project is linked. **Ask Fawzi for any key you don't have** — do not invent or hardcode keys, and never commit a `.env` file.
112
+
113
+ ---
114
+
115
+ ## 5. `/qualia-ship` — deploy
116
+
117
+ ```
118
+ /qualia-ship
119
+ ```
120
+
121
+ Runs the quality gates, commits, deploys (Vercel via CLI), and verifies. As an employee you ship through a **feature branch and review** — `branch-guard` blocks direct pushes to `main`. Deploys happen only through the CLI; GitHub auto-deploy is intentionally disabled.
122
+
123
+ **Credentials this step needs:**
124
+ - A Vercel login on the correct team (`vercel whoami`; `vercel link` if the project isn't linked). Ask Fawzi which Vercel team the project belongs to.
125
+ - Push access to the GitHub repo (org `QualiasolutionsCY` or `SakaniQualia`). Ask Fawzi to be added.
126
+
127
+ ---
128
+
129
+ ## 6. Report — clock out
130
+
131
+ ```
132
+ /qualia-report
133
+ ```
134
+
135
+ Generates your shift report, commits it to `.planning/reports/report-{date}.md`, and (when configured) uploads it to the ERP.
136
+
137
+ **In employee mode (no team code), the report degrades gracefully:** it is generated and committed **locally**, and you'll see a clear message that it was saved locally because no team code is set. Nothing fails. To start uploading reports to the ERP:
138
+
139
+ 1. Get your team code (`QS-NAME-##`) from Fawzi and re-run `npx qualia-framework install` with it, **and**
140
+ 2. Set the ERP API key (ask Fawzi for it):
141
+ ```bash
142
+ printf '%s' "$QUALIA_ERP_KEY" | qualia-framework set-erp-key
143
+ ```
144
+ Verify with `qualia-framework erp-ping`.
145
+
146
+ After that, `/qualia-report` uploads automatically and retries on transient ERP outages.
147
+
148
+ **Credentials this step needs:** a team code + the ERP API key — both issued by Fawzi. Until then, local reports are the expected behavior.
149
+
150
+ ---
151
+
152
+ ## Quick reference
153
+
154
+ | Need | Command | Issued by |
155
+ |---|---|---|
156
+ | Install with no code | type `EMPLOYEE` at the prompt | — |
157
+ | Team code | re-run install, enter `QS-NAME-##` | Fawzi |
158
+ | ERP API key | `qualia-framework set-erp-key` (piped) | Fawzi |
159
+ | AI model access | `OPENROUTER_API_KEY` | Fawzi |
160
+ | Supabase / Vercel / Voice keys | `vercel env pull` once linked | Fawzi |
161
+ | Shared knowledge mirror | `QUALIA_KNOWLEDGE_SOURCE=... install` | repo access from Fawzi |
162
+ | "What's my next step?" | `/qualia` | — |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qualia-framework",
3
- "version": "6.8.0",
3
+ "version": "6.9.0",
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,7 @@
52
52
  "docs/release.md",
53
53
  "docs/changelog-v6.html",
54
54
  "docs/onboarding.html",
55
+ "docs/EMPLOYEE-QUICKSTART.md",
55
56
  "CLAUDE.md",
56
57
  "AGENTS.md",
57
58
  "guide.md",
@@ -112,6 +112,61 @@ If the queue fails with `401`, the ERP API key is invalid. Use:
112
112
  printf '%s' "$QUALIA_ERP_KEY" | qualia-framework set-erp-key
113
113
  ```
114
114
 
115
+ ## 7. Project Env & Auth Health
116
+
117
+ Verify the project has the env vars its stack preset requires, and that the CLIs the deploy pipeline needs are logged in. This is the gap that catches "it built fine locally but the deploy has no Supabase keys."
118
+
119
+ **Read the env contract.** `/qualia-new` writes it per stack preset to `.planning/env.required.json` (fallback `./env.required.json`). It is a JSON array of `{ name, purpose, howToObtain, ownerIssued }`. If neither file exists, print `Env: N/A (no env contract — run /qualia-new to lay down a stack preset)` and skip to CLI auth.
120
+
121
+ **Check each required var.** A var is PASS if it is present in the process env OR defined (non-empty value) in `.env.local`. Run this from the project root:
122
+
123
+ ```bash
124
+ ENVFILE=".planning/env.required.json"; [ -f "$ENVFILE" ] || ENVFILE="env.required.json"
125
+ if [ -f "$ENVFILE" ]; then
126
+ node -e '
127
+ const fs=require("fs");
128
+ const vars=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));
129
+ let local="";
130
+ try { local=fs.readFileSync(".env.local","utf8"); } catch {}
131
+ const inLocal=(n)=>new RegExp("^\\s*"+n+"\\s*=\\s*\\S","m").test(local);
132
+ for (const v of vars) {
133
+ const present = (process.env[v.name] && process.env[v.name].length>0) || inLocal(v.name);
134
+ if (present) { console.log("PASS "+v.name); continue; }
135
+ if (v.ownerIssued) {
136
+ console.log("FAIL "+v.name+" — MISSING. Owner-issued: ask the OWNER (Fawzi) for this key, then add it to .env.local");
137
+ } else {
138
+ console.log("FAIL "+v.name+" — MISSING. "+(v.howToObtain||"")+" Then add "+v.name+"=... to .env.local");
139
+ }
140
+ }
141
+ ' "$ENVFILE"
142
+ fi
143
+ ```
144
+
145
+ Print one PASS/FAIL line per var with the **exact** next action:
146
+ - Missing + `ownerIssued: true` → `ask the OWNER (Fawzi) for this key` (no self-serve command — only the OWNER issues it).
147
+ - Missing + `ownerIssued: false` → the var's `howToObtain` string, then `add {NAME}=... to .env.local`.
148
+ - Present → `PASS {NAME}`.
149
+
150
+ **Check CLI logins.** The deploy pipeline needs these authenticated. Each prints PASS or FAIL with the exact fix:
151
+
152
+ ```bash
153
+ # Vercel — needed for `vercel --prod`
154
+ vercel whoami >/dev/null 2>&1 && echo "PASS vercel (logged in)" \
155
+ || echo "FAIL vercel — not logged in. Fix: vercel login"
156
+
157
+ # Supabase — CLI present + authenticated (projects list needs auth; version proves install)
158
+ supabase projects list >/dev/null 2>&1 && echo "PASS supabase (authenticated)" \
159
+ || { supabase --version >/dev/null 2>&1 \
160
+ && echo "FAIL supabase — installed but not authenticated. Fix: supabase login" \
161
+ || echo "FAIL supabase — CLI missing. Fix: npm i -g supabase (or use npx supabase)"; }
162
+
163
+ # GitHub — needed for push / PRs
164
+ gh auth status >/dev/null 2>&1 && echo "PASS gh (authenticated)" \
165
+ || echo "FAIL gh — not logged in. Fix: gh auth login"
166
+ ```
167
+
168
+ Roll the worst result into the `Env` line of the Output block: all PASS → `PASS`; any owner-issued var missing → `BLOCKED (owner key needed)`; any other FAIL → `DEGRADED`.
169
+
115
170
  ## Output
116
171
 
117
172
  End with:
@@ -127,10 +182,14 @@ Planning hygiene: ...
127
182
  Memory: ...
128
183
  Design/UI: ...
129
184
  Employee experience: ...
185
+ Env: ...
186
+ CLI auth: ...
130
187
  ERP: ...
131
188
  Next: ...
132
189
  ```
133
190
 
191
+ `Env` summarizes section 7's env-var check (PASS / DEGRADED / BLOCKED (owner key needed) / N/A). `CLI auth` summarizes the vercel/supabase/gh login checks (PASS if all three are authenticated, else DEGRADED with the first failing CLI named).
192
+
134
193
  ## Rules
135
194
 
136
195
  1. Read diagnostics before repair.
@@ -138,3 +197,6 @@ Next: ...
138
197
  3. Treat missing contracts as degraded trust, not a project failure.
139
198
  4. Prefer reinstall for missing framework files.
140
199
  5. Prefer `state.js fix` only for malformed generated state.
200
+ 6. **Never print secret values.** The env check reports presence (PASS/FAIL) only — never echo a key's contents.
201
+ 7. **Owner-issued vars get the OWNER, not a command.** For a missing `ownerIssued: true` var, the only correct fix is "ask the OWNER (Fawzi) for this key" — never suggest a self-serve way to obtain it (per the no-proxy-approval rule).
202
+ 8. Missing env contract is `N/A`, not a failure — it means no stack preset was laid down yet (`/qualia-new`).
@@ -84,6 +84,13 @@ User-scoped v1 features:
84
84
  Template type: {template_type from config.json}
85
85
  If set, use ${QUALIA_TEMPLATES}/projects/{type}.md as the milestone arc starting point.
86
86
 
87
+ Stack preset: {stack_id from config.json}
88
+ If .planning/phases.md exists (laid down by the Step 5a stack preset), read it as the
89
+ seed phase plan for Milestone 1 — it is tuned to this stack's archetype. The runnable
90
+ scaffold for this stack is already in the project root, so Milestone 1's foundation
91
+ phase should build ON the scaffold (auth wiring, first migration, first feature),
92
+ not re-scaffold from scratch.
93
+
87
94
  <full_detail>{true if --full-detail, else false}</full_detail>
88
95
  - false (default): Milestone 1 gets full phase detail; M2..M{N-1} stay as sketches. Detail fills in when each milestone opens via /qualia-milestone.
89
96
  - true: every milestone (M1..Handoff) gets full phase-level detail in ROADMAP.md upfront. Useful when the client wants a fully-committed plan at kickoff.
@@ -124,6 +124,44 @@ If "More questions": re-invoke `/qualia-scope` for additional rounds. Otherwise
124
124
 
125
125
  From questioning answers, infer type → `website` | `ai-agent` | `voice-agent` | `mobile-app` | `null`. If matched, `cat ${QUALIA_TEMPLATES}/projects/{type}.md` gives suggested milestone arc. Store `template_type` for Step 13.
126
126
 
127
+ ### Step 5a. Stack Preset Gate + Instantiate (ONE question, then lay down the scaffold)
128
+
129
+ This is the **only** stack question. It selects one of four preset directories at `${QUALIA_TEMPLATES}/stacks/<id>/` and instantiates it. The preset carries the default tech, the env contract, the seed phase plan, and a runnable starter — so the project begins from a real skeleton, not an empty folder. Skip this step entirely on `--quick` (the quick wizard owns its own minimal layout).
130
+
131
+ Use **AskUserQuestion** (never a plain-text prompt):
132
+
133
+ - header: "Stack"
134
+ - question: "What kind of build is this? Pick one — it lays down the starter scaffold and the env it needs."
135
+ - options:
136
+ - "Landing page" — static marketing site, no database, no auth. (`landing-page`)
137
+ - "Full app" — authenticated product, Supabase + RLS + database. (`full-app`)
138
+ - "AI agent" — LLM/chat/voice agent, Supabase + OpenRouter. (`ai-agent`)
139
+ - "Internal tool" — staff portal, invite-only auth, role-gated. (`internal-tool`)
140
+
141
+ Map the answer to `STACK_ID` ∈ `{landing-page, full-app, ai-agent, internal-tool}`. Pre-select the option that matches `template_type` from Step 5 if one was detected (`website`→`landing-page`/`full-app`, `ai-agent`/`voice-agent`→`ai-agent`), but the user's pick always wins.
142
+
143
+ Then instantiate the preset (replace `<id>` with `STACK_ID`):
144
+
145
+ ```bash
146
+ PRESET="${QUALIA_TEMPLATES}/stacks/${STACK_ID}"
147
+
148
+ # 1. Lay down the starter scaffold into the project root (skeleton, not an app).
149
+ # -n: never clobber a file the user already created.
150
+ mkdir -p .planning
151
+ cp -Rn "${PRESET}/scaffold/." . 2>/dev/null || true
152
+
153
+ # 2. Copy the env contract so /qualia-doctor can check it.
154
+ cp "${PRESET}/env.required.json" .planning/env.required.json
155
+
156
+ # 3. Seed the phase plan from the preset (roadmapper refines it in Step 13).
157
+ cp "${PRESET}/phases.md" .planning/phases.md
158
+
159
+ # 4. Keep the per-stack Definition-of-Done where verify can find it.
160
+ cp "${PRESET}/verify-checklist.md" .planning/verify-checklist.md
161
+ ```
162
+
163
+ Record the chosen stack in `config.json` (Step 9) as `"stack_id": "${STACK_ID}"`. The seed `phases.md` is the roadmapper's starting point at Step 13 — it reads `.planning/phases.md` (preset plan) alongside `${QUALIA_TEMPLATES}/projects/{template_type}.md` (milestone-arc hint) and the research synthesis, then writes the final ROADMAP.md. The scaffold gives Milestone 1 a real foundation to build on instead of an empty directory.
164
+
127
165
  ### Step 6. Design Direction (frontend only)
128
166
 
129
167
  - header: "Design"
@@ -212,6 +250,7 @@ git commit -m "docs: PRODUCT.md — register, users, voice, anti-references"
212
250
  "mode": "interactive",
213
251
  "depth": "standard",
214
252
  "template_type": "{detected or null}",
253
+ "stack_id": "{landing-page | full-app | ai-agent | internal-tool}",
215
254
  "workflow": {
216
255
  "research": true,
217
256
  "plan_check": true,
@@ -220,6 +259,8 @@ git commit -m "docs: PRODUCT.md — register, users, voice, anti-references"
220
259
  }
221
260
  ```
222
261
 
262
+ `stack_id` is the preset chosen at Step 5a. It tells `/qualia-doctor` which env contract to expect and `/qualia-verify` which per-stack Definition-of-Done to load.
263
+
223
264
  **Note:** `workflow.research` is always `true`. It exists for telemetry but is no longer read as a gate.
224
265
 
225
266
  ### Step 10. Create DESIGN.md (frontend projects — OKLCH-first)
@@ -421,6 +462,7 @@ Do NOT use `--quick` for: client projects, anything with compliance stakes, anyt
421
462
  ## Rules
422
463
 
423
464
  1. **Project type is the first question, period.** Step 1 (Demo / Full / Quick) is the literal first interaction with the user — even before "what are you building". Every downstream step branches on the answer. Don't skip it, don't infer it, don't ask anything before it.
465
+ 1a. **One stack question, then a real scaffold.** Step 5a asks exactly ONE stack-preset question (`landing-page` / `full-app` / `ai-agent` / `internal-tool`) and then instantiates it: copies `scaffold/` into the project (never clobbering existing files), copies `env.required.json` → `.planning/env.required.json`, and copies `phases.md` → `.planning/phases.md`. The project starts from a runnable skeleton, not an empty folder. Skip this step on `--quick`. Record the choice as `config.json.stack_id`.
424
466
  2. **AskUserQuestion for every discrete-choice question.** Project type, brownfield gate, design vibe, client type, approval gate, auto-chain — all use the interactive UI. The ONLY free-text question in the kickoff flow is the Step 3 one-line pitch. No plain-text prompts for anything that has a closed set of answers.
425
467
  3. **No ad-hoc clarification questioning.** After Step 3 (one-line pitch), the next tool call is `/qualia-scope`. No "let me ask a few quick things first", no "that's too broad, can you clarify". Depth is the scope skill's job — not yours.
426
468
  4. **Discovery interview is mandatory.** Step 4 always invokes `/qualia-scope` in PROJECT MODE. No free-form questioning loop, no "I'll just sketch PROJECT.md from the user's first message." The interview is 8 questions for demo, 14 for full project.
@@ -126,12 +126,15 @@ fi
126
126
  ### Step 6 — Upload to ERP
127
127
 
128
128
  The full payload-builder + 3-attempt-retry logic lives unchanged from v4 — see the **ERP Upload** section below for the canonical implementation. Behavior summary:
129
+ - **No team code in config (employee mode)** → skip upload, report stays LOCAL only; tell the employee explicitly it was saved locally because no team code is set
129
130
  - ERP disabled in config → skip upload with an info line, note local commit
130
131
  - API key missing → warn with self-service fix instructions, skip upload
131
132
  - 401/422 → permanent failure, no retry, tell employee to ask Fawzi
132
133
  - Transient (timeout/5xx) → 3 attempts with 1s/3s/9s backoff
133
134
  - Success → "Uploaded as $CLIENT_REPORT_ID (ERP: {uuid})"
134
135
 
136
+ **No-team-code degrade (employee mode):** When the framework was installed in employee mode, `.qualia-config.json` has `code: ""` and `erp.enabled: false`. The report is still generated, written to `.planning/reports/report-{date}.md`, and committed locally (Steps 3 + 5). The ERP upload is skipped and the employee is told the report lives locally and how to enable ERP later (get a team code from Fawzi, or `qualia-framework set-erp-key`). This is a clean degrade, not an error.
137
+
135
138
  ### Step 7 — State + closing
136
139
 
137
140
  ```bash
@@ -148,6 +151,7 @@ node ${QUALIA_BIN}/qualia-ui.js info "Shift report submitted. You can clock out
148
151
 
149
152
  | Symptom | Likely cause | Self-service fix |
150
153
  |---|---|---|
154
+ | "Report saved locally, not uploaded" | No team code (employee-mode install) | Expected — report is committed locally. To upload to ERP, get a team code from Fawzi and re-run `npx qualia-framework install`, or set a key with `qualia-framework set-erp-key` |
151
155
  | "Could not allocate report ID" | tracking.json missing/corrupt | `cat .planning/tracking.json` to inspect, or restore from `git checkout HEAD -- .planning/tracking.json` |
152
156
  | "ERP API key missing" | `${QUALIA_HOME}/.erp-api-key` empty | `printf '%s' "$QUALIA_ERP_KEY" \| qualia-framework set-erp-key` (ask Fawzi for the key) |
153
157
  | "ERP auth failed (401)" | Key revoked or wrong | Ask Fawzi for a fresh key |
@@ -168,6 +172,15 @@ REPORT_FILE=".planning/reports/report-{date}.md"
168
172
  SUBMITTED_BY=$(git config user.name || echo "unknown")
169
173
  SUBMITTED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
170
174
 
175
+ # Team code presence — empty in employee-mode installs. No code → the report
176
+ # can't be attributed to a team member, so it degrades to a local-only report.
177
+ TEAM_CODE=$(node -e "try{const c=JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.claude/.qualia-config.json','utf8'));process.stdout.write((c.code||'').trim())}catch{}")
178
+ if [ -z "$TEAM_CODE" ] && [ "$DRY_RUN" != "true" ]; then
179
+ node ${QUALIA_BIN}/qualia-ui.js info "No team code configured (employee mode) — report saved LOCALLY at $REPORT_FILE, not uploaded to the ERP."
180
+ node ${QUALIA_BIN}/qualia-ui.js info "To enable ERP uploads: get a team code from Fawzi and re-run 'npx qualia-framework install', or 'printf '%s' \"\$QUALIA_ERP_KEY\" | qualia-framework set-erp-key'."
181
+ ERP_ENABLED="false"
182
+ fi
183
+
171
184
  # Idempotency key — deterministic per (client_report_id, submitted_at). A retry
172
185
  # of the same shift report carries the same key, so the ERP can dedupe at the
173
186
  # header level in addition to the UPSERT on (project_id, client_report_id).
@@ -0,0 +1,110 @@
1
+ # Project-Type Stack Presets
2
+
3
+ These presets turn the question *"what kind of project is this?"* into a runnable
4
+ starting point. When `qualia-new` asks the user to pick a project type, the chosen
5
+ preset supplies the env contract, the phase plan, the Definition-of-Done checklist,
6
+ and a minimal-but-real code scaffold.
7
+
8
+ This directory installs to `~/.claude/qualia-templates/stacks/` automatically — it
9
+ ships inside the `templates/` tree, which the installer copies wholesale. No
10
+ installer change is required to add or edit a preset.
11
+
12
+ ## The four stacks
13
+
14
+ | `id` | What it is | Database / auth | AI | Voice |
15
+ |-----------------|-------------------------------------------------------------------|--------------------------|----------|----------|
16
+ | `landing-page` | Static / SSG marketing site. No login, no DB. | none | none | none |
17
+ | `full-app` | Authenticated product: accounts, roles, dashboard, RLS-everywhere. | Supabase (auth + RLS) | optional | none |
18
+ | `ai-agent` | LLM / chat / tool-calling agent on top of the full-app base. | Supabase (+ pgvector) | OpenRouter | optional |
19
+ | `internal-tool` | Staff-only portal / admin tool. Same Supabase base as full-app. | Supabase (auth + RLS) | optional | none |
20
+
21
+ All stacks default to the Qualia standard: **Next.js 16 (App Router) + React 19 +
22
+ TypeScript + Tailwind + Vercel**, AI via **OpenRouter**, data via **Supabase**.
23
+
24
+ ## Preset contract (every `<id>/` directory has exactly this shape)
25
+
26
+ ```
27
+ templates/stacks/<id>/
28
+ stack.json metadata: id, title, description, archetype, defaultStack,
29
+ scaffoldEntry, whenToUse
30
+ env.required.json array of { name, purpose, howToObtain, ownerIssued }
31
+ phases.md the increment / phase plan tuned for this stack
32
+ verify-checklist.md the per-stack Definition-of-Done checklist
33
+ scaffold/ a minimal but REAL runnable starter (MVP, not a full app)
34
+ ```
35
+
36
+ ### `stack.json` fields
37
+
38
+ | Field | Meaning |
39
+ |-----------------|-------------------------------------------------------------------------------------|
40
+ | `id` | Stack id; must equal the directory name. |
41
+ | `title` | Human label shown in the `qualia-new` project-type picker. |
42
+ | `description` | One line describing what this stack builds. |
43
+ | `archetype` | The `references/archetypes/*.md` file whose DoD + Road this stack borrows. |
44
+ | `defaultStack` | The default tech string (Next.js / Supabase / OpenRouter / …). |
45
+ | `scaffoldEntry` | The file a developer opens first after the scaffold is laid down. |
46
+ | `whenToUse` | A short "pick this when…" sentence to disambiguate from neighbouring stacks. |
47
+
48
+ ### Stack → archetype mapping (DoD source of truth)
49
+
50
+ The stack ids are a delivery-facing rename of the archetype ids. The mapping keeps
51
+ `qualia-scope`'s archetype DoD grill and `qualia-doctor`'s env check consistent:
52
+
53
+ | Stack `id` | `archetype` (DoD source) |
54
+ |-----------------|---------------------------------|
55
+ | `landing-page` | `website` |
56
+ | `full-app` | `web-app` |
57
+ | `ai-agent` | `ai-agent` |
58
+ | `internal-tool` | `web-app` |
59
+
60
+ `internal-tool` and `landing-page` reuse `web-app` / `website` DoD respectively;
61
+ their `phases.md` and `verify-checklist.md` narrow that DoD to the stack's shape
62
+ (no public SEO for an internal tool, no auth for a landing page).
63
+
64
+ ### `env.required.json` fields
65
+
66
+ Each entry is an environment variable the stack needs to run:
67
+
68
+ | Field | Meaning |
69
+ |---------------|--------------------------------------------------------------------------------------|
70
+ | `name` | The env var name (e.g. `NEXT_PUBLIC_SUPABASE_URL`). |
71
+ | `purpose` | Why the stack needs it. |
72
+ | `howToObtain` | The exact step (or CLI command) to get the value. |
73
+ | `ownerIssued` | `true` if only the OWNER (Fawzi) can issue the key; `false` if self-serve. |
74
+
75
+ `ownerIssued: true` vars are ones a developer cannot mint themselves (paid third-party
76
+ API keys: OpenRouter, Retell, ElevenLabs, Telnyx). When such a var is missing,
77
+ `qualia-doctor` prints **"ask the OWNER (Fawzi) for this key"** instead of a self-serve
78
+ fix command.
79
+
80
+ ## How `qualia-new` consumes a preset
81
+
82
+ After the user picks a project type, `qualia-new`:
83
+
84
+ 1. Resolves the chosen `id` to `templates/stacks/<id>/`.
85
+ 2. Copies `env.required.json` → the new project's `.planning/env.required.json`
86
+ (creating `.planning/` if absent).
87
+ 3. Folds `phases.md` into the generated plan as the milestone-arc starting point.
88
+ 4. Lays down `scaffold/` into the project root (a runnable skeleton, then the
89
+ roadmapped phases build on it).
90
+
91
+ ## How `qualia-doctor` consumes a preset
92
+
93
+ `qualia-doctor` reads `.planning/env.required.json` (falling back to `./env.required.json`)
94
+ and, for each entry:
95
+
96
+ 1. Checks the var is present (in the shell env or in `.env.local`).
97
+ 2. Checks the relevant CLI logins: `vercel whoami`, `supabase projects list`
98
+ (or `supabase --version` for auth), `gh auth status`.
99
+ 3. Prints **PASS / FAIL** per item with the EXACT fix command.
100
+ 4. For `ownerIssued: true` vars whose value is missing, prints
101
+ **"ask the OWNER (Fawzi) for this key"** rather than a self-serve command.
102
+
103
+ ## Editing a preset
104
+
105
+ - Keep the scaffold MVP. A runnable skeleton, not a finished app — the roadmapped
106
+ phases earn the rest.
107
+ - Keep `env.required.json` accurate. A var that the scaffold does not actually read
108
+ should not be listed; a var the scaffold needs to boot must be.
109
+ - After editing any JSON, validate it parses:
110
+ `node -e "require('./templates/stacks/<id>/stack.json')"`.
@@ -0,0 +1,44 @@
1
+ [
2
+ {
3
+ "name": "NEXT_PUBLIC_SUPABASE_URL",
4
+ "purpose": "Supabase project URL — used by both client and server SDKs.",
5
+ "howToObtain": "Supabase Dashboard → Project Settings → API → Project URL, or `npx supabase projects list`.",
6
+ "ownerIssued": false
7
+ },
8
+ {
9
+ "name": "NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",
10
+ "purpose": "Public (anon/publishable) key for client-side Supabase calls. RLS protects data.",
11
+ "howToObtain": "Supabase Dashboard → Project Settings → API → Publishable/anon key.",
12
+ "ownerIssued": false
13
+ },
14
+ {
15
+ "name": "SUPABASE_SERVICE_ROLE_KEY",
16
+ "purpose": "Server-only service-role key. NEVER NEXT_PUBLIC_, never in a client component.",
17
+ "howToObtain": "Supabase Dashboard → Project Settings → API → service_role key.",
18
+ "ownerIssued": false
19
+ },
20
+ {
21
+ "name": "OPENROUTER_API_KEY",
22
+ "purpose": "Routes every LLM call through OpenRouter — never hardcode a single provider.",
23
+ "howToObtain": "Issued by Qualia. Ask the OWNER (Fawzi) for a key.",
24
+ "ownerIssued": true
25
+ },
26
+ {
27
+ "name": "RETELL_API_KEY",
28
+ "purpose": "Voice agent platform (only if the agent takes/makes phone calls).",
29
+ "howToObtain": "Issued by Qualia. Ask the OWNER (Fawzi) for a key.",
30
+ "ownerIssued": true
31
+ },
32
+ {
33
+ "name": "ELEVENLABS_API_KEY",
34
+ "purpose": "Voice synthesis / cloning / streaming (voice agents only).",
35
+ "howToObtain": "Issued by Qualia. Ask the OWNER (Fawzi) for a key.",
36
+ "ownerIssued": true
37
+ },
38
+ {
39
+ "name": "TELNYX_API_KEY",
40
+ "purpose": "Telephony / SIP for voice-agent phone numbers (voice agents only).",
41
+ "howToObtain": "Issued by Qualia. Ask the OWNER (Fawzi) for a key.",
42
+ "ownerIssued": true
43
+ }
44
+ ]
@@ -0,0 +1,53 @@
1
+ # AI Agent — Phase Plan
2
+
3
+ Stack: Next.js 16 (Vercel) · Supabase (Postgres + pgvector) · OpenRouter · Tailwind · Railway (workers, optional).
4
+ Archetype: `ai-agent`. Seed plan copied into ROADMAP.md by `/qualia-new`.
5
+ The differentiator is **Phase 3 — the eval gate**: no ship before evals are green.
6
+
7
+ ## Phase 1: Foundation & Data
8
+
9
+ **Goal:** Stack deployed to a Vercel preview; Supabase wired with RLS on every table; OpenRouter wired with a model + fallback.
10
+
11
+ **Success criteria:**
12
+ 1. Authenticated user can hit a stubbed endpoint; RLS verified as two users.
13
+ 2. Schema: conversations, messages, users (+ pgvector tables if RAG).
14
+ 3. OpenRouter wired with a model + fallback chain; secrets in env.
15
+ 4. Deploys to a Vercel preview URL.
16
+
17
+ ## Phase 2: Core Agent Loop
18
+
19
+ **Goal:** A real end-to-end conversation works (input → model → response → persist), with cost/latency logged from the first call.
20
+
21
+ **Success criteria:**
22
+ 1. Streaming chat works end-to-end and persists to Supabase.
23
+ 2. System prompt lives in source control — never hardcoded inline.
24
+ 3. Tool-calling scaffold present; RAG retrieval if applicable.
25
+ 4. Per-request token + latency + cost logged.
26
+
27
+ ## Phase 3: Evals & Guardrails (THE GATE)
28
+
29
+ **Goal:** The agent passes a measurable eval suite mapped to the success metric. Guardrails handle refusal, fallback, and tool failure.
30
+
31
+ **Success criteria:**
32
+ 1. Eval harness with pass/fail cases mapped to the success metric — green.
33
+ 2. Input validation; refusal/safety behavior; fallback on model failure; human-escalation path.
34
+ 3. Each tool: server-side validation, timeout + failure handling, idempotency on writes.
35
+ 4. Per-request + daily cost ceilings enforced. **No ship before this closes.**
36
+
37
+ ## Phase 4: App Surface & Polish
38
+
39
+ **Goal:** Auth flows, rate limiting, and a non-AI-looking design pass.
40
+
41
+ **Success criteria:**
42
+ 1. Auth flows + user management + rate limiting.
43
+ 2. DESIGN.md anti-slop pass; responsive; all async states incl. streaming.
44
+ 3. Product looks built, not generated.
45
+
46
+ ## Phase 5: Handoff
47
+
48
+ **Goal:** Security review, prod deploy (Vercel + Railway if a worker), real-call smoke, handover.
49
+
50
+ **Success criteria:**
51
+ 1. Secrets/env audit; GDPR posture (consent, retention, export/delete).
52
+ 2. Prod deploy; post-deploy smoke includes **real agent calls**, not just HTTP 200.
53
+ 3. Credentials, walkthrough, archive, `/qualia-report` to ERP.
@@ -0,0 +1,12 @@
1
+ # Supabase
2
+ NEXT_PUBLIC_SUPABASE_URL=
3
+ NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
4
+ SUPABASE_SERVICE_ROLE_KEY=
5
+
6
+ # AI — route ALL LLM calls through OpenRouter. Ask the OWNER (Fawzi) for a key.
7
+ OPENROUTER_API_KEY=
8
+
9
+ # Voice (only for voice agents). Owner-issued — ask Fawzi.
10
+ # RETELL_API_KEY=
11
+ # ELEVENLABS_API_KEY=
12
+ # TELNYX_API_KEY=
@@ -0,0 +1,31 @@
1
+ # AI Agent
2
+
3
+ LLM / chat / agent — Next.js 16 + Supabase + OpenRouter (+ optional Retell/ElevenLabs/Telnyx voice).
4
+
5
+ ## Run
6
+
7
+ ```bash
8
+ npm install
9
+ cp .env.example .env.local # fill Supabase keys + OPENROUTER_API_KEY (ask Fawzi)
10
+ npx supabase db push
11
+ npm run dev # http://localhost:3000
12
+ curl -X POST localhost:3000/api/chat -H 'content-type: application/json' \
13
+ -d '{"message":"hello"}'
14
+ ```
15
+
16
+ ## Where things live
17
+
18
+ - `app/api/chat/route.ts` — the agent endpoint (input validation + routing).
19
+ - `lib/openrouter/client.ts` — the ONLY seam that talks to the LLM. Model + fallback chain here.
20
+ - `lib/prompts/system.ts` — system prompt in source control, never inline.
21
+ - `lib/supabase/server.ts` — server adapter (mutations, RLS).
22
+ - `supabase/migrations/` — conversations + messages, RLS from the first migration.
23
+ - `evals/cases.json` — **the ship gate**. No ship before the suite is green (Phase 3).
24
+
25
+ ## Non-negotiables
26
+
27
+ - All LLM calls through OpenRouter — never hardcode a provider.
28
+ - Evals are the finish line, not "it replied".
29
+ - `service_role` + `OPENROUTER_API_KEY` server-only, never logged.
30
+
31
+ This is an MVP skeleton. Build the streaming loop, persistence, and evals per `.planning/ROADMAP.md`.