qualia-framework 2.6.0 → 3.2.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 (321) hide show
  1. package/CLAUDE.md +64 -0
  2. package/README.md +103 -30
  3. package/agents/builder.md +110 -0
  4. package/agents/planner.md +134 -0
  5. package/agents/qa-browser.md +186 -0
  6. package/agents/verifier.md +221 -0
  7. package/bin/cli.js +336 -531
  8. package/bin/install.js +570 -0
  9. package/bin/qualia-ui.js +299 -0
  10. package/bin/state.js +630 -0
  11. package/bin/statusline.js +252 -0
  12. package/guide.md +63 -0
  13. package/hooks/auto-update.js +139 -0
  14. package/hooks/branch-guard.js +47 -0
  15. package/hooks/migration-guard.js +60 -0
  16. package/hooks/pre-compact.js +32 -0
  17. package/hooks/pre-deploy-gate.js +110 -0
  18. package/hooks/pre-push.js +33 -0
  19. package/hooks/session-start.js +170 -0
  20. package/package.json +29 -20
  21. package/rules/design-reference.md +179 -0
  22. package/rules/frontend.md +126 -0
  23. package/skills/qualia/SKILL.md +87 -0
  24. package/skills/qualia-build/SKILL.md +97 -0
  25. package/skills/qualia-debug/SKILL.md +87 -0
  26. package/skills/qualia-design/SKILL.md +93 -0
  27. package/skills/qualia-handoff/SKILL.md +66 -0
  28. package/skills/qualia-idk/SKILL.md +8 -0
  29. package/skills/qualia-learn/SKILL.md +88 -0
  30. package/skills/qualia-new/SKILL.md +323 -0
  31. package/{framework/skills → skills}/qualia-optimize/SKILL.md +1 -1
  32. package/skills/qualia-pause/SKILL.md +63 -0
  33. package/skills/qualia-plan/SKILL.md +101 -0
  34. package/skills/qualia-polish/SKILL.md +157 -0
  35. package/skills/qualia-quick/SKILL.md +37 -0
  36. package/skills/qualia-report/SKILL.md +105 -0
  37. package/skills/qualia-resume/SKILL.md +49 -0
  38. package/skills/qualia-review/SKILL.md +76 -0
  39. package/skills/qualia-ship/SKILL.md +90 -0
  40. package/skills/qualia-skill-new/SKILL.md +167 -0
  41. package/skills/qualia-task/SKILL.md +91 -0
  42. package/skills/qualia-verify/SKILL.md +113 -0
  43. package/templates/DESIGN.md +137 -0
  44. package/templates/plan.md +28 -0
  45. package/templates/project.md +22 -0
  46. package/templates/state.md +27 -0
  47. package/templates/tracking.json +20 -0
  48. package/tests/bin.test.sh +673 -0
  49. package/tests/hooks.test.sh +315 -0
  50. package/tests/state.test.sh +535 -0
  51. package/tests/statusline.test.sh +243 -0
  52. package/bin/collect-metrics.sh +0 -62
  53. package/framework/.claudeignore +0 -51
  54. package/framework/CLAUDE.md +0 -51
  55. package/framework/MCP_SETUP.md +0 -229
  56. package/framework/agents/architecture-strategist.md +0 -53
  57. package/framework/agents/backend-agent.md +0 -150
  58. package/framework/agents/code-simplicity-reviewer.md +0 -86
  59. package/framework/agents/frontend-agent.md +0 -111
  60. package/framework/agents/kieran-typescript-reviewer.md +0 -96
  61. package/framework/agents/performance-oracle.md +0 -111
  62. package/framework/agents/qualia-codebase-mapper.md +0 -761
  63. package/framework/agents/qualia-debugger.md +0 -1204
  64. package/framework/agents/qualia-executor.md +0 -882
  65. package/framework/agents/qualia-integration-checker.md +0 -424
  66. package/framework/agents/qualia-phase-researcher.md +0 -457
  67. package/framework/agents/qualia-plan-checker.md +0 -700
  68. package/framework/agents/qualia-planner.md +0 -1245
  69. package/framework/agents/qualia-project-researcher.md +0 -603
  70. package/framework/agents/qualia-research-synthesizer.md +0 -200
  71. package/framework/agents/qualia-roadmapper.md +0 -606
  72. package/framework/agents/qualia-verifier.md +0 -686
  73. package/framework/agents/red-team-qa.md +0 -130
  74. package/framework/agents/security-auditor.md +0 -72
  75. package/framework/agents/team-orchestrator.md +0 -229
  76. package/framework/agents/teams/framework-audit-team.md +0 -66
  77. package/framework/agents/teams/full-stack-team.md +0 -48
  78. package/framework/agents/teams/optimize-team.md +0 -53
  79. package/framework/agents/teams/review-team.md +0 -70
  80. package/framework/agents/teams/ship-team.md +0 -86
  81. package/framework/agents/test-agent.md +0 -182
  82. package/framework/hooks/auto-format.sh +0 -54
  83. package/framework/hooks/block-env-edit.sh +0 -42
  84. package/framework/hooks/branch-guard.sh +0 -43
  85. package/framework/hooks/confirm-delete.sh +0 -59
  86. package/framework/hooks/migration-validate.sh +0 -77
  87. package/framework/hooks/notification-speak.sh +0 -16
  88. package/framework/hooks/pre-commit.sh +0 -100
  89. package/framework/hooks/pre-compact.sh +0 -56
  90. package/framework/hooks/pre-deploy-gate.sh +0 -160
  91. package/framework/hooks/qualia-colors.sh +0 -32
  92. package/framework/hooks/retention-cleanup.sh +0 -62
  93. package/framework/hooks/save-session-state.sh +0 -185
  94. package/framework/hooks/session-context-loader.sh +0 -96
  95. package/framework/hooks/session-learn.sh +0 -32
  96. package/framework/hooks/skill-announce.sh +0 -123
  97. package/framework/hooks/tool-error-announce.sh +0 -27
  98. package/framework/install.ps1 +0 -323
  99. package/framework/install.sh +0 -313
  100. package/framework/qualia-framework/VERSION +0 -1
  101. package/framework/qualia-framework/assets/qualia-logo.png +0 -0
  102. package/framework/qualia-framework/bin/collect-metrics.sh +0 -67
  103. package/framework/qualia-framework/bin/generate-report-docx.py +0 -429
  104. package/framework/qualia-framework/bin/qualia-tools.js +0 -2201
  105. package/framework/qualia-framework/bin/qualia-tools.test.js +0 -1054
  106. package/framework/qualia-framework/references/checkpoints.md +0 -775
  107. package/framework/qualia-framework/references/completion-checklists.md +0 -359
  108. package/framework/qualia-framework/references/continuation-format.md +0 -249
  109. package/framework/qualia-framework/references/continuation-prompt.md +0 -97
  110. package/framework/qualia-framework/references/decimal-phase-calculation.md +0 -65
  111. package/framework/qualia-framework/references/design-quality.md +0 -56
  112. package/framework/qualia-framework/references/employee-guide.md +0 -167
  113. package/framework/qualia-framework/references/git-integration.md +0 -254
  114. package/framework/qualia-framework/references/git-planning-commit.md +0 -50
  115. package/framework/qualia-framework/references/model-profile-resolution.md +0 -32
  116. package/framework/qualia-framework/references/model-profiles.md +0 -73
  117. package/framework/qualia-framework/references/phase-argument-parsing.md +0 -61
  118. package/framework/qualia-framework/references/planning-config.md +0 -195
  119. package/framework/qualia-framework/references/questioning.md +0 -141
  120. package/framework/qualia-framework/references/tdd.md +0 -263
  121. package/framework/qualia-framework/references/ui-brand.md +0 -160
  122. package/framework/qualia-framework/references/verification-patterns.md +0 -612
  123. package/framework/qualia-framework/templates/DEBUG.md +0 -159
  124. package/framework/qualia-framework/templates/DESIGN.md +0 -81
  125. package/framework/qualia-framework/templates/UAT.md +0 -247
  126. package/framework/qualia-framework/templates/codebase/architecture.md +0 -255
  127. package/framework/qualia-framework/templates/codebase/concerns.md +0 -310
  128. package/framework/qualia-framework/templates/codebase/conventions.md +0 -307
  129. package/framework/qualia-framework/templates/codebase/integrations.md +0 -280
  130. package/framework/qualia-framework/templates/codebase/stack.md +0 -186
  131. package/framework/qualia-framework/templates/codebase/structure.md +0 -285
  132. package/framework/qualia-framework/templates/codebase/testing.md +0 -480
  133. package/framework/qualia-framework/templates/config.json +0 -35
  134. package/framework/qualia-framework/templates/context.md +0 -283
  135. package/framework/qualia-framework/templates/continue-here.md +0 -78
  136. package/framework/qualia-framework/templates/debug-subagent-prompt.md +0 -91
  137. package/framework/qualia-framework/templates/discovery.md +0 -146
  138. package/framework/qualia-framework/templates/lab-notes.md +0 -16
  139. package/framework/qualia-framework/templates/milestone-archive.md +0 -123
  140. package/framework/qualia-framework/templates/milestone.md +0 -115
  141. package/framework/qualia-framework/templates/phase-prompt.md +0 -567
  142. package/framework/qualia-framework/templates/planner-subagent-prompt.md +0 -117
  143. package/framework/qualia-framework/templates/project.md +0 -184
  144. package/framework/qualia-framework/templates/projects/ai-agent.md +0 -156
  145. package/framework/qualia-framework/templates/projects/mobile-app.md +0 -181
  146. package/framework/qualia-framework/templates/projects/voice-agent.md +0 -134
  147. package/framework/qualia-framework/templates/projects/website.md +0 -137
  148. package/framework/qualia-framework/templates/requirements.md +0 -231
  149. package/framework/qualia-framework/templates/research-project/ARCHITECTURE.md +0 -204
  150. package/framework/qualia-framework/templates/research-project/FEATURES.md +0 -147
  151. package/framework/qualia-framework/templates/research-project/PITFALLS.md +0 -200
  152. package/framework/qualia-framework/templates/research-project/STACK.md +0 -120
  153. package/framework/qualia-framework/templates/research-project/SUMMARY.md +0 -170
  154. package/framework/qualia-framework/templates/research.md +0 -552
  155. package/framework/qualia-framework/templates/roadmap.md +0 -206
  156. package/framework/qualia-framework/templates/state.md +0 -179
  157. package/framework/qualia-framework/templates/summary-complex.md +0 -59
  158. package/framework/qualia-framework/templates/summary-minimal.md +0 -41
  159. package/framework/qualia-framework/templates/summary-standard.md +0 -48
  160. package/framework/qualia-framework/templates/summary.md +0 -246
  161. package/framework/qualia-framework/templates/user-setup.md +0 -311
  162. package/framework/qualia-framework/templates/verification-report.md +0 -322
  163. package/framework/qualia-framework/workflows/add-phase.md +0 -179
  164. package/framework/qualia-framework/workflows/add-todo.md +0 -157
  165. package/framework/qualia-framework/workflows/audit-milestone.md +0 -241
  166. package/framework/qualia-framework/workflows/check-todos.md +0 -176
  167. package/framework/qualia-framework/workflows/complete-milestone.md +0 -858
  168. package/framework/qualia-framework/workflows/diagnose-issues.md +0 -219
  169. package/framework/qualia-framework/workflows/discovery-phase.md +0 -289
  170. package/framework/qualia-framework/workflows/discuss-phase.md +0 -534
  171. package/framework/qualia-framework/workflows/execute-phase.md +0 -559
  172. package/framework/qualia-framework/workflows/execute-plan.md +0 -438
  173. package/framework/qualia-framework/workflows/help.md +0 -470
  174. package/framework/qualia-framework/workflows/insert-phase.md +0 -220
  175. package/framework/qualia-framework/workflows/list-phase-assumptions.md +0 -178
  176. package/framework/qualia-framework/workflows/map-codebase.md +0 -327
  177. package/framework/qualia-framework/workflows/new-milestone.md +0 -363
  178. package/framework/qualia-framework/workflows/new-project.md +0 -982
  179. package/framework/qualia-framework/workflows/pause-work.md +0 -122
  180. package/framework/qualia-framework/workflows/plan-milestone-gaps.md +0 -256
  181. package/framework/qualia-framework/workflows/plan-phase.md +0 -422
  182. package/framework/qualia-framework/workflows/progress.md +0 -389
  183. package/framework/qualia-framework/workflows/quick.md +0 -252
  184. package/framework/qualia-framework/workflows/remove-phase.md +0 -326
  185. package/framework/qualia-framework/workflows/research-phase.md +0 -74
  186. package/framework/qualia-framework/workflows/resume-project.md +0 -306
  187. package/framework/qualia-framework/workflows/set-profile.md +0 -80
  188. package/framework/qualia-framework/workflows/settings.md +0 -145
  189. package/framework/qualia-framework/workflows/transition.md +0 -556
  190. package/framework/qualia-framework/workflows/update.md +0 -197
  191. package/framework/qualia-framework/workflows/verify-phase.md +0 -195
  192. package/framework/qualia-framework/workflows/verify-work.md +0 -625
  193. package/framework/rules/context7.md +0 -14
  194. package/framework/rules/frontend.md +0 -33
  195. package/framework/rules/speed.md +0 -23
  196. package/framework/scripts/__pycache__/say.cpython-314.pyc +0 -0
  197. package/framework/scripts/apply-retention.sh +0 -120
  198. package/framework/scripts/bootstrap-pop-os.sh +0 -354
  199. package/framework/scripts/claude-voice +0 -13
  200. package/framework/scripts/cleanup.sh +0 -131
  201. package/framework/scripts/cowork-mode.sh +0 -141
  202. package/framework/scripts/generate-project-claude-md.sh +0 -153
  203. package/framework/scripts/load-test-webhook.js +0 -172
  204. package/framework/scripts/say.py +0 -236
  205. package/framework/scripts/showcase-video-recorder/ffmpeg-builder.js +0 -167
  206. package/framework/scripts/showcase-video-recorder/playwright-helpers.js +0 -216
  207. package/framework/scripts/speak.py +0 -55
  208. package/framework/scripts/speak.sh +0 -18
  209. package/framework/scripts/status.sh +0 -138
  210. package/framework/scripts/sync-to-framework.sh +0 -65
  211. package/framework/scripts/voice-hotkey.py +0 -227
  212. package/framework/scripts/voice-input.sh +0 -51
  213. package/framework/skills/animate/SKILL.md +0 -202
  214. package/framework/skills/bolder/SKILL.md +0 -144
  215. package/framework/skills/browser-qa/SKILL.md +0 -536
  216. package/framework/skills/clarify/SKILL.md +0 -179
  217. package/framework/skills/client-handoff/SKILL.md +0 -135
  218. package/framework/skills/collab-onboard/SKILL.md +0 -111
  219. package/framework/skills/colorize/SKILL.md +0 -170
  220. package/framework/skills/critique/SKILL.md +0 -126
  221. package/framework/skills/deep-research/SKILL.md +0 -240
  222. package/framework/skills/delight/SKILL.md +0 -329
  223. package/framework/skills/deploy/SKILL.md +0 -261
  224. package/framework/skills/deploy-verify/SKILL.md +0 -377
  225. package/framework/skills/deploy-verify/scripts/canary-check.sh +0 -206
  226. package/framework/skills/deploy-verify/scripts/check-console-errors.js +0 -147
  227. package/framework/skills/deploy-verify/scripts/check-cwv.js +0 -139
  228. package/framework/skills/deploy-verify/scripts/project-detect.sh +0 -84
  229. package/framework/skills/deploy-verify/scripts/verify.sh +0 -548
  230. package/framework/skills/design-quieter/SKILL.md +0 -130
  231. package/framework/skills/distill/SKILL.md +0 -149
  232. package/framework/skills/docs-lookup/SKILL.md +0 -79
  233. package/framework/skills/fcm-notifications/SKILL.md +0 -125
  234. package/framework/skills/financial-ledger/SKILL.md +0 -1039
  235. package/framework/skills/frontend-master/NOTICE.md +0 -4
  236. package/framework/skills/frontend-master/SKILL.md +0 -127
  237. package/framework/skills/frontend-master/reference/color-and-contrast.md +0 -132
  238. package/framework/skills/frontend-master/reference/interaction-design.md +0 -123
  239. package/framework/skills/frontend-master/reference/motion-design.md +0 -99
  240. package/framework/skills/frontend-master/reference/responsive-design.md +0 -114
  241. package/framework/skills/frontend-master/reference/spatial-design.md +0 -100
  242. package/framework/skills/frontend-master/reference/typography.md +0 -131
  243. package/framework/skills/frontend-master/reference/ux-writing.md +0 -107
  244. package/framework/skills/harden/SKILL.md +0 -357
  245. package/framework/skills/i18n-rtl/SKILL.md +0 -752
  246. package/framework/skills/learn/SKILL.md +0 -95
  247. package/framework/skills/memory/SKILL.md +0 -50
  248. package/framework/skills/mobile-expo/SKILL.md +0 -977
  249. package/framework/skills/mobile-expo/references/store-checklist.md +0 -550
  250. package/framework/skills/nestjs-backend/README.md +0 -73
  251. package/framework/skills/nestjs-backend/SKILL.md +0 -446
  252. package/framework/skills/nestjs-backend/references/templates.md +0 -1173
  253. package/framework/skills/normalize/SKILL.md +0 -79
  254. package/framework/skills/onboard/SKILL.md +0 -242
  255. package/framework/skills/openrouter-agent/SKILL.md +0 -922
  256. package/framework/skills/polish/SKILL.md +0 -209
  257. package/framework/skills/pr/SKILL.md +0 -66
  258. package/framework/skills/qualia/SKILL.md +0 -199
  259. package/framework/skills/qualia-add-todo/SKILL.md +0 -68
  260. package/framework/skills/qualia-audit-milestone/SKILL.md +0 -95
  261. package/framework/skills/qualia-check-todos/SKILL.md +0 -55
  262. package/framework/skills/qualia-complete-milestone/SKILL.md +0 -134
  263. package/framework/skills/qualia-debug/SKILL.md +0 -149
  264. package/framework/skills/qualia-design/SKILL.md +0 -203
  265. package/framework/skills/qualia-discuss-phase/SKILL.md +0 -72
  266. package/framework/skills/qualia-evolve/SKILL.md +0 -200
  267. package/framework/skills/qualia-execute-phase/SKILL.md +0 -89
  268. package/framework/skills/qualia-framework-audit/SKILL.md +0 -604
  269. package/framework/skills/qualia-guide/SKILL.md +0 -32
  270. package/framework/skills/qualia-help/SKILL.md +0 -114
  271. package/framework/skills/qualia-idk/SKILL.md +0 -352
  272. package/framework/skills/qualia-list-phase-assumptions/SKILL.md +0 -67
  273. package/framework/skills/qualia-new-milestone/SKILL.md +0 -72
  274. package/framework/skills/qualia-new-project/SKILL.md +0 -232
  275. package/framework/skills/qualia-pause-work/SKILL.md +0 -96
  276. package/framework/skills/qualia-plan-milestone-gaps/SKILL.md +0 -57
  277. package/framework/skills/qualia-plan-phase/SKILL.md +0 -104
  278. package/framework/skills/qualia-production-check/SKILL.md +0 -0
  279. package/framework/skills/qualia-progress/SKILL.md +0 -53
  280. package/framework/skills/qualia-quick/SKILL.md +0 -89
  281. package/framework/skills/qualia-report/SKILL.md +0 -166
  282. package/framework/skills/qualia-research-phase/SKILL.md +0 -88
  283. package/framework/skills/qualia-resume-work/SKILL.md +0 -62
  284. package/framework/skills/qualia-review/SKILL.md +0 -263
  285. package/framework/skills/qualia-start/SKILL.md +0 -161
  286. package/framework/skills/qualia-verify-work/SKILL.md +0 -132
  287. package/framework/skills/rag/SKILL.md +0 -750
  288. package/framework/skills/responsive/SKILL.md +0 -231
  289. package/framework/skills/retro/SKILL.md +0 -284
  290. package/framework/skills/sakani-conventions/SKILL.md +0 -136
  291. package/framework/skills/sakani-conventions/evals/evals.json +0 -23
  292. package/framework/skills/sakani-conventions/references/entities.md +0 -365
  293. package/framework/skills/sakani-conventions/references/error-codes.md +0 -95
  294. package/framework/skills/seo-master/SKILL.md +0 -490
  295. package/framework/skills/seo-master/references/checklist.md +0 -199
  296. package/framework/skills/seo-master/references/structured-data.md +0 -609
  297. package/framework/skills/ship/SKILL.md +0 -239
  298. package/framework/skills/stack-researcher/SKILL.md +0 -215
  299. package/framework/skills/status/SKILL.md +0 -154
  300. package/framework/skills/status/scripts/health-check.sh +0 -562
  301. package/framework/skills/subscription-payments/SKILL.md +0 -250
  302. package/framework/skills/supabase/SKILL.md +0 -973
  303. package/framework/skills/supabase/references/templates.md +0 -159
  304. package/framework/skills/team/SKILL.md +0 -67
  305. package/framework/skills/test-runner/SKILL.md +0 -202
  306. package/framework/skills/voice-agent/SKILL.md +0 -1312
  307. package/framework/skills/zoho-workflow/SKILL.md +0 -51
  308. package/framework/statusline-command.sh +0 -117
  309. package/framework/teams/default/inboxes/plan-04.json +0 -9
  310. package/framework/teams/review-team.md +0 -75
  311. package/framework/teams/ship-team.md +0 -86
  312. package/profiles/fawzi.json +0 -16
  313. package/profiles/hasan.json +0 -16
  314. package/profiles/moayad.json +0 -16
  315. package/templates/CLAUDE-owner.md +0 -52
  316. package/templates/CLAUDE.md.hbs +0 -58
  317. package/templates/env.claude.template +0 -12
  318. package/templates/settings.json +0 -172
  319. package/uninstall.sh +0 -90
  320. /package/{framework/rules → rules}/deployment.md +0 -0
  321. /package/{framework/rules → rules}/security.md +0 -0
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+ // Qualia status line — teal branded, shows phase + context + git.
3
+ // Pure Node.js port of the original statusline.sh. Cross-platform
4
+ // (Windows/macOS/Linux). No jq, no GNU stat, no /tmp hardcoding.
5
+ //
6
+ // Reads JSON from stdin (Claude Code status line schema), prints
7
+ // two ANSI-formatted lines to stdout. Never throws — every section
8
+ // is wrapped so missing data degrades gracefully.
9
+
10
+ const fs = require("fs");
11
+ const os = require("os");
12
+ const path = require("path");
13
+ const { spawnSync } = require("child_process");
14
+ const HOME = os.homedir();
15
+
16
+ // ─── Colors (matches bin/qualia-ui.js palette) ───────────
17
+ const TEAL = "\x1b[38;2;0;206;209m";
18
+ const TEAL_GLOW = "\x1b[38;2;0;170;175m";
19
+ const TEAL_DIM = "\x1b[38;2;0;130;135m";
20
+ const WHITE = "\x1b[38;2;220;225;230m";
21
+ const DIM = "\x1b[38;2;80;90;100m";
22
+ const GREEN = "\x1b[38;2;52;211;153m";
23
+ const YELLOW = "\x1b[38;2;234;179;8m";
24
+ const RED = "\x1b[38;2;239;68;68m";
25
+ const RESET = "\x1b[0m";
26
+
27
+ // ─── Read input ──────────────────────────────────────────
28
+ function readInput() {
29
+ try {
30
+ const raw = fs.readFileSync(0, "utf8");
31
+ return JSON.parse(raw);
32
+ } catch {
33
+ return {};
34
+ }
35
+ }
36
+
37
+ const input = readInput();
38
+
39
+ function pick(obj, keypath, fallback) {
40
+ try {
41
+ let cur = obj;
42
+ for (const k of keypath.split(".")) {
43
+ if (cur == null) return fallback;
44
+ cur = cur[k];
45
+ }
46
+ return cur == null ? fallback : cur;
47
+ } catch {
48
+ return fallback;
49
+ }
50
+ }
51
+
52
+ const MODEL = String(pick(input, "model.display_name", ""));
53
+ const DIR = String(pick(input, "workspace.current_dir", process.cwd()));
54
+ const PCT_RAW = Number(pick(input, "context_window.used_percentage", 0)) || 0;
55
+ const PCT = Math.floor(PCT_RAW);
56
+ const COST = Number(pick(input, "cost.total_cost_usd", 0)) || 0;
57
+ const DURATION_MS = Number(pick(input, "cost.total_duration_ms", 0)) || 0;
58
+ const AGENT = String(pick(input, "agent.name", "") || "");
59
+ const WORKTREE = String(pick(input, "worktree.name", "") || "");
60
+
61
+ // ─── Context bar ─────────────────────────────────────────
62
+ let BAR = "";
63
+ let BAR_COLOR = TEAL;
64
+ try {
65
+ if (PCT >= 80) BAR_COLOR = RED;
66
+ else if (PCT >= 50) BAR_COLOR = YELLOW;
67
+ else BAR_COLOR = TEAL;
68
+
69
+ const BAR_WIDTH = 10;
70
+ const filled = Math.max(0, Math.min(BAR_WIDTH, Math.floor((PCT * BAR_WIDTH) / 100)));
71
+ const empty = BAR_WIDTH - filled;
72
+ BAR = "━".repeat(filled) + "╌".repeat(empty);
73
+ } catch {
74
+ BAR = "╌".repeat(10);
75
+ }
76
+
77
+ // ─── Git branch (cached, cross-platform) ─────────────────
78
+ let BRANCH = "";
79
+ let CHANGES = 0;
80
+ try {
81
+ const username = (os.userInfo().username || "anon").replace(/[^a-zA-Z0-9_-]/g, "_");
82
+ const cacheFile = path.join(os.tmpdir(), `qualia-git-cache-${username}`);
83
+
84
+ let fresh = false;
85
+ try {
86
+ const st = fs.statSync(cacheFile);
87
+ if (Date.now() - st.mtimeMs <= 3000) fresh = true;
88
+ } catch {
89
+ fresh = false;
90
+ }
91
+
92
+ if (!fresh) {
93
+ let branch = "";
94
+ let changes = 0;
95
+ try {
96
+ const dirCheck = spawnSync("git", ["rev-parse", "--git-dir"], {
97
+ cwd: DIR,
98
+ encoding: "utf8",
99
+ timeout: 1000,
100
+ stdio: ["ignore", "pipe", "ignore"],
101
+ });
102
+ if (dirCheck.status === 0) {
103
+ const br = spawnSync("git", ["branch", "--show-current"], {
104
+ cwd: DIR,
105
+ encoding: "utf8",
106
+ timeout: 1000,
107
+ stdio: ["ignore", "pipe", "ignore"],
108
+ });
109
+ if (br.status === 0) branch = (br.stdout || "").trim();
110
+
111
+ const st = spawnSync("git", ["status", "--porcelain"], {
112
+ cwd: DIR,
113
+ encoding: "utf8",
114
+ timeout: 1000,
115
+ stdio: ["ignore", "pipe", "ignore"],
116
+ });
117
+ if (st.status === 0) {
118
+ const out = (st.stdout || "").trim();
119
+ changes = out ? out.split("\n").length : 0;
120
+ }
121
+ }
122
+ } catch {}
123
+ try {
124
+ fs.writeFileSync(cacheFile, `${branch}|${changes}`);
125
+ } catch {}
126
+ }
127
+
128
+ try {
129
+ const cached = fs.readFileSync(cacheFile, "utf8");
130
+ const [b, c] = cached.split("|");
131
+ BRANCH = b || "";
132
+ CHANGES = parseInt(c, 10) || 0;
133
+ } catch {}
134
+ } catch {}
135
+
136
+ // ─── Phase info from .planning/tracking.json ─────────────
137
+ let PHASE_INFO = "";
138
+ try {
139
+ const trackingPath = path.join(DIR, ".planning", "tracking.json");
140
+ if (fs.existsSync(trackingPath)) {
141
+ const tracking = JSON.parse(fs.readFileSync(trackingPath, "utf8"));
142
+ const phase = Number(tracking.phase || 0) || 0;
143
+ const total = Number(tracking.total_phases || 0) || 0;
144
+ const status = String(tracking.status || "");
145
+ if (total > 0) {
146
+ const pdone = Math.floor((phase * 100) / total);
147
+ const pfill = Math.max(0, Math.min(4, Math.floor(pdone / 25)));
148
+ const pempt = 4 - pfill;
149
+ const pbar = "●".repeat(pfill) + "○".repeat(pempt);
150
+ PHASE_INFO = `${TEAL}${pbar}${RESET} ${WHITE}P${phase}/${total}${RESET} ${TEAL_GLOW}${status}${RESET}`;
151
+ }
152
+ }
153
+ } catch {}
154
+
155
+ // ─── Memory count ────────────────────────────────────────
156
+ let MEMORY_COUNT = 0;
157
+ try {
158
+ const dirKey = DIR.replace(/\//g, "-");
159
+ const memDir = path.join(HOME, ".claude", "projects", dirKey, "memory");
160
+ if (fs.existsSync(memDir)) {
161
+ const files = fs.readdirSync(memDir).filter(f => f.endsWith(".md") && f !== "MEMORY.md");
162
+ MEMORY_COUNT = files.length;
163
+ }
164
+ } catch {}
165
+
166
+ // ─── Hooks count ─────────────────────────────────────────
167
+ let HOOKS_COUNT = 0;
168
+ try {
169
+ const settingsPath = path.join(HOME, ".claude", "settings.json");
170
+ if (fs.existsSync(settingsPath)) {
171
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
172
+ if (settings.hooks) {
173
+ for (const event of Object.values(settings.hooks)) {
174
+ if (Array.isArray(event)) {
175
+ for (const matcher of event) {
176
+ if (matcher.hooks && Array.isArray(matcher.hooks)) {
177
+ HOOKS_COUNT += matcher.hooks.length;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+ } catch {}
185
+
186
+ // ─── Skills count ────────────────────────────────────────
187
+ let SKILLS_COUNT = 0;
188
+ try {
189
+ const skillsDir = path.join(HOME, ".claude", "skills");
190
+ if (fs.existsSync(skillsDir)) {
191
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
192
+ SKILLS_COUNT = entries.filter(e => e.isDirectory() || e.name.endsWith(".md")).length;
193
+ }
194
+ } catch {}
195
+
196
+ // ─── Duration ────────────────────────────────────────────
197
+ let DUR = "0s";
198
+ try {
199
+ if (DURATION_MS >= 60000) {
200
+ DUR = `${Math.floor(DURATION_MS / 60000)}m`;
201
+ } else {
202
+ DUR = `${Math.floor(DURATION_MS / 1000)}s`;
203
+ }
204
+ } catch {}
205
+
206
+ // ─── Cost ────────────────────────────────────────────────
207
+ let COST_FMT = "$0.00";
208
+ try {
209
+ COST_FMT = `$${COST.toFixed(2)}`;
210
+ } catch {}
211
+
212
+ // ─── Line 1: Project + Git + Agent + Worktree + Phase + Memory + Hooks ──
213
+ let LINE1 = "";
214
+ try {
215
+ const dirBase = path.basename(DIR) || DIR;
216
+ LINE1 = `${TEAL}⬢${RESET} ${WHITE}${dirBase}${RESET}`;
217
+ if (BRANCH) {
218
+ if (CHANGES > 0) {
219
+ LINE1 += ` ${DIM}on${RESET} ${TEAL_GLOW}${BRANCH}${RESET} ${YELLOW}~${CHANGES}${RESET}`;
220
+ } else {
221
+ LINE1 += ` ${DIM}on${RESET} ${TEAL_GLOW}${BRANCH}${RESET}`;
222
+ }
223
+ }
224
+ if (AGENT) LINE1 += ` ${DIM}│${RESET} ${TEAL}⚡${AGENT}${RESET}`;
225
+ if (WORKTREE) LINE1 += ` ${DIM}│${RESET} ${TEAL_DIM}⎇ ${WORKTREE}${RESET}`;
226
+ if (PHASE_INFO) LINE1 += ` ${DIM}│${RESET} ${PHASE_INFO}`;
227
+ // Memory, hooks, skills — context indicators
228
+ const contextParts = [];
229
+ if (MEMORY_COUNT > 0) contextParts.push(`${TEAL}⊙${RESET}${DIM}${MEMORY_COUNT}${RESET}`);
230
+ if (HOOKS_COUNT > 0) contextParts.push(`${TEAL_GLOW}⚙${RESET}${DIM}${HOOKS_COUNT}${RESET}`);
231
+ if (SKILLS_COUNT > 0) contextParts.push(`${TEAL_DIM}✦${RESET}${DIM}${SKILLS_COUNT}${RESET}`);
232
+ if (contextParts.length > 0) {
233
+ LINE1 += ` ${DIM}│${RESET} ${contextParts.join(` ${DIM}·${RESET} `)}`;
234
+ }
235
+ } catch {
236
+ LINE1 = `${TEAL}⬢${RESET} ${WHITE}qualia${RESET}`;
237
+ }
238
+
239
+ // ─── Line 2: Context bar + Cost + Duration + Model ───────
240
+ let LINE2 = "";
241
+ try {
242
+ LINE2 =
243
+ `${BAR_COLOR}${BAR}${RESET} ${DIM}${PCT}%${RESET} ` +
244
+ `${DIM}│${RESET} ${DIM}${COST_FMT}${RESET} ` +
245
+ `${DIM}│${RESET} ${DIM}${DUR}${RESET} ` +
246
+ `${DIM}│${RESET} ${TEAL_DIM}${MODEL}${RESET}`;
247
+ } catch {
248
+ LINE2 = `${DIM}${PCT}%${RESET}`;
249
+ }
250
+
251
+ process.stdout.write(LINE1 + "\n");
252
+ process.stdout.write(LINE2 + "\n");
package/guide.md ADDED
@@ -0,0 +1,63 @@
1
+ # Qualia Developer Guide
2
+
3
+ > Follow the road. Type the commands. The framework handles the rest.
4
+
5
+ ## The Road
6
+
7
+ ```
8
+ /qualia-new ← Set up project (once)
9
+
10
+ For each phase:
11
+ /qualia-plan ← Plan it (planner agent)
12
+ /qualia-build ← Build it (builder subagents)
13
+ /qualia-verify ← Verify it works (verifier agent)
14
+
15
+ /qualia-polish ← Design pass
16
+ /qualia-ship ← Deploy to production
17
+ /qualia-handoff ← Deliver to client
18
+
19
+ Done.
20
+ ```
21
+
22
+ ## The 10 Commands
23
+
24
+ | When | Command | What it does |
25
+ |------|---------|-------------|
26
+ | Starting | `/qualia-new` | Set up project from scratch |
27
+ | Building | `/qualia-plan` | Plan the current phase |
28
+ | | `/qualia-build` | Build it (parallel tasks) |
29
+ | | `/qualia-verify` | Check it actually works |
30
+ | Quick fix | `/qualia-quick` | Skip planning, just do it |
31
+ | Finishing | `/qualia-polish` | Design and UX pass |
32
+ | | `/qualia-ship` | Deploy to production |
33
+ | | `/qualia-handoff` | Deliver to client |
34
+ | Reporting | `/qualia-report` | Log what you did (mandatory) |
35
+ | **Lost?** | **`/qualia`** | **Tells you the exact next command** |
36
+
37
+ ## Rules
38
+
39
+ 1. **Feature branches only** — never push to main
40
+ 2. **Read before write** — don't edit files you haven't read
41
+ 3. **MVP first** — build what's asked, nothing extra
42
+ 4. **`/qualia` is your friend** — lost? type it
43
+
44
+ ## When You're Stuck
45
+
46
+ ```
47
+ /qualia ← "what's next?"
48
+ ```
49
+
50
+ If that doesn't help, paste the error and ask Claude directly. If Claude can't fix it, tell Fawzi.
51
+
52
+ ## Session Start / End
53
+
54
+ **Start:** Claude loads your project context automatically.
55
+ **End:** Run `/qualia-report` — this is mandatory before clock-out.
56
+
57
+ ## How It Works (you don't need to know this, but if curious)
58
+
59
+ - **Context isolation:** Each task runs in a fresh AI brain. Task 50 gets the same quality as Task 1.
60
+ - **Goal-backward verification:** The verifier doesn't trust "I built it." It greps the code to check if things actually work.
61
+ - **Plans are prompts:** The plan file IS what the builder reads. No translation loss.
62
+ - **Wave execution:** Independent tasks run in parallel. Dependent tasks wait.
63
+ - **tracking.json:** Updated on every push. The ERP reads it automatically.
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ // ~/.claude/hooks/auto-update.js — daily silent update check in the background.
3
+ // PreToolUse hook on every Bash tool call. Fast path: single stat() call that
4
+ // returns immediately if last check was <24h ago. Cross-platform.
5
+
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const os = require("os");
9
+ const { spawn, spawnSync } = require("child_process");
10
+
11
+ const _traceStart = Date.now();
12
+
13
+ const CLAUDE_DIR = path.join(os.homedir(), ".claude");
14
+ const CACHE_FILE = path.join(CLAUDE_DIR, ".qualia-last-update-check");
15
+ const CONFIG_FILE = path.join(CLAUDE_DIR, ".qualia-config.json");
16
+ const LOCK_FILE = path.join(CLAUDE_DIR, ".qualia-updating");
17
+ const MAX_AGE_MS = 24 * 60 * 60 * 1000;
18
+
19
+ function _trace(hookName, result, extra) {
20
+ try {
21
+ const traceDir = path.join(os.homedir(), ".claude", ".qualia-traces");
22
+ if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
23
+ const entry = {
24
+ hook: hookName,
25
+ result,
26
+ timestamp: new Date().toISOString(),
27
+ duration_ms: Date.now() - _traceStart,
28
+ ...extra,
29
+ };
30
+ const traceFile = path.join(traceDir, `${new Date().toISOString().split("T")[0]}.jsonl`);
31
+ fs.appendFileSync(traceFile, JSON.stringify(entry) + "\n");
32
+ } catch {}
33
+ }
34
+
35
+ try {
36
+ // Fast path: recently checked
37
+ if (fs.existsSync(CACHE_FILE)) {
38
+ const last = Number(fs.readFileSync(CACHE_FILE, "utf8")) || 0;
39
+ if (Date.now() - last * 1000 < MAX_AGE_MS) {
40
+ _trace("auto-update", "allow", { reason: "recently-checked" });
41
+ process.exit(0);
42
+ }
43
+ }
44
+
45
+ // Already updating
46
+ if (fs.existsSync(LOCK_FILE)) {
47
+ _trace("auto-update", "allow", { reason: "already-updating" });
48
+ process.exit(0);
49
+ }
50
+
51
+ // Update cache timestamp immediately to debounce concurrent checks
52
+ fs.writeFileSync(CACHE_FILE, String(Math.floor(Date.now() / 1000)));
53
+
54
+ // Read current config
55
+ let cfg = {};
56
+ try {
57
+ cfg = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf8"));
58
+ } catch {
59
+ _trace("auto-update", "allow", { reason: "config-unreadable" });
60
+ process.exit(0);
61
+ }
62
+ if (!cfg.code || !cfg.version) {
63
+ _trace("auto-update", "allow", { reason: "config-incomplete" });
64
+ process.exit(0);
65
+ }
66
+
67
+ // Fork the check-and-update into a detached background process so the hook
68
+ // returns immediately and Claude Code is never blocked.
69
+ //
70
+ // OWNER: silent auto-install (unchanged behavior).
71
+ // EMPLOYEE: write a sticky notification file — session-start.js renders a
72
+ // banner every session until they run the update manually. Fawzi (OWNER)
73
+ // never sees the banner because his framework auto-updates ahead of it.
74
+ const script = `
75
+ const fs = require("fs");
76
+ const path = require("path");
77
+ const { spawnSync } = require("child_process");
78
+ const CLAUDE_DIR = ${JSON.stringify(CLAUDE_DIR)};
79
+ const LOCK_FILE = ${JSON.stringify(LOCK_FILE)};
80
+ const CONFIG_FILE = ${JSON.stringify(CONFIG_FILE)};
81
+ const NOTIF_FILE = path.join(CLAUDE_DIR, ".qualia-update-available.json");
82
+ const cfg = ${JSON.stringify(cfg)};
83
+ try {
84
+ fs.writeFileSync(LOCK_FILE, String(process.pid));
85
+ const r = spawnSync("npm", ["view", "qualia-framework", "version"], {
86
+ encoding: "utf8",
87
+ timeout: 15000,
88
+ shell: process.platform === "win32",
89
+ });
90
+ const latest = ((r.stdout || "").trim());
91
+ if (!latest) { try { fs.unlinkSync(LOCK_FILE); } catch {} process.exit(0); }
92
+ const cmp = (a, b) => {
93
+ const pa = a.split(".").map(Number), pb = b.split(".").map(Number);
94
+ for (let i = 0; i < 3; i++) {
95
+ if ((pa[i]||0) > (pb[i]||0)) return 1;
96
+ if ((pa[i]||0) < (pb[i]||0)) return -1;
97
+ }
98
+ return 0;
99
+ };
100
+ if (cmp(latest, cfg.version) > 0) {
101
+ if (cfg.role === "OWNER") {
102
+ // Silent auto-install for OWNER — no notification banner ever shown.
103
+ spawnSync("npx", ["qualia-framework@latest", "install"], {
104
+ input: cfg.code + "\\n",
105
+ timeout: 120000,
106
+ stdio: ["pipe", "ignore", "ignore"],
107
+ shell: process.platform === "win32",
108
+ });
109
+ try { fs.unlinkSync(NOTIF_FILE); } catch {}
110
+ } else {
111
+ // EMPLOYEE: write sticky notification. session-start.js will render
112
+ // a visible banner every session until the employee runs the update.
113
+ try {
114
+ fs.writeFileSync(NOTIF_FILE, JSON.stringify({
115
+ current: cfg.version,
116
+ latest: latest,
117
+ detected_at: new Date().toISOString(),
118
+ }, null, 2));
119
+ } catch {}
120
+ }
121
+ } else {
122
+ // Already up to date — clear any stale notification file.
123
+ try { fs.unlinkSync(NOTIF_FILE); } catch {}
124
+ }
125
+ } catch {}
126
+ try { fs.unlinkSync(LOCK_FILE); } catch {}
127
+ `;
128
+
129
+ const child = spawn(process.execPath, ["-e", script], {
130
+ detached: true,
131
+ stdio: "ignore",
132
+ });
133
+ child.unref();
134
+ } catch {
135
+ // Silent — never block the tool call
136
+ }
137
+
138
+ _trace("auto-update", "allow", { reason: "check-spawned" });
139
+ process.exit(0);
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ // ~/.claude/hooks/branch-guard.js — block non-OWNER push to main/master.
3
+ // PreToolUse hook on `git push*` commands. Reads role from
4
+ // ~/.claude/.qualia-config.json (single source of truth).
5
+ // Exits 1 to BLOCK. Exits 0 to allow.
6
+ // Cross-platform (Windows/macOS/Linux).
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+ const os = require("os");
11
+ const { spawnSync } = require("child_process");
12
+
13
+ const CONFIG = path.join(os.homedir(), ".claude", ".qualia-config.json");
14
+
15
+ function fail(msg) {
16
+ console.log(msg);
17
+ process.exit(1);
18
+ }
19
+
20
+ let role = "";
21
+ try {
22
+ const cfg = JSON.parse(fs.readFileSync(CONFIG, "utf8"));
23
+ role = cfg.role || "";
24
+ } catch {
25
+ fail(`BLOCKED: ${CONFIG} missing or unreadable. Run: npx qualia-framework install`);
26
+ }
27
+
28
+ if (!role) {
29
+ fail(`BLOCKED: Cannot determine role from ${CONFIG}. Defaulting to deny.`);
30
+ }
31
+
32
+ // Ask git for the current branch --show-current. Works identically on Windows/macOS/Linux.
33
+ const r = spawnSync("git", ["branch", "--show-current"], {
34
+ encoding: "utf8",
35
+ timeout: 3000,
36
+ });
37
+ const branch = ((r.stdout || "").trim());
38
+
39
+ if (branch === "main" || branch === "master") {
40
+ if (role !== "OWNER") {
41
+ console.log(`BLOCKED: Employees cannot push to ${branch}. Create a feature branch first.`);
42
+ console.log("Run: git checkout -b feature/your-feature-name");
43
+ process.exit(1);
44
+ }
45
+ }
46
+
47
+ process.exit(0);
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ // ~/.claude/hooks/migration-guard.js — catch dangerous SQL patterns in migrations.
3
+ // PreToolUse hook on Edit/Write tool calls. Reads tool input as JSON on stdin.
4
+ // Exits 2 to BLOCK. Exits 0 to allow.
5
+ // Cross-platform (Windows/macOS/Linux).
6
+
7
+ const fs = require("fs");
8
+
9
+ function readInput() {
10
+ try {
11
+ const raw = fs.readFileSync(0, "utf8");
12
+ return JSON.parse(raw);
13
+ } catch {
14
+ return {};
15
+ }
16
+ }
17
+
18
+ const input = readInput();
19
+ const ti = input.tool_input || {};
20
+ const file = String(ti.file_path || "").replace(/\\/g, "/");
21
+ const content = String(ti.content || ti.new_string || "");
22
+
23
+ // Only inspect migration/SQL files
24
+ if (!/migration|migrate|\.sql$/i.test(file)) {
25
+ process.exit(0);
26
+ }
27
+
28
+ const errors = [];
29
+
30
+ // DROP TABLE without IF EXISTS
31
+ if (/DROP\s+TABLE/i.test(content) && !/IF\s+EXISTS/i.test(content)) {
32
+ errors.push("DROP TABLE without IF EXISTS");
33
+ }
34
+
35
+ // DELETE without WHERE
36
+ if (/DELETE\s+FROM/i.test(content) && !/WHERE/i.test(content)) {
37
+ errors.push("DELETE FROM without WHERE clause");
38
+ }
39
+
40
+ // TRUNCATE (almost always wrong in migrations)
41
+ if (/TRUNCATE/i.test(content)) {
42
+ errors.push("TRUNCATE detected — are you sure?");
43
+ }
44
+
45
+ // CREATE TABLE without RLS
46
+ if (/CREATE\s+TABLE/i.test(content) && !/ENABLE\s+ROW\s+LEVEL\s+SECURITY/i.test(content)) {
47
+ errors.push("CREATE TABLE without ENABLE ROW LEVEL SECURITY");
48
+ }
49
+
50
+ if (errors.length > 0) {
51
+ console.log("⬢ Migration guard — dangerous patterns found:");
52
+ for (const e of errors) {
53
+ console.log(` ✗ ${e}`);
54
+ }
55
+ console.log("");
56
+ console.log("Fix these before proceeding. If intentional, ask Fawzi to approve.");
57
+ process.exit(2);
58
+ }
59
+
60
+ process.exit(0);
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ // ~/.claude/hooks/pre-compact.js — commit STATE.md before context compaction.
3
+ // PreCompact hook. Silent on failure — context compaction must never be blocked.
4
+ // Cross-platform (Windows/macOS/Linux).
5
+
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const { spawnSync } = require("child_process");
9
+
10
+ const STATE_FILE = path.join(".planning", "STATE.md");
11
+
12
+ try {
13
+ if (fs.existsSync(STATE_FILE)) {
14
+ console.log("QUALIA: Saving state before compaction...");
15
+ // Check if STATE.md has uncommitted changes
16
+ const diff = spawnSync("git", ["diff", "--name-only", STATE_FILE], {
17
+ encoding: "utf8",
18
+ timeout: 3000,
19
+ });
20
+ if ((diff.stdout || "").includes("STATE.md")) {
21
+ spawnSync("git", ["add", STATE_FILE], { timeout: 3000 });
22
+ spawnSync("git", ["commit", "-m", "state: pre-compaction save"], {
23
+ timeout: 5000,
24
+ stdio: "ignore",
25
+ });
26
+ }
27
+ }
28
+ } catch {
29
+ // Silent — never block compaction
30
+ }
31
+
32
+ process.exit(0);