qualia-framework 2.6.0 → 3.1.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 (328) hide show
  1. package/CLAUDE.md +63 -0
  2. package/README.md +108 -30
  3. package/agents/builder.md +110 -0
  4. package/agents/planner.md +186 -0
  5. package/agents/qa-browser.md +186 -0
  6. package/agents/verifier.md +369 -0
  7. package/bin/cli.js +691 -492
  8. package/bin/install.js +622 -0
  9. package/bin/qualia-ui.js +284 -0
  10. package/bin/state.js +824 -0
  11. package/bin/statusline.js +252 -0
  12. package/docs/erp-contract.md +161 -0
  13. package/guide.md +63 -0
  14. package/hooks/auto-update.js +117 -0
  15. package/hooks/block-env-edit.js +52 -0
  16. package/hooks/branch-guard.js +68 -0
  17. package/hooks/migration-guard.js +83 -0
  18. package/hooks/pre-compact.js +52 -0
  19. package/hooks/pre-deploy-gate.js +149 -0
  20. package/hooks/pre-push.js +53 -0
  21. package/hooks/session-start.js +126 -0
  22. package/package.json +30 -20
  23. package/rules/design-reference.md +179 -0
  24. package/rules/frontend.md +126 -0
  25. package/rules/infrastructure.md +87 -0
  26. package/skills/qualia/SKILL.md +88 -0
  27. package/skills/qualia-build/SKILL.md +115 -0
  28. package/skills/qualia-debug/SKILL.md +87 -0
  29. package/skills/qualia-design/SKILL.md +99 -0
  30. package/skills/qualia-handoff/SKILL.md +66 -0
  31. package/skills/qualia-help/SKILL.md +60 -0
  32. package/skills/qualia-idk/SKILL.md +8 -0
  33. package/skills/qualia-learn/SKILL.md +111 -0
  34. package/skills/qualia-new/SKILL.md +323 -0
  35. package/skills/qualia-pause/SKILL.md +63 -0
  36. package/skills/qualia-plan/SKILL.md +101 -0
  37. package/skills/qualia-polish/SKILL.md +207 -0
  38. package/skills/qualia-quick/SKILL.md +37 -0
  39. package/skills/qualia-report/SKILL.md +114 -0
  40. package/skills/qualia-resume/SKILL.md +49 -0
  41. package/skills/qualia-review/SKILL.md +161 -0
  42. package/skills/qualia-ship/SKILL.md +90 -0
  43. package/skills/qualia-skill-new/SKILL.md +167 -0
  44. package/skills/qualia-task/SKILL.md +91 -0
  45. package/skills/qualia-test/SKILL.md +134 -0
  46. package/skills/qualia-verify/SKILL.md +113 -0
  47. package/templates/DESIGN.md +475 -0
  48. package/templates/help.html +476 -0
  49. package/templates/plan.md +42 -0
  50. package/templates/project.md +22 -0
  51. package/templates/state.md +27 -0
  52. package/templates/tracking.json +20 -0
  53. package/tests/bin.test.sh +687 -0
  54. package/tests/hooks.test.sh +384 -0
  55. package/tests/runner.js +1956 -0
  56. package/tests/state.test.sh +713 -0
  57. package/tests/statusline.test.sh +243 -0
  58. package/bin/collect-metrics.sh +0 -62
  59. package/framework/.claudeignore +0 -51
  60. package/framework/CLAUDE.md +0 -51
  61. package/framework/MCP_SETUP.md +0 -229
  62. package/framework/agents/architecture-strategist.md +0 -53
  63. package/framework/agents/backend-agent.md +0 -150
  64. package/framework/agents/code-simplicity-reviewer.md +0 -86
  65. package/framework/agents/frontend-agent.md +0 -111
  66. package/framework/agents/kieran-typescript-reviewer.md +0 -96
  67. package/framework/agents/performance-oracle.md +0 -111
  68. package/framework/agents/qualia-codebase-mapper.md +0 -761
  69. package/framework/agents/qualia-debugger.md +0 -1204
  70. package/framework/agents/qualia-executor.md +0 -882
  71. package/framework/agents/qualia-integration-checker.md +0 -424
  72. package/framework/agents/qualia-phase-researcher.md +0 -457
  73. package/framework/agents/qualia-plan-checker.md +0 -700
  74. package/framework/agents/qualia-planner.md +0 -1245
  75. package/framework/agents/qualia-project-researcher.md +0 -603
  76. package/framework/agents/qualia-research-synthesizer.md +0 -200
  77. package/framework/agents/qualia-roadmapper.md +0 -606
  78. package/framework/agents/qualia-verifier.md +0 -686
  79. package/framework/agents/red-team-qa.md +0 -130
  80. package/framework/agents/security-auditor.md +0 -72
  81. package/framework/agents/team-orchestrator.md +0 -229
  82. package/framework/agents/teams/framework-audit-team.md +0 -66
  83. package/framework/agents/teams/full-stack-team.md +0 -48
  84. package/framework/agents/teams/optimize-team.md +0 -53
  85. package/framework/agents/teams/review-team.md +0 -70
  86. package/framework/agents/teams/ship-team.md +0 -86
  87. package/framework/agents/test-agent.md +0 -182
  88. package/framework/hooks/auto-format.sh +0 -54
  89. package/framework/hooks/block-env-edit.sh +0 -42
  90. package/framework/hooks/branch-guard.sh +0 -43
  91. package/framework/hooks/confirm-delete.sh +0 -59
  92. package/framework/hooks/migration-validate.sh +0 -77
  93. package/framework/hooks/notification-speak.sh +0 -16
  94. package/framework/hooks/pre-commit.sh +0 -100
  95. package/framework/hooks/pre-compact.sh +0 -56
  96. package/framework/hooks/pre-deploy-gate.sh +0 -160
  97. package/framework/hooks/qualia-colors.sh +0 -32
  98. package/framework/hooks/retention-cleanup.sh +0 -62
  99. package/framework/hooks/save-session-state.sh +0 -185
  100. package/framework/hooks/session-context-loader.sh +0 -96
  101. package/framework/hooks/session-learn.sh +0 -32
  102. package/framework/hooks/skill-announce.sh +0 -123
  103. package/framework/hooks/tool-error-announce.sh +0 -27
  104. package/framework/install.ps1 +0 -323
  105. package/framework/install.sh +0 -313
  106. package/framework/qualia-framework/VERSION +0 -1
  107. package/framework/qualia-framework/assets/qualia-logo.png +0 -0
  108. package/framework/qualia-framework/bin/collect-metrics.sh +0 -67
  109. package/framework/qualia-framework/bin/generate-report-docx.py +0 -429
  110. package/framework/qualia-framework/bin/qualia-tools.js +0 -2201
  111. package/framework/qualia-framework/bin/qualia-tools.test.js +0 -1054
  112. package/framework/qualia-framework/references/checkpoints.md +0 -775
  113. package/framework/qualia-framework/references/completion-checklists.md +0 -359
  114. package/framework/qualia-framework/references/continuation-format.md +0 -249
  115. package/framework/qualia-framework/references/continuation-prompt.md +0 -97
  116. package/framework/qualia-framework/references/decimal-phase-calculation.md +0 -65
  117. package/framework/qualia-framework/references/design-quality.md +0 -56
  118. package/framework/qualia-framework/references/employee-guide.md +0 -167
  119. package/framework/qualia-framework/references/git-integration.md +0 -254
  120. package/framework/qualia-framework/references/git-planning-commit.md +0 -50
  121. package/framework/qualia-framework/references/model-profile-resolution.md +0 -32
  122. package/framework/qualia-framework/references/model-profiles.md +0 -73
  123. package/framework/qualia-framework/references/phase-argument-parsing.md +0 -61
  124. package/framework/qualia-framework/references/planning-config.md +0 -195
  125. package/framework/qualia-framework/references/questioning.md +0 -141
  126. package/framework/qualia-framework/references/tdd.md +0 -263
  127. package/framework/qualia-framework/references/ui-brand.md +0 -160
  128. package/framework/qualia-framework/references/verification-patterns.md +0 -612
  129. package/framework/qualia-framework/templates/DEBUG.md +0 -159
  130. package/framework/qualia-framework/templates/DESIGN.md +0 -81
  131. package/framework/qualia-framework/templates/UAT.md +0 -247
  132. package/framework/qualia-framework/templates/codebase/architecture.md +0 -255
  133. package/framework/qualia-framework/templates/codebase/concerns.md +0 -310
  134. package/framework/qualia-framework/templates/codebase/conventions.md +0 -307
  135. package/framework/qualia-framework/templates/codebase/integrations.md +0 -280
  136. package/framework/qualia-framework/templates/codebase/stack.md +0 -186
  137. package/framework/qualia-framework/templates/codebase/structure.md +0 -285
  138. package/framework/qualia-framework/templates/codebase/testing.md +0 -480
  139. package/framework/qualia-framework/templates/config.json +0 -35
  140. package/framework/qualia-framework/templates/context.md +0 -283
  141. package/framework/qualia-framework/templates/continue-here.md +0 -78
  142. package/framework/qualia-framework/templates/debug-subagent-prompt.md +0 -91
  143. package/framework/qualia-framework/templates/discovery.md +0 -146
  144. package/framework/qualia-framework/templates/lab-notes.md +0 -16
  145. package/framework/qualia-framework/templates/milestone-archive.md +0 -123
  146. package/framework/qualia-framework/templates/milestone.md +0 -115
  147. package/framework/qualia-framework/templates/phase-prompt.md +0 -567
  148. package/framework/qualia-framework/templates/planner-subagent-prompt.md +0 -117
  149. package/framework/qualia-framework/templates/project.md +0 -184
  150. package/framework/qualia-framework/templates/projects/ai-agent.md +0 -156
  151. package/framework/qualia-framework/templates/projects/mobile-app.md +0 -181
  152. package/framework/qualia-framework/templates/projects/voice-agent.md +0 -134
  153. package/framework/qualia-framework/templates/projects/website.md +0 -137
  154. package/framework/qualia-framework/templates/requirements.md +0 -231
  155. package/framework/qualia-framework/templates/research-project/ARCHITECTURE.md +0 -204
  156. package/framework/qualia-framework/templates/research-project/FEATURES.md +0 -147
  157. package/framework/qualia-framework/templates/research-project/PITFALLS.md +0 -200
  158. package/framework/qualia-framework/templates/research-project/STACK.md +0 -120
  159. package/framework/qualia-framework/templates/research-project/SUMMARY.md +0 -170
  160. package/framework/qualia-framework/templates/research.md +0 -552
  161. package/framework/qualia-framework/templates/roadmap.md +0 -206
  162. package/framework/qualia-framework/templates/state.md +0 -179
  163. package/framework/qualia-framework/templates/summary-complex.md +0 -59
  164. package/framework/qualia-framework/templates/summary-minimal.md +0 -41
  165. package/framework/qualia-framework/templates/summary-standard.md +0 -48
  166. package/framework/qualia-framework/templates/summary.md +0 -246
  167. package/framework/qualia-framework/templates/user-setup.md +0 -311
  168. package/framework/qualia-framework/templates/verification-report.md +0 -322
  169. package/framework/qualia-framework/workflows/add-phase.md +0 -179
  170. package/framework/qualia-framework/workflows/add-todo.md +0 -157
  171. package/framework/qualia-framework/workflows/audit-milestone.md +0 -241
  172. package/framework/qualia-framework/workflows/check-todos.md +0 -176
  173. package/framework/qualia-framework/workflows/complete-milestone.md +0 -858
  174. package/framework/qualia-framework/workflows/diagnose-issues.md +0 -219
  175. package/framework/qualia-framework/workflows/discovery-phase.md +0 -289
  176. package/framework/qualia-framework/workflows/discuss-phase.md +0 -534
  177. package/framework/qualia-framework/workflows/execute-phase.md +0 -559
  178. package/framework/qualia-framework/workflows/execute-plan.md +0 -438
  179. package/framework/qualia-framework/workflows/help.md +0 -470
  180. package/framework/qualia-framework/workflows/insert-phase.md +0 -220
  181. package/framework/qualia-framework/workflows/list-phase-assumptions.md +0 -178
  182. package/framework/qualia-framework/workflows/map-codebase.md +0 -327
  183. package/framework/qualia-framework/workflows/new-milestone.md +0 -363
  184. package/framework/qualia-framework/workflows/new-project.md +0 -982
  185. package/framework/qualia-framework/workflows/pause-work.md +0 -122
  186. package/framework/qualia-framework/workflows/plan-milestone-gaps.md +0 -256
  187. package/framework/qualia-framework/workflows/plan-phase.md +0 -422
  188. package/framework/qualia-framework/workflows/progress.md +0 -389
  189. package/framework/qualia-framework/workflows/quick.md +0 -252
  190. package/framework/qualia-framework/workflows/remove-phase.md +0 -326
  191. package/framework/qualia-framework/workflows/research-phase.md +0 -74
  192. package/framework/qualia-framework/workflows/resume-project.md +0 -306
  193. package/framework/qualia-framework/workflows/set-profile.md +0 -80
  194. package/framework/qualia-framework/workflows/settings.md +0 -145
  195. package/framework/qualia-framework/workflows/transition.md +0 -556
  196. package/framework/qualia-framework/workflows/update.md +0 -197
  197. package/framework/qualia-framework/workflows/verify-phase.md +0 -195
  198. package/framework/qualia-framework/workflows/verify-work.md +0 -625
  199. package/framework/rules/context7.md +0 -14
  200. package/framework/rules/frontend.md +0 -33
  201. package/framework/rules/speed.md +0 -23
  202. package/framework/scripts/__pycache__/say.cpython-314.pyc +0 -0
  203. package/framework/scripts/apply-retention.sh +0 -120
  204. package/framework/scripts/bootstrap-pop-os.sh +0 -354
  205. package/framework/scripts/claude-voice +0 -13
  206. package/framework/scripts/cleanup.sh +0 -131
  207. package/framework/scripts/cowork-mode.sh +0 -141
  208. package/framework/scripts/generate-project-claude-md.sh +0 -153
  209. package/framework/scripts/load-test-webhook.js +0 -172
  210. package/framework/scripts/say.py +0 -236
  211. package/framework/scripts/showcase-video-recorder/ffmpeg-builder.js +0 -167
  212. package/framework/scripts/showcase-video-recorder/playwright-helpers.js +0 -216
  213. package/framework/scripts/speak.py +0 -55
  214. package/framework/scripts/speak.sh +0 -18
  215. package/framework/scripts/status.sh +0 -138
  216. package/framework/scripts/sync-to-framework.sh +0 -65
  217. package/framework/scripts/voice-hotkey.py +0 -227
  218. package/framework/scripts/voice-input.sh +0 -51
  219. package/framework/skills/animate/SKILL.md +0 -202
  220. package/framework/skills/bolder/SKILL.md +0 -144
  221. package/framework/skills/browser-qa/SKILL.md +0 -536
  222. package/framework/skills/clarify/SKILL.md +0 -179
  223. package/framework/skills/client-handoff/SKILL.md +0 -135
  224. package/framework/skills/collab-onboard/SKILL.md +0 -111
  225. package/framework/skills/colorize/SKILL.md +0 -170
  226. package/framework/skills/critique/SKILL.md +0 -126
  227. package/framework/skills/deep-research/SKILL.md +0 -240
  228. package/framework/skills/delight/SKILL.md +0 -329
  229. package/framework/skills/deploy/SKILL.md +0 -261
  230. package/framework/skills/deploy-verify/SKILL.md +0 -377
  231. package/framework/skills/deploy-verify/scripts/canary-check.sh +0 -206
  232. package/framework/skills/deploy-verify/scripts/check-console-errors.js +0 -147
  233. package/framework/skills/deploy-verify/scripts/check-cwv.js +0 -139
  234. package/framework/skills/deploy-verify/scripts/project-detect.sh +0 -84
  235. package/framework/skills/deploy-verify/scripts/verify.sh +0 -548
  236. package/framework/skills/design-quieter/SKILL.md +0 -130
  237. package/framework/skills/distill/SKILL.md +0 -149
  238. package/framework/skills/docs-lookup/SKILL.md +0 -79
  239. package/framework/skills/fcm-notifications/SKILL.md +0 -125
  240. package/framework/skills/financial-ledger/SKILL.md +0 -1039
  241. package/framework/skills/frontend-master/NOTICE.md +0 -4
  242. package/framework/skills/frontend-master/SKILL.md +0 -127
  243. package/framework/skills/frontend-master/reference/color-and-contrast.md +0 -132
  244. package/framework/skills/frontend-master/reference/interaction-design.md +0 -123
  245. package/framework/skills/frontend-master/reference/motion-design.md +0 -99
  246. package/framework/skills/frontend-master/reference/responsive-design.md +0 -114
  247. package/framework/skills/frontend-master/reference/spatial-design.md +0 -100
  248. package/framework/skills/frontend-master/reference/typography.md +0 -131
  249. package/framework/skills/frontend-master/reference/ux-writing.md +0 -107
  250. package/framework/skills/harden/SKILL.md +0 -357
  251. package/framework/skills/i18n-rtl/SKILL.md +0 -752
  252. package/framework/skills/learn/SKILL.md +0 -95
  253. package/framework/skills/memory/SKILL.md +0 -50
  254. package/framework/skills/mobile-expo/SKILL.md +0 -977
  255. package/framework/skills/mobile-expo/references/store-checklist.md +0 -550
  256. package/framework/skills/nestjs-backend/README.md +0 -73
  257. package/framework/skills/nestjs-backend/SKILL.md +0 -446
  258. package/framework/skills/nestjs-backend/references/templates.md +0 -1173
  259. package/framework/skills/normalize/SKILL.md +0 -79
  260. package/framework/skills/onboard/SKILL.md +0 -242
  261. package/framework/skills/openrouter-agent/SKILL.md +0 -922
  262. package/framework/skills/polish/SKILL.md +0 -209
  263. package/framework/skills/pr/SKILL.md +0 -66
  264. package/framework/skills/qualia/SKILL.md +0 -199
  265. package/framework/skills/qualia-add-todo/SKILL.md +0 -68
  266. package/framework/skills/qualia-audit-milestone/SKILL.md +0 -95
  267. package/framework/skills/qualia-check-todos/SKILL.md +0 -55
  268. package/framework/skills/qualia-complete-milestone/SKILL.md +0 -134
  269. package/framework/skills/qualia-debug/SKILL.md +0 -149
  270. package/framework/skills/qualia-design/SKILL.md +0 -203
  271. package/framework/skills/qualia-discuss-phase/SKILL.md +0 -72
  272. package/framework/skills/qualia-evolve/SKILL.md +0 -200
  273. package/framework/skills/qualia-execute-phase/SKILL.md +0 -89
  274. package/framework/skills/qualia-framework-audit/SKILL.md +0 -604
  275. package/framework/skills/qualia-guide/SKILL.md +0 -32
  276. package/framework/skills/qualia-help/SKILL.md +0 -114
  277. package/framework/skills/qualia-idk/SKILL.md +0 -352
  278. package/framework/skills/qualia-list-phase-assumptions/SKILL.md +0 -67
  279. package/framework/skills/qualia-new-milestone/SKILL.md +0 -72
  280. package/framework/skills/qualia-new-project/SKILL.md +0 -232
  281. package/framework/skills/qualia-optimize/SKILL.md +0 -417
  282. package/framework/skills/qualia-pause-work/SKILL.md +0 -96
  283. package/framework/skills/qualia-plan-milestone-gaps/SKILL.md +0 -57
  284. package/framework/skills/qualia-plan-phase/SKILL.md +0 -104
  285. package/framework/skills/qualia-production-check/SKILL.md +0 -0
  286. package/framework/skills/qualia-progress/SKILL.md +0 -53
  287. package/framework/skills/qualia-quick/SKILL.md +0 -89
  288. package/framework/skills/qualia-report/SKILL.md +0 -166
  289. package/framework/skills/qualia-research-phase/SKILL.md +0 -88
  290. package/framework/skills/qualia-resume-work/SKILL.md +0 -62
  291. package/framework/skills/qualia-review/SKILL.md +0 -263
  292. package/framework/skills/qualia-start/SKILL.md +0 -161
  293. package/framework/skills/qualia-verify-work/SKILL.md +0 -132
  294. package/framework/skills/rag/SKILL.md +0 -750
  295. package/framework/skills/responsive/SKILL.md +0 -231
  296. package/framework/skills/retro/SKILL.md +0 -284
  297. package/framework/skills/sakani-conventions/SKILL.md +0 -136
  298. package/framework/skills/sakani-conventions/evals/evals.json +0 -23
  299. package/framework/skills/sakani-conventions/references/entities.md +0 -365
  300. package/framework/skills/sakani-conventions/references/error-codes.md +0 -95
  301. package/framework/skills/seo-master/SKILL.md +0 -490
  302. package/framework/skills/seo-master/references/checklist.md +0 -199
  303. package/framework/skills/seo-master/references/structured-data.md +0 -609
  304. package/framework/skills/ship/SKILL.md +0 -239
  305. package/framework/skills/stack-researcher/SKILL.md +0 -215
  306. package/framework/skills/status/SKILL.md +0 -154
  307. package/framework/skills/status/scripts/health-check.sh +0 -562
  308. package/framework/skills/subscription-payments/SKILL.md +0 -250
  309. package/framework/skills/supabase/SKILL.md +0 -973
  310. package/framework/skills/supabase/references/templates.md +0 -159
  311. package/framework/skills/team/SKILL.md +0 -67
  312. package/framework/skills/test-runner/SKILL.md +0 -202
  313. package/framework/skills/voice-agent/SKILL.md +0 -1312
  314. package/framework/skills/zoho-workflow/SKILL.md +0 -51
  315. package/framework/statusline-command.sh +0 -117
  316. package/framework/teams/default/inboxes/plan-04.json +0 -9
  317. package/framework/teams/review-team.md +0 -75
  318. package/framework/teams/ship-team.md +0 -86
  319. package/profiles/fawzi.json +0 -16
  320. package/profiles/hasan.json +0 -16
  321. package/profiles/moayad.json +0 -16
  322. package/templates/CLAUDE-owner.md +0 -52
  323. package/templates/CLAUDE.md.hbs +0 -58
  324. package/templates/env.claude.template +0 -12
  325. package/templates/settings.json +0 -172
  326. package/uninstall.sh +0 -90
  327. /package/{framework/rules → rules}/deployment.md +0 -0
  328. /package/{framework/rules → rules}/security.md +0 -0
