qualia-framework-v2 2.9.0 → 2.10.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.
package/bin/cli.js CHANGED
@@ -34,7 +34,7 @@ function writeConfig(cfg) {
34
34
 
35
35
  function banner() {
36
36
  console.log("");
37
- console.log(` ${TEAL}${BOLD}◆${RESET} ${WHITE}${BOLD}Qualia Framework${RESET} ${DIM}v${PKG.version}${RESET}`);
37
+ console.log(` ${TEAL}${BOLD}⬢${RESET} ${WHITE}${BOLD}Qualia Framework${RESET} ${DIM}v${PKG.version}${RESET}`);
38
38
  console.log(` ${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
39
39
  }
40
40
 
@@ -339,7 +339,7 @@ async function cmdUninstall() {
339
339
 
340
340
  // Summary.
341
341
  console.log("");
342
- console.log(`${TEAL} Uninstall complete${RESET}`);
342
+ console.log(`${TEAL} Uninstall complete${RESET}`);
343
343
  console.log(`${DIM} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
344
344
  console.log(` ${DIM}Files removed:${RESET} ${WHITE}${counters.filesRemoved}${RESET}`);
345
345
  console.log(` ${DIM}Directories removed:${RESET} ${WHITE}${counters.dirsRemoved}${RESET}`);
package/bin/install.js CHANGED
@@ -70,7 +70,7 @@ function askCode() {
70
70
  return new Promise((resolve) => {
71
71
  const rl = createInterface({ input: process.stdin, output: process.stdout });
72
72
  console.log("");
73
- console.log(`${TEAL} Qualia Framework v2${RESET}`);
73
+ console.log(`${TEAL} Qualia Framework v2${RESET}`);
74
74
  console.log(`${DIM} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
75
75
  console.log("");
76
76
  rl.question(` ${WHITE}Enter install code:${RESET} `, (answer) => {
@@ -425,16 +425,16 @@ Client-specific preferences, design choices, and requirements. Loaded by \`/qual
425
425
  settings.spinnerTipsOverride = {
426
426
  excludeDefault: true,
427
427
  tips: [
428
- " Lost? Type /qualia for the next step",
429
- " Small fix? Use /qualia-quick to skip planning",
430
- " End of day? /qualia-report before you clock out",
431
- " Context isolation: every task gets a fresh AI brain",
432
- " The verifier doesn't trust claims — it greps the code",
433
- " Plans are prompts — the plan IS what the builder reads",
434
- " Feature branches only — never push to main",
435
- " Read before write — no exceptions",
436
- " MVP first — build what's asked, nothing extra",
437
- " tracking.json syncs to ERP on every push",
428
+ " Lost? Type /qualia for the next step",
429
+ " Small fix? Use /qualia-quick to skip planning",
430
+ " End of day? /qualia-report before you clock out",
431
+ " Context isolation: every task gets a fresh AI brain",
432
+ " The verifier doesn't trust claims — it greps the code",
433
+ " Plans are prompts — the plan IS what the builder reads",
434
+ " Feature branches only — never push to main",
435
+ " Read before write — no exceptions",
436
+ " MVP first — build what's asked, nothing extra",
437
+ " tracking.json syncs to ERP on every push",
438
438
  ],
439
439
  };
440
440
 
@@ -470,21 +470,21 @@ Client-specific preferences, design choices, and requirements. Loaded by \`/qual
470
470
  if: "Bash(git push*)",
471
471
  command: nodeCmd("branch-guard.js"),
472
472
  timeout: 10,
473
- statusMessage: " Checking branch permissions...",
473
+ statusMessage: " Checking branch permissions...",
474
474
  },
475
475
  {
476
476
  type: "command",
477
477
  if: "Bash(git push*)",
478
478
  command: nodeCmd("pre-push.js"),
479
479
  timeout: 15,
480
- statusMessage: " Syncing tracking...",
480
+ statusMessage: " Syncing tracking...",
481
481
  },
482
482
  {
483
483
  type: "command",
484
484
  if: "Bash(vercel --prod*)",
485
485
  command: nodeCmd("pre-deploy-gate.js"),
486
486
  timeout: 180,
487
- statusMessage: " Running quality gates...",
487
+ statusMessage: " Running quality gates...",
488
488
  },
489
489
  ],
490
490
  },
@@ -496,14 +496,14 @@ Client-specific preferences, design choices, and requirements. Loaded by \`/qual
496
496
  if: "Edit(*.env*)|Write(*.env*)",
497
497
  command: nodeCmd("block-env-edit.js"),
498
498
  timeout: 5,
499
- statusMessage: " Checking file permissions...",
499
+ statusMessage: " Checking file permissions...",
500
500
  },
501
501
  {
502
502
  type: "command",
503
503
  if: "Edit(*migration*)|Write(*migration*)|Edit(*.sql)|Write(*.sql)",
504
504
  command: nodeCmd("migration-guard.js"),
505
505
  timeout: 10,
506
- statusMessage: " Checking migration safety...",
506
+ statusMessage: " Checking migration safety...",
507
507
  },
508
508
  ],
509
509
  },
@@ -516,7 +516,7 @@ Client-specific preferences, design choices, and requirements. Loaded by \`/qual
516
516
  type: "command",
517
517
  command: nodeCmd("pre-compact.js"),
518
518
  timeout: 15,
519
- statusMessage: " Saving state...",
519
+ statusMessage: " Saving state...",
520
520
  },
521
521
  ],
522
522
  },
@@ -542,7 +542,7 @@ Client-specific preferences, design choices, and requirements. Loaded by \`/qual
542
542
 
543
543
  // ─── Summary ───────────────────────────────────────────
544
544
  console.log("");
545
- console.log(`${TEAL} Installed ✓${RESET}`);
545
+ console.log(`${TEAL} Installed ✓${RESET}`);
546
546
  console.log(`${DIM} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
547
547
  console.log(` ${WHITE}${member.name}${RESET} ${DIM}(${member.role})${RESET}`);
548
548
  console.log(` Skills: ${WHITE}${skills.length}${RESET}`);
package/bin/qualia-ui.js CHANGED
@@ -40,25 +40,25 @@ const RULE_DIM = `${DIM2}${RULE}${RESET}`;
40
40
 
41
41
  // ─── Action Labels ───────────────────────────────────────
42
42
  const ACTIONS = {
43
- router: { label: "SMART ROUTER", glyph: "" },
44
- new: { label: "NEW PROJECT", glyph: "" },
45
- plan: { label: "PLANNING", glyph: "" },
46
- build: { label: "BUILDING", glyph: "" },
47
- verify: { label: "VERIFYING", glyph: "" },
48
- polish: { label: "POLISHING", glyph: "" },
49
- ship: { label: "SHIPPING", glyph: "" },
50
- handoff: { label: "HANDING OFF", glyph: "" },
51
- report: { label: "SESSION REPORT", glyph: "" },
52
- debug: { label: "DEBUGGING", glyph: "" },
53
- learn: { label: "LEARNING", glyph: "" },
54
- pause: { label: "PAUSING", glyph: "" },
55
- resume: { label: "RESUMING", glyph: "" },
56
- review: { label: "REVIEW", glyph: "" },
57
- design: { label: "DESIGN PASS", glyph: "" },
58
- quick: { label: "QUICK FIX", glyph: "" },
59
- task: { label: "TASK", glyph: "" },
60
- "skill-new": { label: "NEW SKILL", glyph: "" },
61
- gaps: { label: "GAP CLOSURE", glyph: "" },
43
+ router: { label: "SMART ROUTER", glyph: "" },
44
+ new: { label: "NEW PROJECT", glyph: "" },
45
+ plan: { label: "PLANNING", glyph: "" },
46
+ build: { label: "BUILDING", glyph: "" },
47
+ verify: { label: "VERIFYING", glyph: "" },
48
+ polish: { label: "POLISHING", glyph: "" },
49
+ ship: { label: "SHIPPING", glyph: "" },
50
+ handoff: { label: "HANDING OFF", glyph: "" },
51
+ report: { label: "SESSION REPORT", glyph: "" },
52
+ debug: { label: "DEBUGGING", glyph: "" },
53
+ learn: { label: "LEARNING", glyph: "" },
54
+ pause: { label: "PAUSING", glyph: "" },
55
+ resume: { label: "RESUMING", glyph: "" },
56
+ review: { label: "REVIEW", glyph: "" },
57
+ design: { label: "DESIGN PASS", glyph: "" },
58
+ quick: { label: "QUICK FIX", glyph: "" },
59
+ task: { label: "TASK", glyph: "" },
60
+ "skill-new": { label: "NEW SKILL", glyph: "" },
61
+ gaps: { label: "GAP CLOSURE", glyph: "" },
62
62
  };
63
63
 
64
64
  // ─── State Reading ───────────────────────────────────────
@@ -126,7 +126,7 @@ function pad(str, width) {
126
126
 
127
127
  // ─── Commands ────────────────────────────────────────────
128
128
  function cmdBanner(action, phase, subtitle) {
129
- const spec = ACTIONS[action] || { label: (action || "qualia").toUpperCase(), glyph: "" };
129
+ const spec = ACTIONS[action] || { label: (action || "qualia").toUpperCase(), glyph: "" };
130
130
  const state = readState();
131
131
  const config = readConfig();
132
132
  const project = projectName();
@@ -136,7 +136,7 @@ function cmdBanner(action, phase, subtitle) {
136
136
  : spec.label;
137
137
 
138
138
  console.log("");
139
- console.log(` ${TEAL}${BOLD}${spec.glyph}${RESET} ${WHITE}${BOLD}QUALIA${RESET} ${DIM}►${RESET} ${WHITE}${title}${RESET}`);
139
+ console.log(` ${TEAL}${BOLD}${spec.glyph}${RESET} ${WHITE}${BOLD}QUALIA${RESET} ${DIM}▸${RESET} ${WHITE}${title}${RESET}`);
140
140
  console.log(` ${RULE_DIM}`);
141
141
 
142
142
  // Context panel
@@ -218,7 +218,7 @@ function cmdInfo(msg) {
218
218
  function cmdSpawn(agent, desc) {
219
219
  const name = agent || "agent";
220
220
  const d = desc ? ` ${DIM}— ${desc}${RESET}` : "";
221
- console.log(` ${TEAL}⟐${RESET} ${WHITE}Spawning${RESET} ${TEAL}${name}${RESET}${d}`);
221
+ console.log(` ${TEAL}⬡${RESET} ${WHITE}Spawning${RESET} ${TEAL}${name}${RESET}${d}`);
222
222
  }
223
223
 
224
224
  function cmdWave(num, total, taskCount) {
@@ -226,7 +226,7 @@ function cmdWave(num, total, taskCount) {
226
226
  const n = parseInt(num) || 0;
227
227
  const t = parseInt(total) || 0;
228
228
  const c = parseInt(taskCount) || 0;
229
- console.log(` ${TEAL}▸${RESET} ${WHITE}${BOLD}Wave ${n}/${t}${RESET} ${DIM}(${c} ${c === 1 ? "task" : "tasks"}, parallel)${RESET}`);
229
+ console.log(` ${TEAL}»${RESET} ${WHITE}${BOLD}Wave ${n}/${t}${RESET} ${DIM}(${c} ${c === 1 ? "task" : "tasks"}, parallel)${RESET}`);
230
230
  }
231
231
 
232
232
  function cmdTask(num, title) {
@@ -241,16 +241,16 @@ function cmdDone(num, title, commit) {
241
241
  function cmdNext(cmd) {
242
242
  if (!cmd) return;
243
243
  console.log("");
244
- console.log(` ${TEAL}→${RESET} ${WHITE}Next:${RESET} ${TEAL}${BOLD}${cmd}${RESET}`);
244
+ console.log(` ${TEAL}⟶${RESET} ${WHITE}Next:${RESET} ${TEAL}${BOLD}${cmd}${RESET}`);
245
245
  console.log("");
246
246
  }
247
247
 
248
248
  function cmdEnd(status, nextCmd) {
249
249
  console.log("");
250
- console.log(` ${TEAL}${BOLD}◆${RESET} ${WHITE}${BOLD}${status || "DONE"}${RESET}`);
250
+ console.log(` ${TEAL}${BOLD}⬢${RESET} ${WHITE}${BOLD}${status || "DONE"}${RESET}`);
251
251
  console.log(` ${RULE_DIM}`);
252
252
  if (nextCmd) {
253
- console.log(` ${TEAL}→${RESET} ${WHITE}Next:${RESET} ${TEAL}${BOLD}${nextCmd}${RESET}`);
253
+ console.log(` ${TEAL}⟶${RESET} ${WHITE}Next:${RESET} ${TEAL}${BOLD}${nextCmd}${RESET}`);
254
254
  }
255
255
  console.log("");
256
256
  }
package/bin/statusline.js CHANGED
@@ -11,6 +11,7 @@ const fs = require("fs");
11
11
  const os = require("os");
12
12
  const path = require("path");
13
13
  const { spawnSync } = require("child_process");
14
+ const HOME = os.homedir();
14
15
 
15
16
  // ─── Colors (matches bin/qualia-ui.js palette) ───────────
16
17
  const TEAL = "\x1b[38;2;0;206;209m";
@@ -151,6 +152,47 @@ try {
151
152
  }
152
153
  } catch {}
153
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
+
154
196
  // ─── Duration ────────────────────────────────────────────
155
197
  let DUR = "0s";
156
198
  try {
@@ -167,11 +209,11 @@ try {
167
209
  COST_FMT = `$${COST.toFixed(2)}`;
168
210
  } catch {}
169
211
 
170
- // ─── Line 1: Project + Git + Agent + Worktree + Phase ────
212
+ // ─── Line 1: Project + Git + Agent + Worktree + Phase + Memory + Hooks ──
171
213
  let LINE1 = "";
172
214
  try {
173
215
  const dirBase = path.basename(DIR) || DIR;
174
- LINE1 = `${TEAL}◆${RESET} ${WHITE}${dirBase}${RESET}`;
216
+ LINE1 = `${TEAL}⬢${RESET} ${WHITE}${dirBase}${RESET}`;
175
217
  if (BRANCH) {
176
218
  if (CHANGES > 0) {
177
219
  LINE1 += ` ${DIM}on${RESET} ${TEAL_GLOW}${BRANCH}${RESET} ${YELLOW}~${CHANGES}${RESET}`;
@@ -182,8 +224,16 @@ try {
182
224
  if (AGENT) LINE1 += ` ${DIM}│${RESET} ${TEAL}⚡${AGENT}${RESET}`;
183
225
  if (WORKTREE) LINE1 += ` ${DIM}│${RESET} ${TEAL_DIM}⎇ ${WORKTREE}${RESET}`;
184
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
+ }
185
235
  } catch {
186
- LINE1 = `${TEAL}◆${RESET} ${WHITE}qualia${RESET}`;
236
+ LINE1 = `${TEAL}⬢${RESET} ${WHITE}qualia${RESET}`;
187
237
  }
188
238
 
189
239
  // ─── Line 2: Context bar + Cost + Duration + Model ───────
@@ -48,7 +48,7 @@ if (/CREATE\s+TABLE/i.test(content) && !/ENABLE\s+ROW\s+LEVEL\s+SECURITY/i.test(
48
48
  }
49
49
 
50
50
  if (errors.length > 0) {
51
- console.log(" Migration guard — dangerous patterns found:");
51
+ console.log(" Migration guard — dangerous patterns found:");
52
52
  for (const e of errors) {
53
53
  console.log(` ✗ ${e}`);
54
54
  }
@@ -73,7 +73,7 @@ function scanServiceRoleLeaks() {
73
73
  return leaks;
74
74
  }
75
75
 
76
- console.log(" Pre-deploy gate...");
76
+ console.log(" Pre-deploy gate...");
77
77
 
78
78
  // TypeScript
79
79
  if (fs.existsSync("tsconfig.json")) {
@@ -105,6 +105,6 @@ if (leaks.length > 0) {
105
105
  process.exit(1);
106
106
  }
107
107
  console.log(" ✓ Security");
108
- console.log(" All gates passed.");
108
+ console.log(" All gates passed.");
109
109
 
110
110
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qualia-framework-v2",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Claude Code workflow framework by Qualia Solutions. Plan, build, verify, ship.",
5
5
  "bin": {
6
6
  "qualia-framework-v2": "./bin/cli.js"
@@ -73,7 +73,7 @@ git commit -m "style: design transformation"
73
73
  ```
74
74
 
75
75
  ```
76
- Design Transformation Complete
76
+ Design Transformation Complete
77
77
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
78
78
  Files: {N}
79
79
  Changes:
@@ -70,7 +70,7 @@ echo "{formatted entry}" >> ~/.claude/knowledge/{type}.md
70
70
  ### 4. Confirm
71
71
 
72
72
  ```
73
- Saved to {file}
73
+ Saved to {file}
74
74
  "{title}"
75
75
  ```
76
76
 
@@ -100,7 +100,7 @@ options:
100
100
  description: "Gradients, rounded shapes, vibrant palette"
101
101
  preview: |
102
102
  ┌──────────────────────────────┐
103
- ● ▲ ■ COLORFUL │
103
+ ● ▲ ■ COLORFUL │
104
104
  │ │
105
105
  │ ╭──────╮ ╭──────╮ │
106
106
  │ │ Card │ │ Card │ │
@@ -173,7 +173,7 @@ If there's an entry for this client, show it to the user: *"I have notes on {cli
173
173
  Present a summary:
174
174
 
175
175
  ```
176
- QUALIA PROJECT SUMMARY
176
+ QUALIA PROJECT SUMMARY
177
177
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
178
178
 
179
179
  Project {name}
@@ -64,7 +64,7 @@ Every finding:
64
64
  Write to `.planning/REVIEW.md`. CRITICAL or HIGH findings are deploy blockers — `/qualia-ship` checks for them.
65
65
 
66
66
  ```
67
- Review Complete
67
+ Review Complete
68
68
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
69
69
  Critical: {N}
70
70
  High: {N}