package/bin/install.js ADDED
@@ -0,0 +1,622 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { createInterface } = require("readline");
4
+ const path = require("path");
5
+ const fs = require("fs");
6
+
7
+ // ─── Colors ──────────────────────────────────────────────
8
+ const TEAL = "\x1b[38;2;0;206;209m";
9
+ const DIM = "\x1b[38;2;80;90;100m";
10
+ const GREEN = "\x1b[38;2;52;211;153m";
11
+ const WHITE = "\x1b[38;2;220;225;230m";
12
+ const YELLOW = "\x1b[38;2;234;179;8m";
13
+ const RED = "\x1b[38;2;239;68;68m";
14
+ const RESET = "\x1b[0m";
15
+
16
+ const CLAUDE_DIR = path.join(require("os").homedir(), ".claude");
17
+ const FRAMEWORK_DIR = path.resolve(__dirname, "..");
18
+
19
+ // ─── Team codes ──────────────────────────────────────────
20
+ const DEFAULT_TEAM = {
21
+ "QS-FAWZI-01": {
22
+ name: "Fawzi Goussous",
23
+ role: "OWNER",
24
+ description: "Company owner. Full access. Can push to main, approve deploys, edit secrets.",
25
+ },
26
+ "QS-HASAN-02": {
27
+ name: "Hasan",
28
+ role: "EMPLOYEE",
29
+ description: "Developer. Feature branches only. Cannot push to main or edit .env files.",
30
+ },
31
+ "QS-MOAYAD-03": {
32
+ name: "Moayad",
33
+ role: "EMPLOYEE",
34
+ description: "Developer. Feature branches only. Cannot push to main or edit .env files.",
35
+ },
36
+ "QS-RAMA-04": {
37
+ name: "Rama",
38
+ role: "EMPLOYEE",
39
+ description: "Developer. Feature branches only. Cannot push to main or edit .env files.",
40
+ },
41
+ "QS-SALLY-05": {
42
+ name: "Sally",
43
+ role: "EMPLOYEE",
44
+ description: "Developer. Feature branches only. Cannot push to main or edit .env files.",
45
+ },
46
+ };
47
+
48
+ // Load team from external file, fall back to embedded defaults.
49
+ function loadTeam() {
50
+ const teamFile = path.join(CLAUDE_DIR, ".qualia-team.json");
51
+ try {
52
+ if (fs.existsSync(teamFile)) {
53
+ const external = JSON.parse(fs.readFileSync(teamFile, "utf8"));
54
+ if (external && typeof external === "object" && Object.keys(external).length > 0) {
55
+ return external;
56
+ }
57
+ }
58
+ } catch {}
59
+ return DEFAULT_TEAM;
60
+ }
61
+
62
+ const TEAM = loadTeam();
63
+
64
+ let installed = 0;
65
+ let errors = 0;
66
+
67
+ function log(msg) {
68
+ console.log(` ${msg}`);
69
+ }
70
+ function ok(label) {
71
+ installed++;
72
+ log(`${GREEN}✓${RESET} ${label}`);
73
+ }
74
+ function warn(label) {
75
+ errors++;
76
+ log(`${YELLOW}✗${RESET} ${label}`);
77
+ }
78
+ function copy(src, dest) {
79
+ const destDir = path.dirname(dest);
80
+ if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
81
+ fs.copyFileSync(src, dest);
82
+ }
83
+
84
+ // ─── Branded Header ─────────────────────────────────────
85
+ const BOLD = "\x1b[1m";
86
+ const TEAL_GLOW = "\x1b[38;2;0;170;175m";
87
+ const PKG_VERSION = require("../package.json").version;
88
+ const RULE = "━".repeat(48);
89
+
90
+ function printHeader() {
91
+ console.log("");
92
+ console.log("");
93
+ console.log(` ${TEAL}${BOLD}⬢ Q U A L I A${RESET}`);
94
+ console.log(` ${DIM}${RULE}${RESET}`);
95
+ console.log(` ${WHITE}Framework v${PKG_VERSION}${RESET} ${DIM}·${RESET} ${TEAL_GLOW}Qualia Solutions${RESET}`);
96
+ console.log(` ${DIM}Plan → Build → Verify → Ship${RESET}`);
97
+ console.log(` ${DIM}${RULE}${RESET}`);
98
+ console.log("");
99
+ }
100
+
101
+ function printSection(title) {
102
+ console.log("");
103
+ console.log(` ${TEAL}▸${RESET} ${WHITE}${BOLD}${title}${RESET}`);
104
+ console.log(` ${DIM}${"─".repeat(40)}${RESET}`);
105
+ }
106
+
107
+ // ─── Prompt for code ─────────────────────────────────────
108
+ function askCode() {
109
+ return new Promise((resolve) => {
110
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
111
+ printHeader();
112
+ rl.question(` ${WHITE}Enter install code:${RESET} `, (answer) => {
113
+ rl.close();
114
+ resolve(answer.trim());
115
+ });
116
+ });
117
+ }
118
+
119
+ // ─── Resolve team code (tolerates case + O/0 typo in suffix) ─
120
+ // Accepts "qs-fawzi-01", "QS-FAWZI-01", "QS-FAWZI-O1" (letter O in the
121
+ // numeric suffix), and returns the canonical key if found, else null.
122
+ // Only normalizes O→0 in the segment AFTER the last dash — "QS-MOAYAD-03"
123
+ // contains a real "O" in the name and must not be mangled.
124
+ function resolveTeamCode(input) {
125
+ const normalized = String(input || "").trim().toUpperCase();
126
+ if (TEAM[normalized]) return normalized;
127
+ const fuzzy = normalized.replace(
128
+ /-([^-]*)$/,
129
+ (_, suffix) => `-${suffix.replace(/O/g, "0")}`
130
+ );
131
+ if (TEAM[fuzzy]) return fuzzy;
132
+ return null;
133
+ }
134
+
135
+ // ─── Main ────────────────────────────────────────────────
136
+ async function main() {
137
+ const rawCode = await askCode();
138
+ const code = resolveTeamCode(rawCode);
139
+ const member = code ? TEAM[code] : null;
140
+
141
+ if (!member) {
142
+ console.log("");
143
+ log(`${RED}✗${RESET} Invalid code: "${rawCode}". Get your install code from Fawzi.`);
144
+ log(`${DIM} Tip: codes use digit zero, not letter O. Format: QS-NAME-01${RESET}`);
145
+ console.log("");
146
+ process.exit(1);
147
+ }
148
+
149
+ console.log("");
150
+ const roleColor = member.role === "OWNER" ? TEAL : GREEN;
151
+ console.log(` ${GREEN}✓${RESET} ${WHITE}${BOLD}Welcome, ${member.name}${RESET}`);
152
+ console.log(` ${DIM} Role:${RESET} ${roleColor}${member.role}${RESET} ${DIM}·${RESET} ${DIM}Target:${RESET} ${WHITE}${CLAUDE_DIR}${RESET}`);
153
+
154
+ // ─── Skills ──────────────────────────────────────────
155
+ const skillsDir = path.join(FRAMEWORK_DIR, "skills");
156
+ const skills = fs
157
+ .readdirSync(skillsDir)
158
+ .filter((d) => fs.statSync(path.join(skillsDir, d)).isDirectory());
159
+
160
+ printSection("Skills");
161
+ for (const skill of skills) {
162
+ try {
163
+ copy(
164
+ path.join(skillsDir, skill, "SKILL.md"),
165
+ path.join(CLAUDE_DIR, "skills", skill, "SKILL.md")
166
+ );
167
+ ok(skill);
168
+ } catch (e) {
169
+ warn(`${skill} — ${e.message}`);
170
+ }
171
+ }
172
+
173
+ // ─── Agents ────────────────────────────────────────────
174
+ printSection("Agents");
175
+ const agentsDir = path.join(FRAMEWORK_DIR, "agents");
176
+ for (const file of fs.readdirSync(agentsDir)) {
177
+ try {
178
+ copy(path.join(agentsDir, file), path.join(CLAUDE_DIR, "agents", file));
179
+ ok(file);
180
+ } catch (e) {
181
+ warn(`${file} — ${e.message}`);
182
+ }
183
+ }
184
+
185
+ // ─── Rules ─────────────────────────────────────────────
186
+ printSection("Rules");
187
+ const rulesDir = path.join(FRAMEWORK_DIR, "rules");
188
+ for (const file of fs.readdirSync(rulesDir)) {
189
+ try {
190
+ copy(path.join(rulesDir, file), path.join(CLAUDE_DIR, "rules", file));
191
+ ok(file);
192
+ } catch (e) {
193
+ warn(`${file} — ${e.message}`);
194
+ }
195
+ }
196
+
197
+ // ─── Hooks ─────────────────────────────────────────────
198
+ printSection("Hooks");
199
+ const hooksSource = path.join(FRAMEWORK_DIR, "hooks");
200
+ const hooksDest = path.join(CLAUDE_DIR, "hooks");
201
+ if (!fs.existsSync(hooksDest)) fs.mkdirSync(hooksDest, { recursive: true });
202
+ // Clean up legacy .sh hooks from previous v2.5/v2.6 installs so no orphans
203
+ // remain on disk after upgrading to the pure-Node v2.7+ hooks.
204
+ try {
205
+ for (const f of fs.readdirSync(hooksDest)) {
206
+ if (f.endsWith(".sh")) {
207
+ try { fs.unlinkSync(path.join(hooksDest, f)); } catch {}
208
+ }
209
+ }
210
+ } catch {}
211
+ for (const file of fs.readdirSync(hooksSource)) {
212
+ try {
213
+ const dest = path.join(hooksDest, file);
214
+ copy(path.join(hooksSource, file), dest);
215
+ // chmod is a no-op on Windows but harmless
216
+ fs.chmodSync(dest, 0o755);
217
+ ok(file);
218
+ } catch (e) {
219
+ warn(`${file} — ${e.message}`);
220
+ }
221
+ }
222
+
223
+ // ─── Templates ─────────────────────────────────────────
224
+ printSection("Templates");
225
+ const tmplDir = path.join(FRAMEWORK_DIR, "templates");
226
+ const tmplDest = path.join(CLAUDE_DIR, "qualia-templates");
227
+ if (!fs.existsSync(tmplDest)) fs.mkdirSync(tmplDest, { recursive: true });
228
+ for (const file of fs.readdirSync(tmplDir)) {
229
+ try {
230
+ copy(path.join(tmplDir, file), path.join(tmplDest, file));
231
+ ok(file);
232
+ } catch (e) {
233
+ warn(`${file} — ${e.message}`);
234
+ }
235
+ }
236
+
237
+ // ─── CLAUDE.md with role ───────────────────────────────
238
+ printSection("Configuration");
239
+ try {
240
+ let claudeMd = fs.readFileSync(
241
+ path.join(FRAMEWORK_DIR, "CLAUDE.md"),
242
+ "utf8"
243
+ );
244
+ claudeMd = claudeMd.replace("{{ROLE}}", member.role);
245
+ claudeMd = claudeMd.replace("{{ROLE_DESCRIPTION}}", member.description);
246
+ const claudeDest = path.join(CLAUDE_DIR, "CLAUDE.md");
247
+ fs.writeFileSync(claudeDest, claudeMd, "utf8");
248
+ ok(`Configured as ${member.role}`);
249
+ } catch (e) {
250
+ warn(`CLAUDE.md — ${e.message}`);
251
+ }
252
+
253
+ // ─── Scripts ─────────────────────────────────────────────
254
+ printSection("Scripts");
255
+ try {
256
+ const binDest = path.join(CLAUDE_DIR, "bin");
257
+ if (!fs.existsSync(binDest)) fs.mkdirSync(binDest, { recursive: true });
258
+ copy(
259
+ path.join(FRAMEWORK_DIR, "bin", "state.js"),
260
+ path.join(binDest, "state.js")
261
+ );
262
+ ok("state.js (state machine)");
263
+ copy(
264
+ path.join(FRAMEWORK_DIR, "bin", "qualia-ui.js"),
265
+ path.join(binDest, "qualia-ui.js")
266
+ );
267
+ fs.chmodSync(path.join(binDest, "qualia-ui.js"), 0o755);
268
+ ok("qualia-ui.js (cosmetics library)");
269
+ copy(
270
+ path.join(FRAMEWORK_DIR, "bin", "statusline.js"),
271
+ path.join(binDest, "statusline.js")
272
+ );
273
+ ok("statusline.js (status bar renderer)");
274
+ } catch (e) {
275
+ warn(`scripts — ${e.message}`);
276
+ }
277
+
278
+ // ─── Guide ─────────────────────────────────────────────
279
+ try {
280
+ copy(
281
+ path.join(FRAMEWORK_DIR, "guide.md"),
282
+ path.join(CLAUDE_DIR, "qualia-guide.md")
283
+ );
284
+ ok("guide.md");
285
+ } catch (e) {
286
+ warn(`guide.md — ${e.message}`);
287
+ }
288
+
289
+ // ─── Knowledge directory ─────────────────────────────────
290
+ printSection("Knowledge Base");
291
+ const knowledgeDir = path.join(CLAUDE_DIR, "knowledge");
292
+ if (!fs.existsSync(knowledgeDir)) fs.mkdirSync(knowledgeDir, { recursive: true });
293
+ const knowledgeFiles = {
294
+ "learned-patterns.md": `# Learned Patterns
295
+
296
+ Patterns discovered across projects. Updated by \`/qualia-learn\` and manual notes.
297
+
298
+ ---
299
+
300
+ ## Cross-platform Node: always spawnSync with argv, never execSync with shell strings
301
+ **Why:** \`execSync(\\\`node \${path}/state.js check 2>/dev/null\\\`)\` breaks on Windows when the path contains spaces (common: \`C:\\\\Users\\\\John Doe\`) and the \`2>/dev/null\` redirect is bash-only. Windows cmd.exe tries to create \`\\\\dev\\\\null\` at drive root.
302
+ **How:** Use \`spawnSync(process.execPath, [path, "check"], { stdio: ["ignore","pipe","ignore"] })\`. Argv array is immune to path splitting; \`stdio: "ignore"\` silences stderr without shell redirection.
303
+
304
+ ---
305
+
306
+ ## Cross-platform stdin piping: spawnSync with input:, not bash <<< here-strings
307
+ **Why:** The \`<<<\` bash here-string works on bash + zsh but fails silently on Windows cmd.exe AND on Debian/Ubuntu where \`/bin/sh\` is dash (no \`<<<\` support).
308
+ **How:** \`spawnSync("npx", ["cmd"], { input: "data\\\\n", stdio: ["pipe","inherit","inherit"], shell: process.platform === "win32" })\`. The \`input:\` option pipes stdin directly. \`shell: process.platform === "win32"\` is required because npm/npx are \`.cmd\` shims on Windows that only resolve through a shell.
309
+
310
+ ---
311
+
312
+ ## Fresh-context isolation beats shared-context compression
313
+ **Why:** Claude's output quality degrades as context fills. A single massive context doing plan + build + verify hits the degradation curve on the later tasks.
314
+ **How:** Spawn separate subagents for planner / builder (per task) / verifier. Each gets fresh context. Task 50 gets the same quality as task 1. Cost: PROJECT.md + STATE.md get re-loaded into each subagent context, but the quality win dominates.
315
+
316
+ ---
317
+
318
+ ## Goal-backward verification beats task-completion tracking
319
+ **Why:** A task "create chat component" can be marked complete with a placeholder file. The task ran; the goal didn't.
320
+ **How:** For each phase success criterion, do a 3-level check: (1) what must be TRUE, (2) what files/functions must EXIST and be substantive (not stubs), (3) what must be CONNECTED (imported and called). Grep the codebase. Never trust summaries.
321
+ `,
322
+ "common-fixes.md": `# Common Fixes
323
+
324
+ Recurring issues and their solutions.
325
+
326
+ ---
327
+
328
+ ## Install code "Invalid" — user typed letter O instead of digit 0
329
+ **Symptom:** \`npx qualia-framework install\` rejects \`QS-NAME-O1\` (letter O in suffix).
330
+ **Cause:** Team codes use digit zero (\`-01\`, \`-02\`, etc.), not letter O.
331
+ **Fix:** Since v2.8.1, install.js auto-normalizes: \`QS-FAWZI-O1\` → \`QS-FAWZI-01\`. The normalization only touches the segment after the last dash, so \`QS-MOAYAD-03\` (real O in name) is preserved.
332
+ **Framework version:** Fixed in v2.8.1.
333
+
334
+ ---
335
+
336
+ ## Windows banner shows "No project detected" inside a real project
337
+ **Symptom:** The session-start banner from qualia-ui.js displays the router panel but without phase/status, even in a project with \`.planning/\`.
338
+ **Cause:** Before v2.8.0, \`qualia-ui.js\` called state.js via \`execSync(\\\`node \${path} check 2>/dev/null\\\`)\`. Windows cmd.exe couldn't parse the \`2>/dev/null\` redirect and/or split the path on spaces in the username.
339
+ **Fix:** v2.8.0 switched to \`spawnSync(process.execPath, [statePath, "check"], { stdio: ["ignore","pipe","ignore"] })\`. Argv array + silent stdio = cross-platform safe.
340
+ **Framework version:** Fixed in v2.8.0.
341
+
342
+ ---
343
+
344
+ ## \`npx qualia-framework update\` fails on Windows or Ubuntu
345
+ **Symptom:** Manual update command fails silently or with a shell parse error on Windows and Debian/Ubuntu.
346
+ **Cause:** Before v2.8.0, cli.js cmdUpdate used \`execSync(\\\`npx ... install <<< "\${code}"\\\`, { shell: true })\`. The \`<<<\` here-string is bash-only; cmd.exe doesn't understand it, and \`/bin/sh\` on Debian/Ubuntu is \`dash\` which also lacks it.
347
+ **Fix:** v2.8.0 replaced with \`spawnSync("npx", [...], { input: code + "\\\\n", shell: process.platform === "win32" })\`. Uses stdin pipe instead of here-string.
348
+ **Framework version:** Fixed in v2.8.0.
349
+
350
+ ---
351
+
352
+ ## Pre-deploy gate false-positive on Next.js Server Components using service_role
353
+ **Symptom:** \`/qualia-ship\` is blocked with "service_role found in client code" for a file that's actually a Server Component (runs server-side only).
354
+ **Cause:** pre-deploy-gate.js skips files matching \`.server.\` filename pattern OR \`server/\` directory path. If the Server Component is at \`app/admin/page.tsx\` (no .server. marker, not in a server/ dir), the scan flags it.
355
+ **Workaround:** Rename to \`.server.tsx\` OR move to a \`server/\` subdirectory OR extract the service_role usage into a helper in \`lib/server/\`.
356
+ **Framework version:** Known issue as of v2.8.1; better heuristic planned for v3.0.
357
+ `,
358
+ "client-prefs.md": `# Client Preferences
359
+
360
+ Client-specific preferences, design choices, and requirements. Loaded by \`/qualia-new\` when starting a project for a known client.
361
+
362
+ ---
363
+
364
+ ## Example Client (template)
365
+ **Industry:** {e.g., fintech, healthcare, SaaS}
366
+ **Contact:** {email}
367
+ **Design:** {dark-bold | clean-minimal | colorful-playful | corporate-professional}
368
+ **Stack preferences:** {anything non-default}
369
+ **Hard constraints:** {things they've explicitly said no to}
370
+ **Source of notes:** {date or conversation reference}
371
+ `,
372
+ };
373
+ for (const [name, defaultContent] of Object.entries(knowledgeFiles)) {
374
+ const dest = path.join(knowledgeDir, name);
375
+ if (!fs.existsSync(dest)) {
376
+ fs.writeFileSync(dest, defaultContent);
377
+ ok(`${name} (created)`);
378
+ } else {
379
+ ok(`${name} (exists)`);
380
+ }
381
+ }
382
+
383
+ // ─── Save config (for update command) ──────────────────
384
+ const configFile = path.join(CLAUDE_DIR, ".qualia-config.json");
385
+ const config = {
386
+ code,
387
+ installed_by: member.name,
388
+ role: member.role,
389
+ version: require("../package.json").version,
390
+ installed_at: new Date().toISOString().split("T")[0],
391
+ erp: {
392
+ enabled: true,
393
+ url: "https://portal.qualiasolutions.net",
394
+ api_key_file: ".erp-api-key",
395
+ },
396
+ };
397
+ fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n");
398
+
399
+ // ─── ERP API key (for report uploads) ──────────────────
400
+ printSection("ERP Integration");
401
+ const erpKeyFile = path.join(CLAUDE_DIR, ".erp-api-key");
402
+ if (!fs.existsSync(erpKeyFile)) {
403
+ fs.writeFileSync(erpKeyFile, "qualia-claude-2026", { mode: 0o600 });
404
+ ok(".erp-api-key (created)");
405
+ } else {
406
+ ok(".erp-api-key (exists)");
407
+ }
408
+
409
+ // ─── Configure settings.json ───────────────────────────
410
+ console.log("");
411
+ log(`${WHITE}Configuring settings.json...${RESET}`);
412
+
413
+ const settingsPath = path.join(CLAUDE_DIR, "settings.json");
414
+ let settings = {};
415
+ if (fs.existsSync(settingsPath)) {
416
+ try {
417
+ settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
418
+ } catch {}
419
+ }
420
+
421
+ // Env
422
+ if (!settings.env) settings.env = {};
423
+ Object.assign(settings.env, {
424
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
425
+ CLAUDE_CODE_DISABLE_AUTO_MEMORY: "0",
426
+ MAX_MCP_OUTPUT_TOKENS: "25000",
427
+ CLAUDE_CODE_NO_FLICKER: "1",
428
+ });
429
+
430
+ // Status line
431
+ settings.statusLine = {
432
+ type: "command",
433
+ command: `node "${path.join(CLAUDE_DIR, "bin", "statusline.js")}"`,
434
+ };
435
+
436
+ // Spinner
437
+ settings.spinnerVerbs = {
438
+ mode: "replace",
439
+ verbs: [
440
+ "Qualia-fying",
441
+ "Solution-ing",
442
+ "Teal-crafting",
443
+ "Vibe-forging",
444
+ "Shipping",
445
+ "Wiring",
446
+ "Polishing",
447
+ "Verifying",
448
+ "Orchestrating",
449
+ "Architecting",
450
+ "Deploying",
451
+ "Hardening",
452
+ ],
453
+ };
454
+
455
+ settings.spinnerTipsOverride = {
456
+ excludeDefault: true,
457
+ tips: [
458
+ "⬢ Lost? Type /qualia for the next step",
459
+ "⬢ Small fix? Use /qualia-quick to skip planning",
460
+ "⬢ End of day? /qualia-report before you clock out",
461
+ "⬢ Context isolation: every task gets a fresh AI brain",
462
+ "⬢ The verifier doesn't trust claims — it greps the code",
463
+ "⬢ Plans are prompts — the plan IS what the builder reads",
464
+ "⬢ Feature branches only — never push to main",
465
+ "⬢ Read before write — no exceptions",
466
+ "⬢ MVP first — build what's asked, nothing extra",
467
+ "⬢ tracking.json syncs to ERP on every push",
468
+ ],
469
+ };
470
+
471
+ // Hooks — pure Node.js, cross-platform (Windows/macOS/Linux).
472
+ // Every hook command is `node <absolute-path-to-hook.js>` which avoids the
473
+ // bash/Git Bash requirement on Windows.
474
+ const hd = path.join(CLAUDE_DIR, "hooks");
475
+ const nodeCmd = (hookFile) => `node "${path.join(hd, hookFile)}"`;
476
+ settings.hooks = {
477
+ SessionStart: [
478
+ {
479
+ matcher: ".*",
480
+ hooks: [
481
+ {
482
+ type: "command",
483
+ command: nodeCmd("session-start.js"),
484
+ timeout: 5,
485
+ },
486
+ ],
487
+ },
488
+ ],
489
+ PreToolUse: [
490
+ {
491
+ matcher: "Bash",
492
+ hooks: [
493
+ {
494
+ type: "command",
495
+ command: nodeCmd("auto-update.js"),
496
+ timeout: 5,
497
+ },
498
+ {
499
+ type: "command",
500
+ if: "Bash(git push*)",
501
+ command: nodeCmd("branch-guard.js"),
502
+ timeout: 5,
503
+ statusMessage: "⬢ Checking branch permissions...",
504
+ },
505
+ {
506
+ type: "command",
507
+ if: "Bash(git push*)",
508
+ command: nodeCmd("pre-push.js"),
509
+ timeout: 15,
510
+ statusMessage: "⬢ Syncing tracking...",
511
+ },
512
+ {
513
+ type: "command",
514
+ if: "Bash(vercel --prod*)",
515
+ command: nodeCmd("pre-deploy-gate.js"),
516
+ timeout: 180,
517
+ statusMessage: "⬢ Running quality gates...",
518
+ },
519
+ ],
520
+ },
521
+ {
522
+ matcher: "Edit|Write",
523
+ hooks: [
524
+ {
525
+ type: "command",
526
+ command: nodeCmd("block-env-edit.js"),
527
+ timeout: 5,
528
+ statusMessage: "⬢ Checking file permissions...",
529
+ },
530
+ {
531
+ type: "command",
532
+ if: "Edit(*migration*)|Write(*migration*)|Edit(*.sql)|Write(*.sql)",
533
+ command: nodeCmd("migration-guard.js"),
534
+ timeout: 10,
535
+ statusMessage: "⬢ Checking migration safety...",
536
+ },
537
+ ],
538
+ },
539
+ ],
540
+ PreCompact: [
541
+ {
542
+ matcher: "compact",
543
+ hooks: [
544
+ {
545
+ type: "command",
546
+ command: nodeCmd("pre-compact.js"),
547
+ timeout: 15,
548
+ statusMessage: "⬢ Saving state...",
549
+ },
550
+ ],
551
+ },
552
+ ],
553
+ };
554
+
555
+ // Permissions — no restrictions on env files or branches.
556
+ // Everyone can read/write .env, push to main.
557
+ if (!settings.permissions) settings.permissions = {};
558
+ if (!settings.permissions.allow) settings.permissions.allow = [];
559
+ if (!settings.permissions.deny) settings.permissions.deny = [];
560
+
561
+ // ─── Optional: next-devtools MCP ─────────────────────────
562
+ // Wire next-devtools-mcp for runtime error visibility in Next.js projects
563
+ if (!settings.mcpServers) settings.mcpServers = {};
564
+ if (!settings.mcpServers["next-devtools"]) {
565
+ settings.mcpServers["next-devtools"] = {
566
+ command: "npx",
567
+ args: ["next-devtools-mcp@0.3.10"],
568
+ disabled: false,
569
+ };
570
+ ok("MCP: next-devtools (runtime error visibility for Next.js projects)");
571
+ }
572
+
573
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
574
+
575
+ ok("Hooks: session-start, auto-update, branch-guard, pre-push, block-env-edit, migration-guard, deploy-gate, pre-compact");
576
+ ok("Status line + spinner configured");
577
+ ok("Environment variables + permissions");
578
+
579
+ // ─── Summary ───────────────────────────────────────────
580
+ console.log("");
581
+ console.log(` ${DIM}${RULE}${RESET}`);
582
+ console.log(` ${TEAL}${BOLD}⬢ INSTALLED${RESET}`);
583
+ console.log(` ${DIM}${RULE}${RESET}`);
584
+ console.log("");
585
+ console.log(` ${WHITE}${BOLD}${member.name}${RESET} ${DIM}·${RESET} ${roleColor}${member.role}${RESET} ${DIM}·${RESET} ${DIM}v${PKG_VERSION}${RESET}`);
586
+ console.log("");
587
+ const agentCount = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length;
588
+ const hookCount = fs.readdirSync(hooksSource).length;
589
+ const ruleCount = fs.readdirSync(rulesDir).length;
590
+ const tmplCount = fs.readdirSync(tmplDir).length;
591
+ console.log(` ${DIM}Skills${RESET} ${TEAL}${skills.length}${RESET} ${DIM}Agents${RESET} ${TEAL}${agentCount}${RESET} ${DIM}Hooks${RESET} ${TEAL}${hookCount}${RESET}`);
592
+ console.log(` ${DIM}Rules${RESET} ${TEAL}${ruleCount}${RESET} ${DIM}Scripts${RESET} ${TEAL}3${RESET} ${DIM}Templates${RESET} ${TEAL}${tmplCount}${RESET}`);
593
+
594
+ if (errors > 0) {
595
+ console.log("");
596
+ console.log(` ${YELLOW}${errors} warning(s)${RESET} — check output above`);
597
+ }
598
+
599
+ console.log("");
600
+ console.log(` ${DIM}${RULE}${RESET}`);
601
+ console.log(` ${WHITE}${BOLD}Quick Start${RESET}`);
602
+ console.log(` ${DIM}${RULE}${RESET}`);
603
+ console.log("");
604
+ console.log(` ${TEAL}1.${RESET} ${WHITE}Restart Claude Code${RESET} ${DIM}(loads new settings)${RESET}`);
605
+ console.log(` ${TEAL}2.${RESET} ${WHITE}cd into any project${RESET} ${DIM}and run${RESET} ${TEAL}claude${RESET}`);
606
+ console.log(` ${TEAL}3.${RESET} ${WHITE}Type${RESET} ${TEAL}${BOLD}/qualia${RESET} ${DIM}— it tells you what to do next${RESET}`);
607
+ console.log("");
608
+ console.log(` ${DIM}New project?${RESET} ${TEAL}/qualia-new${RESET}`);
609
+ console.log(` ${DIM}Quick fix?${RESET} ${TEAL}/qualia-quick${RESET}`);
610
+ console.log(` ${DIM}End of day?${RESET} ${TEAL}/qualia-report${RESET} ${DIM}(mandatory)${RESET}`);
611
+ console.log(` ${DIM}Stuck?${RESET} ${TEAL}/qualia${RESET}`);
612
+ console.log("");
613
+ console.log(` ${DIM}${RULE}${RESET}`);
614
+ console.log(` ${TEAL}${BOLD}Welcome to the future with Qualia.${RESET}`);
615
+ console.log(` ${DIM}${RULE}${RESET}`);
616
+ console.log("");
617
+ }
618
+
619
+ main().catch((e) => {
620
+ console.error(`${RED} ✗ Installation failed: ${e.message}${RESET}`);
621
+ process.exit(1);
622
+ });