fivocell 3.1.0 → 4.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 (176) hide show
  1. package/dist/__tests__/behavior-intelligence-bug.test.d.ts +2 -0
  2. package/dist/__tests__/behavior-intelligence-bug.test.d.ts.map +1 -0
  3. package/dist/__tests__/behavior-intelligence-bug.test.js +21 -0
  4. package/dist/__tests__/behavior-intelligence-bug.test.js.map +1 -0
  5. package/dist/__tests__/code-scanner-arrow-return-type.test.d.ts +2 -0
  6. package/dist/__tests__/code-scanner-arrow-return-type.test.d.ts.map +1 -0
  7. package/dist/__tests__/code-scanner-arrow-return-type.test.js +76 -0
  8. package/dist/__tests__/code-scanner-arrow-return-type.test.js.map +1 -0
  9. package/dist/__tests__/code-scanner-blindspot.test.d.ts +2 -0
  10. package/dist/__tests__/code-scanner-blindspot.test.d.ts.map +1 -0
  11. package/dist/__tests__/code-scanner-blindspot.test.js +18 -0
  12. package/dist/__tests__/code-scanner-blindspot.test.js.map +1 -0
  13. package/dist/__tests__/code-scanner-error-recovery.test.d.ts +2 -0
  14. package/dist/__tests__/code-scanner-error-recovery.test.d.ts.map +1 -0
  15. package/dist/__tests__/code-scanner-error-recovery.test.js +21 -0
  16. package/dist/__tests__/code-scanner-error-recovery.test.js.map +1 -0
  17. package/dist/__tests__/code-scanner-n1-detection.test.d.ts +2 -0
  18. package/dist/__tests__/code-scanner-n1-detection.test.d.ts.map +1 -0
  19. package/dist/__tests__/code-scanner-n1-detection.test.js +113 -0
  20. package/dist/__tests__/code-scanner-n1-detection.test.js.map +1 -0
  21. package/dist/__tests__/code-scanner-nesting.test.d.ts +2 -0
  22. package/dist/__tests__/code-scanner-nesting.test.d.ts.map +1 -0
  23. package/dist/__tests__/code-scanner-nesting.test.js +113 -0
  24. package/dist/__tests__/code-scanner-nesting.test.js.map +1 -0
  25. package/dist/__tests__/code-scanner-null-check.test.d.ts +2 -0
  26. package/dist/__tests__/code-scanner-null-check.test.d.ts.map +1 -0
  27. package/dist/__tests__/code-scanner-null-check.test.js +126 -0
  28. package/dist/__tests__/code-scanner-null-check.test.js.map +1 -0
  29. package/dist/__tests__/code-scanner-sql-fix.test.d.ts +2 -0
  30. package/dist/__tests__/code-scanner-sql-fix.test.d.ts.map +1 -0
  31. package/dist/__tests__/code-scanner-sql-fix.test.js +21 -0
  32. package/dist/__tests__/code-scanner-sql-fix.test.js.map +1 -0
  33. package/dist/__tests__/code-scanner-trust-score.test.d.ts +1 -0
  34. package/dist/__tests__/code-scanner-trust-score.test.d.ts.map +1 -0
  35. package/dist/__tests__/code-scanner-trust-score.test.js +39 -0
  36. package/dist/__tests__/code-scanner-trust-score.test.js.map +1 -0
  37. package/dist/__tests__/code-scanner-validation.test.d.ts +2 -0
  38. package/dist/__tests__/code-scanner-validation.test.d.ts.map +1 -0
  39. package/dist/__tests__/code-scanner-validation.test.js +131 -0
  40. package/dist/__tests__/code-scanner-validation.test.js.map +1 -0
  41. package/dist/__tests__/community-store.test.d.ts +2 -0
  42. package/dist/__tests__/community-store.test.d.ts.map +1 -0
  43. package/dist/__tests__/community-store.test.js +231 -0
  44. package/dist/__tests__/community-store.test.js.map +1 -0
  45. package/dist/__tests__/enhanced-blind-spots.test.d.ts +2 -0
  46. package/dist/__tests__/enhanced-blind-spots.test.d.ts.map +1 -0
  47. package/dist/__tests__/enhanced-blind-spots.test.js +302 -0
  48. package/dist/__tests__/enhanced-blind-spots.test.js.map +1 -0
  49. package/dist/__tests__/knowledge-graph-store.test.d.ts +2 -0
  50. package/dist/__tests__/knowledge-graph-store.test.d.ts.map +1 -0
  51. package/dist/__tests__/knowledge-graph-store.test.js +252 -0
  52. package/dist/__tests__/knowledge-graph-store.test.js.map +1 -0
  53. package/dist/__tests__/live-watcher.test.d.ts +2 -0
  54. package/dist/__tests__/live-watcher.test.d.ts.map +1 -0
  55. package/dist/__tests__/live-watcher.test.js +312 -0
  56. package/dist/__tests__/live-watcher.test.js.map +1 -0
  57. package/dist/__tests__/mcp-cell-tools.test.d.ts +2 -0
  58. package/dist/__tests__/mcp-cell-tools.test.d.ts.map +1 -0
  59. package/dist/__tests__/mcp-cell-tools.test.js +176 -0
  60. package/dist/__tests__/mcp-cell-tools.test.js.map +1 -0
  61. package/dist/__tests__/multi-project.test.d.ts +2 -0
  62. package/dist/__tests__/multi-project.test.d.ts.map +1 -0
  63. package/dist/__tests__/multi-project.test.js +145 -0
  64. package/dist/__tests__/multi-project.test.js.map +1 -0
  65. package/dist/__tests__/pc-scanner-paths.test.d.ts +2 -0
  66. package/dist/__tests__/pc-scanner-paths.test.d.ts.map +1 -0
  67. package/dist/__tests__/pc-scanner-paths.test.js +16 -0
  68. package/dist/__tests__/pc-scanner-paths.test.js.map +1 -0
  69. package/dist/__tests__/prompt-builder-realdata.test.d.ts +2 -0
  70. package/dist/__tests__/prompt-builder-realdata.test.d.ts.map +1 -0
  71. package/dist/__tests__/prompt-builder-realdata.test.js +94 -0
  72. package/dist/__tests__/prompt-builder-realdata.test.js.map +1 -0
  73. package/dist/__tests__/prompt-builder-sessions.test.d.ts +2 -0
  74. package/dist/__tests__/prompt-builder-sessions.test.d.ts.map +1 -0
  75. package/dist/__tests__/prompt-builder-sessions.test.js +124 -0
  76. package/dist/__tests__/prompt-builder-sessions.test.js.map +1 -0
  77. package/dist/__tests__/security.test.d.ts +1 -0
  78. package/dist/__tests__/security.test.d.ts.map +1 -0
  79. package/dist/__tests__/security.test.js +161 -0
  80. package/dist/__tests__/security.test.js.map +1 -0
  81. package/dist/__tests__/session-bridge.test.d.ts +2 -0
  82. package/dist/__tests__/session-bridge.test.d.ts.map +1 -0
  83. package/dist/__tests__/session-bridge.test.js +158 -0
  84. package/dist/__tests__/session-bridge.test.js.map +1 -0
  85. package/dist/__tests__/session-memory-tables.test.d.ts +2 -0
  86. package/dist/__tests__/session-memory-tables.test.d.ts.map +1 -0
  87. package/dist/__tests__/session-memory-tables.test.js +169 -0
  88. package/dist/__tests__/session-memory-tables.test.js.map +1 -0
  89. package/dist/__tests__/staleness-detection.test.d.ts +2 -0
  90. package/dist/__tests__/staleness-detection.test.d.ts.map +1 -0
  91. package/dist/__tests__/staleness-detection.test.js +105 -0
  92. package/dist/__tests__/staleness-detection.test.js.map +1 -0
  93. package/dist/__tests__/team-collaboration.test.d.ts +2 -0
  94. package/dist/__tests__/team-collaboration.test.d.ts.map +1 -0
  95. package/dist/__tests__/team-collaboration.test.js +224 -0
  96. package/dist/__tests__/team-collaboration.test.js.map +1 -0
  97. package/dist/__tests__/tool-specific-format.test.d.ts +2 -0
  98. package/dist/__tests__/tool-specific-format.test.d.ts.map +1 -0
  99. package/dist/__tests__/tool-specific-format.test.js +132 -0
  100. package/dist/__tests__/tool-specific-format.test.js.map +1 -0
  101. package/dist/__tests__/usage-intelligence-store.test.d.ts +2 -0
  102. package/dist/__tests__/usage-intelligence-store.test.d.ts.map +1 -0
  103. package/dist/__tests__/usage-intelligence-store.test.js +266 -0
  104. package/dist/__tests__/usage-intelligence-store.test.js.map +1 -0
  105. package/dist/ai-bridge.d.ts +20 -0
  106. package/dist/ai-bridge.d.ts.map +1 -0
  107. package/dist/ai-bridge.js +250 -0
  108. package/dist/ai-bridge.js.map +1 -0
  109. package/dist/behavior-intelligence.d.ts.map +1 -1
  110. package/dist/behavior-intelligence.js +12 -1
  111. package/dist/behavior-intelligence.js.map +1 -1
  112. package/dist/cli.js +501 -4
  113. package/dist/cli.js.map +1 -1
  114. package/dist/code-scanner.d.ts.map +1 -1
  115. package/dist/code-scanner.js +426 -69
  116. package/dist/code-scanner.js.map +1 -1
  117. package/dist/core/community-store.d.ts +128 -0
  118. package/dist/core/community-store.d.ts.map +1 -0
  119. package/dist/core/community-store.js +329 -0
  120. package/dist/core/community-store.js.map +1 -0
  121. package/dist/core/database.d.ts +0 -3
  122. package/dist/core/database.d.ts.map +1 -1
  123. package/dist/core/database.js +287 -15
  124. package/dist/core/database.js.map +1 -1
  125. package/dist/core/enhanced-blind-spots.d.ts +27 -0
  126. package/dist/core/enhanced-blind-spots.d.ts.map +1 -0
  127. package/dist/core/enhanced-blind-spots.js +591 -0
  128. package/dist/core/enhanced-blind-spots.js.map +1 -0
  129. package/dist/core/knowledge-graph-store.d.ts +69 -0
  130. package/dist/core/knowledge-graph-store.d.ts.map +1 -0
  131. package/dist/core/knowledge-graph-store.js +269 -0
  132. package/dist/core/knowledge-graph-store.js.map +1 -0
  133. package/dist/core/live-watcher.d.ts +52 -0
  134. package/dist/core/live-watcher.d.ts.map +1 -0
  135. package/dist/core/live-watcher.js +369 -0
  136. package/dist/core/live-watcher.js.map +1 -0
  137. package/dist/core/project-registry.d.ts +24 -0
  138. package/dist/core/project-registry.d.ts.map +1 -0
  139. package/dist/core/project-registry.js +70 -0
  140. package/dist/core/project-registry.js.map +1 -0
  141. package/dist/core/prompt-builder.d.ts +50 -0
  142. package/dist/core/prompt-builder.d.ts.map +1 -1
  143. package/dist/core/prompt-builder.js +533 -79
  144. package/dist/core/prompt-builder.js.map +1 -1
  145. package/dist/core/security.d.ts +23 -0
  146. package/dist/core/security.d.ts.map +1 -0
  147. package/dist/core/security.js +117 -0
  148. package/dist/core/security.js.map +1 -0
  149. package/dist/core/session-memory.d.ts +64 -0
  150. package/dist/core/session-memory.d.ts.map +1 -1
  151. package/dist/core/session-memory.js +111 -0
  152. package/dist/core/session-memory.js.map +1 -1
  153. package/dist/core/usage-intelligence-store.d.ts +126 -0
  154. package/dist/core/usage-intelligence-store.d.ts.map +1 -0
  155. package/dist/core/usage-intelligence-store.js +405 -0
  156. package/dist/core/usage-intelligence-store.js.map +1 -0
  157. package/dist/daemon/server.d.ts.map +1 -1
  158. package/dist/daemon/server.js +936 -17
  159. package/dist/daemon/server.js.map +1 -1
  160. package/dist/knowledge-graph-builder.d.ts +16 -0
  161. package/dist/knowledge-graph-builder.d.ts.map +1 -0
  162. package/dist/knowledge-graph-builder.js +186 -0
  163. package/dist/knowledge-graph-builder.js.map +1 -0
  164. package/dist/pc-scanner.d.ts +1 -0
  165. package/dist/pc-scanner.d.ts.map +1 -1
  166. package/dist/pc-scanner.js +58 -30
  167. package/dist/pc-scanner.js.map +1 -1
  168. package/dist/stack-detector.d.ts +34 -0
  169. package/dist/stack-detector.d.ts.map +1 -0
  170. package/dist/stack-detector.js +471 -0
  171. package/dist/stack-detector.js.map +1 -0
  172. package/dist/team-intel.d.ts +31 -0
  173. package/dist/team-intel.d.ts.map +1 -0
  174. package/dist/team-intel.js +310 -0
  175. package/dist/team-intel.js.map +1 -0
  176. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -55,7 +55,36 @@ const C = {
55
55
  };
56
56
  const project = path.basename(process.cwd());
57
57
  // ─── Parse ──────────────────────────────────────────────────────────────────
58
- const args = process.argv.slice(2);
58
+ // Parse args, treating double-quoted values as single tokens (so paths with spaces survive).
59
+ function parseArgs(argv) {
60
+ const out = [];
61
+ let buf = '';
62
+ let inQuote = false;
63
+ for (const a of argv) {
64
+ if (inQuote) {
65
+ buf += ' ' + a;
66
+ if (a.endsWith('"')) {
67
+ out.push(buf.slice(0, -1));
68
+ buf = '';
69
+ inQuote = false;
70
+ }
71
+ }
72
+ else if (a.startsWith('"') && !a.endsWith('"')) {
73
+ buf = a.slice(1);
74
+ inQuote = true;
75
+ }
76
+ else if (a.startsWith('"') && a.endsWith('"') && a.length > 1) {
77
+ out.push(a.slice(1, -1));
78
+ }
79
+ else {
80
+ out.push(a);
81
+ }
82
+ }
83
+ if (buf)
84
+ out.push(buf);
85
+ return out;
86
+ }
87
+ const args = parseArgs(process.argv.slice(2));
59
88
  const cmd = args[0] || '';
60
89
  switch (cmd) {
61
90
  case 'start':
@@ -67,6 +96,9 @@ switch (cmd) {
67
96
  case 'scan':
68
97
  doScan();
69
98
  break;
99
+ case 'analyze':
100
+ doAnalyze();
101
+ break;
70
102
  case 'status':
71
103
  doStatus();
72
104
  break;
@@ -76,6 +108,12 @@ switch (cmd) {
76
108
  case 'community':
77
109
  doCommunity();
78
110
  break;
111
+ case 'watch':
112
+ doWatch();
113
+ break;
114
+ case 'blindspots':
115
+ doBlindspots();
116
+ break;
79
117
  case 'help':
80
118
  doHelp();
81
119
  break;
@@ -157,6 +195,82 @@ function doStop() {
157
195
  }
158
196
  console.log();
159
197
  }
198
+ // ─── cell analyze ───────────────────────────────────────────────────────────
199
+ function doAnalyze() {
200
+ console.log();
201
+ console.log(C.bold(' Cell AI Analysis'));
202
+ console.log(C.dim(' ────────────────'));
203
+ console.log();
204
+ const sub = args[1] || '';
205
+ // ─── Save AI-generated insights ────────────────────────────────────
206
+ if (sub === '--save' && args[2]) {
207
+ const category = args[2];
208
+ console.log(C.primary(` Save AI insights for: ${category}`));
209
+ console.log(C.dim(' Paste the AI-generated response below (Ctrl+Z or Ctrl+D to finish):'));
210
+ console.log();
211
+ // Read from stdin
212
+ const chunks = [];
213
+ process.stdin.on('data', (chunk) => chunks.push(chunk));
214
+ process.stdin.on('end', () => {
215
+ const content = Buffer.concat(chunks).toString().trim();
216
+ if (content) {
217
+ const { saveAIInsight } = require('./ai-bridge');
218
+ saveAIInsight(project, category, content);
219
+ console.log(C.success(` Insights saved: ${category}`));
220
+ console.log(C.dim(` .cell/personal/insights/${category}.md`));
221
+ console.log();
222
+ process.exit(0);
223
+ }
224
+ else {
225
+ console.log(C.warn(' No content provided.'));
226
+ console.log();
227
+ process.exit(1);
228
+ }
229
+ });
230
+ process.stdin.resume();
231
+ return;
232
+ }
233
+ // ─── Show insights ─────────────────────────────────────────────────
234
+ if (sub === '--show') {
235
+ const { getAIInsights } = require('./ai-bridge');
236
+ const insights = getAIInsights(project);
237
+ if (insights.length === 0) {
238
+ console.log(C.dim(' No AI insights yet. Run: cell analyze'));
239
+ console.log();
240
+ return;
241
+ }
242
+ for (const i of insights) {
243
+ console.log(C.bold(` ${i.category}`));
244
+ console.log(C.dim(` ${i.timestamp} | Source: ${i.source}`));
245
+ console.log(i.content.substring(0, 300));
246
+ console.log(C.dim(' ...'));
247
+ console.log();
248
+ }
249
+ return;
250
+ }
251
+ // ─── Default: Generate prompts ─────────────────────────────────────
252
+ const { getAnalysisCommand } = require('./ai-bridge');
253
+ const { intro, prompts } = getAnalysisCommand(process.cwd());
254
+ console.log(C.dim(intro));
255
+ console.log();
256
+ for (const p of prompts) {
257
+ console.log(C.bold(` ━━━ ${p.title} ━━━`));
258
+ console.log(C.dim(` Tokens: ~${p.tokensEstimate} | Category: ${p.category}`));
259
+ console.log();
260
+ const promptLines = p.prompt.split('\n');
261
+ for (const line of promptLines.slice(0, 10)) {
262
+ console.log(` ${C.dim('│')} ${line}`);
263
+ }
264
+ if (promptLines.length > 10) {
265
+ console.log(` ${C.dim('│')} ... (${promptLines.length - 10} more lines)`);
266
+ }
267
+ console.log();
268
+ console.log(C.primary(` → Copy to AI tool, get answer, then: cell analyze --save ${p.category}`));
269
+ console.log();
270
+ }
271
+ console.log(C.dim(' cell analyze --show View saved insights'));
272
+ console.log();
273
+ }
160
274
  // ─── cell scan ───────────────────────────────────────────────────────────────
161
275
  function doScan() {
162
276
  const banner = figlet_1.default.textSync('CELL', { font: 'ANSI Shadow', horizontalLayout: 'fitted' });
@@ -222,9 +336,25 @@ function showProjectStatus() {
222
336
  console.log();
223
337
  console.log(C.bold(' 📂 Personal Layer'));
224
338
  console.log(C.dim(' ─────────────────'));
225
- console.log(` Style: ${C.num(profile.quoteStyle)} quotes, ${C.num(profile.semicolonStyle)} semis, ${C.num(profile.indentStyle)}`);
339
+ // Stack fingerprint (from stack-detector)
340
+ try {
341
+ const { detectProjectDNA } = require('./stack-detector');
342
+ const dna = detectProjectDNA(process.cwd());
343
+ if (dna && dna.stack.trustScore > 0) {
344
+ const s = dna.stack;
345
+ console.log(` Stack: ${C.num(s.languages?.join(', ') || '')} · ${s.frontend !== 'none' ? s.frontend + ' + ' : ''}${s.backend}${s.database[0] !== 'none' ? ' · ' + s.database.join(', ') : ''}`);
346
+ console.log(` ${s.orm !== 'none' ? 'ORM: ' + s.orm + ' · ' : ''}Test: ${s.testing.join(', ')}${s.validation !== 'none' ? ' · Validation: ' + s.validation : ''}`);
347
+ console.log(` Arch: ${dna.architecture.type} (${dna.architecture.confidence}), Entry: ${dna.architecture.entryPoints.join(', ')}`);
348
+ console.log(` Style: ${C.num(profile.quoteStyle)} quotes, ${C.num(profile.semicolonStyle)} semis, ${C.num(profile.indentStyle)}`);
349
+ }
350
+ else {
351
+ console.log(` Style: ${C.num(profile.quoteStyle)} quotes, ${C.num(profile.semicolonStyle)} semis, ${C.num(profile.indentStyle)}`);
352
+ }
353
+ }
354
+ catch {
355
+ console.log(` Style: ${C.num(profile.quoteStyle)} quotes, ${C.num(profile.semicolonStyle)} semis, ${C.num(profile.indentStyle)}`);
356
+ }
226
357
  console.log(` Code: ${C.num(profile.functionStyle)} functions, ${C.num(profile.asyncStyle)}, ${C.num(profile.errorHandling)} errors`);
227
- console.log(` Arch: ${C.num(profile.architectureStyle)}, ${C.num(profile.testPattern)} tests`);
228
358
  if (profile.strengths.length) {
229
359
  for (const s of profile.strengths)
230
360
  console.log(` ${C.success('+')} ${s}`);
@@ -392,6 +522,22 @@ function doTeam() {
392
522
  console.log();
393
523
  return;
394
524
  }
525
+ // ─── team onboard ───────────────────────────────────────────────────
526
+ if (sub === 'onboard' && args[2]) {
527
+ const newMember = args[2];
528
+ const teamPath = path.join(process.cwd(), '.cell', 'team');
529
+ console.log(C.primary(` Generating onboarding guide for ${newMember}...`));
530
+ const { generateOnboardingGuide, formatOnboardingText } = require('./team-intel');
531
+ const guide = generateOnboardingGuide(teamPath, newMember);
532
+ if (guide) {
533
+ console.log(formatOnboardingText(guide));
534
+ }
535
+ else {
536
+ console.log(C.warn(' No team data found. Run: cell team push <your-name> first.'));
537
+ }
538
+ console.log();
539
+ return;
540
+ }
395
541
  // ─── team status ────────────────────────────────────────────────────
396
542
  if (sub === 'status') {
397
543
  const { teamStatus } = require('./team-git');
@@ -432,11 +578,191 @@ function doTeam() {
432
578
  console.log(C.success(` + Strongest: ${intel.summary.strongestArea}`));
433
579
  if (intel.summary.weakestArea)
434
580
  console.log(C.warn(` ! Weakest: ${intel.summary.weakestArea}`));
581
+ // Team pattern library
582
+ const teamPath = path.join(process.cwd(), '.cell', 'team');
583
+ try {
584
+ const { buildTeamPatternLibrary } = require('./team-intel');
585
+ const rules = buildTeamPatternLibrary(teamPath);
586
+ if (rules.length > 0) {
587
+ console.log(C.bold(' 📋 Pattern Library:'));
588
+ const doRules = rules.filter((r) => r.type === 'do').slice(0, 3);
589
+ const dontRules = rules.filter((r) => r.type === 'dont').slice(0, 2);
590
+ for (const r of doRules) {
591
+ console.log(` ${C.success('✓')} ${r.rule} (${r.agreement}% agreement)`);
592
+ }
593
+ for (const r of dontRules) {
594
+ console.log(` ${C.warn('✗')} ${r.rule}`);
595
+ }
596
+ }
597
+ }
598
+ catch { }
435
599
  if (intel.summary.criticalBlindSpots > 0)
436
600
  console.log(C.warn(` ! ${intel.summary.criticalBlindSpots} critical blind spots`));
437
601
  console.log();
438
602
  return;
439
603
  }
604
+ // ─── team silos ─────────────────────────────────────────────────────
605
+ if (sub === 'silos') {
606
+ const { detectKnowledgeSilos } = require('./team-collaboration');
607
+ const silos = detectKnowledgeSilos();
608
+ console.log(C.bold(` Knowledge Silos: ${silos.length}`));
609
+ console.log();
610
+ if (silos.length === 0) {
611
+ console.log(C.dim(' No silos detected. Knowledge is well distributed.'));
612
+ }
613
+ else {
614
+ for (const s of silos.slice(0, 10)) {
615
+ const riskColor = s.riskLevel === 'high' ? C.warn : s.riskLevel === 'medium' ? C.primary : C.dim;
616
+ console.log(` ${riskColor('●')} ${s.name} — ${s.knowledgeArea}`);
617
+ console.log(C.dim(` ${s.members.join(', ')} (bus factor: ${s.busFactor})`));
618
+ }
619
+ }
620
+ console.log();
621
+ return;
622
+ }
623
+ // ─── team bus-factor ───────────────────────────────────────────────
624
+ if (sub === 'bus-factor') {
625
+ const { calculateBusFactor } = require('./team-collaboration');
626
+ const report = calculateBusFactor();
627
+ console.log(C.bold(` Bus Factor: ${report.overallScore}/100`));
628
+ console.log();
629
+ if (report.singlePointsOfFailure.length > 0) {
630
+ console.log(C.warn(' Single Points of Failure:'));
631
+ for (const spof of report.singlePointsOfFailure.slice(0, 5)) {
632
+ console.log(C.warn(` ⚠ ${spof}`));
633
+ }
634
+ console.log();
635
+ }
636
+ if (report.members.length > 0) {
637
+ console.log(C.dim(' Top members:'));
638
+ for (const m of report.members.slice(0, 5)) {
639
+ console.log(` ${m.name}: score ${m.score} (${m.risk} risk)`);
640
+ }
641
+ }
642
+ console.log();
643
+ return;
644
+ }
645
+ // ─── team health ───────────────────────────────────────────────────
646
+ if (sub === 'health') {
647
+ const { getTeamHealth } = require('./team-collaboration');
648
+ const health = getTeamHealth(args[2]);
649
+ console.log(C.bold(` Team Health: ${health.score}/100`));
650
+ console.log();
651
+ console.log(C.dim(` Bus factor: ${health.busFactor}, Silos: ${health.siloCount}, Edges: ${health.collaborationEdges}`));
652
+ if (health.strengths.length > 0) {
653
+ console.log(C.success(' Strengths:'));
654
+ for (const s of health.strengths.slice(0, 3))
655
+ console.log(C.success(` + ${s}`));
656
+ }
657
+ if (health.skillGaps.length > 0) {
658
+ console.log(C.warn(' Skill gaps:'));
659
+ for (const g of health.skillGaps.slice(0, 3))
660
+ console.log(C.warn(` ! ${g}`));
661
+ }
662
+ if (health.recommendations.length > 0) {
663
+ console.log(C.primary(' Recommendations:'));
664
+ for (const r of health.recommendations.slice(0, 3))
665
+ console.log(` → ${r}`);
666
+ }
667
+ console.log();
668
+ return;
669
+ }
670
+ // ─── community sub-commands ─────────────────────────────────────────
671
+ if (sub === 'community' || sub === 'comm') {
672
+ const csub = args[2];
673
+ if (csub === 'stats') {
674
+ const { getCommunityStats } = require('./core/community-store');
675
+ const stats = getCommunityStats();
676
+ console.log(C.bold(' Community Stats'));
677
+ console.log(C.dim(` Patterns: ${stats.totalPatterns}, Insights: ${stats.totalInsights}, Benchmarks: ${stats.totalBenchmarks}`));
678
+ console.log(C.dim(` Total votes: ${stats.totalVotes}`));
679
+ if (Object.keys(stats.byCategory).length > 0) {
680
+ console.log(C.dim(' By category:'));
681
+ for (const [cat, count] of Object.entries(stats.byCategory)) {
682
+ console.log(` ${cat}: ${count}`);
683
+ }
684
+ }
685
+ console.log();
686
+ return;
687
+ }
688
+ if (csub === 'share' && args[3]) {
689
+ const { shareCommunityPattern, validatePrivacy } = require('./core/community-store');
690
+ const rule = args[3];
691
+ const category = args[4] || 'general';
692
+ const language = args[5];
693
+ const validation = validatePrivacy(rule);
694
+ if (!validation.safe) {
695
+ console.log(C.warn(' Blocked — privacy violations:'));
696
+ for (const e of validation.errors)
697
+ console.log(C.warn(` ✗ ${e}`));
698
+ console.log();
699
+ return;
700
+ }
701
+ const result = shareCommunityPattern({ category, rule, language });
702
+ console.log(C.success(` Shared: ${result.patternId}`));
703
+ if (result.warnings.length > 0) {
704
+ console.log(C.dim(' Warnings:'));
705
+ for (const w of result.warnings)
706
+ console.log(C.dim(` - ${w}`));
707
+ }
708
+ console.log();
709
+ return;
710
+ }
711
+ if (csub === 'trends') {
712
+ const { getTechEvolution } = require('./core/community-store');
713
+ const trends = getTechEvolution();
714
+ console.log(C.bold(' Technology Trends'));
715
+ for (const t of trends.slice(0, 10)) {
716
+ const arrow = t.trend30d > 0 ? C.success('↑') : t.trend30d < 0 ? C.warn('↓') : C.dim('→');
717
+ console.log(` ${arrow} ${t.technology} — ${t.adoptionPhase} (${t.currentUsage} signals)`);
718
+ }
719
+ console.log();
720
+ return;
721
+ }
722
+ console.log(C.dim(' Usage: cell team community [stats|share <rule> <category>|trends]'));
723
+ console.log();
724
+ return;
725
+ }
726
+ // ─── team usage (Phase 6) ──────────────────────────────────────────
727
+ if (sub === 'usage') {
728
+ const { getUsageDashboard, getDecisionPatterns, detectRepeatMistakes, getBurnoutSignals } = require('./core/usage-intelligence-store');
729
+ const project = args[2] || 'Fivo-Cell';
730
+ const dash = getUsageDashboard(project);
731
+ console.log(C.bold(` Usage Dashboard — ${project}`));
732
+ console.log();
733
+ console.log(C.dim(` Decisions: ${dash.decisions.total} (${dash.decisions.right} right, ${dash.decisions.wrong} wrong)`));
734
+ if (dash.decisions.topPatterns.length > 0) {
735
+ console.log(C.bold(' Decision Patterns:'));
736
+ for (const p of dash.decisions.topPatterns.slice(0, 3)) {
737
+ console.log(` ${p.advice}`);
738
+ }
739
+ }
740
+ console.log();
741
+ console.log(C.dim(` Mistakes: ${dash.mistakes.total} repeated (${dash.mistakes.critical} critical)`));
742
+ if (dash.mistakes.top.length > 0) {
743
+ for (const m of dash.mistakes.top.slice(0, 3)) {
744
+ console.log(` ${C.warn('!')} ${m.errorType} (${m.count}x) — ${m.suggestion}`);
745
+ }
746
+ }
747
+ console.log();
748
+ console.log(C.dim(` AI: ${dash.ai.modelsUsed} models, avg acceptance ${dash.ai.avgAcceptance}%`));
749
+ if (dash.ai.topModel !== 'none')
750
+ console.log(C.dim(` Top model: ${dash.ai.topModel}`));
751
+ console.log();
752
+ console.log(C.dim(` Productivity: flow ${dash.productivity.flowScore}, friction ${dash.productivity.frictionScore}`));
753
+ console.log();
754
+ console.log(C.dim(` Skills: ${dash.skills.improving} improving, ${dash.skills.plateau} plateau, ${dash.skills.regressing} regressing`));
755
+ console.log();
756
+ const burnoutColor = dash.burnout.risk === 'high' ? C.warn : dash.burnout.risk === 'medium' ? C.primary : C.success;
757
+ console.log(burnoutColor(` Burnout risk: ${dash.burnout.risk.toUpperCase()}`));
758
+ if (dash.burnout.signals.length > 0) {
759
+ for (const s of dash.burnout.signals)
760
+ console.log(C.dim(` - ${s}`));
761
+ }
762
+ console.log(C.dim(` ${dash.burnout.advice}`));
763
+ console.log();
764
+ return;
765
+ }
440
766
  if (sub === 'add' && args[2]) {
441
767
  const name = args[2];
442
768
  const role = args[3] || 'developer';
@@ -471,9 +797,176 @@ function doTeam() {
471
797
  console.log(` ${C.primary('cell team push <name>')} Share your patterns with team`);
472
798
  console.log(` ${C.primary('cell team pull')} Pull team data from git`);
473
799
  console.log(` ${C.primary('cell team status')} Team intelligence dashboard`);
800
+ console.log(` ${C.primary('cell team silos')} Knowledge silo detection`);
801
+ console.log(` ${C.primary('cell team bus-factor')} Bus factor analysis`);
802
+ console.log(` ${C.primary('cell team health [proj]')} Team health score`);
803
+ console.log(` ${C.primary('cell team community')} Community stats/share/trends`);
804
+ console.log(` ${C.primary('cell team usage [proj]')} Personal usage intelligence`);
474
805
  console.log(` ${C.primary('cell team add/remove')} Manage members`);
475
806
  console.log();
476
807
  }
808
+ // ─── cell watch ─────────────────────────────────────────────────────────────
809
+ function doWatch() {
810
+ console.log();
811
+ console.log(C.bold(' Cell Live Watcher'));
812
+ console.log(C.dim(' ─────────────────'));
813
+ console.log();
814
+ const sub = args[1] || 'daemon';
815
+ const project = args[2] || path.basename(process.cwd());
816
+ const dir = args[3] || process.cwd();
817
+ // If invoked with no subcommand: run as a long-lived watcher daemon (for .bat auto-restart loop)
818
+ if (sub === 'daemon' || sub === '') {
819
+ runWatchDaemon(project, dir);
820
+ return;
821
+ }
822
+ try {
823
+ const liveWatcher = require('./core/live-watcher');
824
+ const http = require('http');
825
+ function callDaemon(toolName, toolArgs) {
826
+ return new Promise((resolve, reject) => {
827
+ const body = JSON.stringify({ method: 'tools/call', params: { name: toolName, arguments: toolArgs } });
828
+ const req = http.request({ hostname: '127.0.0.1', port: 9876, path: '/mcp', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } }, (res) => {
829
+ let data = '';
830
+ res.on('data', (chunk) => { data += chunk; });
831
+ res.on('end', () => {
832
+ try {
833
+ const parsed = JSON.parse(data);
834
+ resolve(parsed.result || parsed);
835
+ }
836
+ catch (e) {
837
+ reject(e);
838
+ }
839
+ });
840
+ });
841
+ req.on('error', reject);
842
+ req.write(body);
843
+ req.end();
844
+ });
845
+ }
846
+ if (sub === 'start' || sub === 'stop') {
847
+ // Watcher state lives in daemon's in-memory map; CLI must talk to daemon
848
+ const toolName = sub === 'start' ? 'cell_watch_start' : 'cell_watch_stop';
849
+ const toolArgs = { project };
850
+ if (sub === 'start')
851
+ toolArgs.dir = dir;
852
+ callDaemon(toolName, toolArgs).then((r) => {
853
+ const ok = sub === 'start' ? r.started : r.stopped;
854
+ console.log(ok ? C.success(` ✓ ${r.message}`) : C.warn(` ! ${r.message}`));
855
+ console.log();
856
+ }).catch((e) => {
857
+ const msg = e instanceof Error ? e.message : String(e);
858
+ console.log(C.warn(` Daemon not running (${msg}). Start with: cell start`));
859
+ console.log();
860
+ });
861
+ return;
862
+ }
863
+ if (sub === 'events') {
864
+ const events = liveWatcher.getLiveEvents(project, 20);
865
+ if (events.length === 0) {
866
+ console.log(C.dim(` No live events for ${project} yet. Start watcher with: cell watch start ${project}`));
867
+ }
868
+ else {
869
+ console.log(C.bold(` Recent events for ${project} (${events.length}):`));
870
+ for (const e of events) {
871
+ const icon = e.eventType === 'file_save' ? '~' : e.eventType === 'file_create' ? '+' : e.eventType === 'file_delete' ? '-' : '*';
872
+ console.log(` ${C.dim(icon)} ${C.dim(e.createdAt)} ${e.eventType}: ${C.num(e.filePath)}`);
873
+ }
874
+ }
875
+ }
876
+ else if (sub === 'refresh') {
877
+ const result = liveWatcher.performAutoRefresh(project, true);
878
+ console.log(C.success(` ✓ Refresh logged: ${result.details} (${result.durationMs}ms)`));
879
+ }
880
+ else if (sub === 'check') {
881
+ const check = liveWatcher.checkIfNeedsRefresh(project);
882
+ const needs = check.needsRefresh;
883
+ console.log(needs ? C.warn(` ⚠ Needs refresh: ${check.reason}`) : C.success(` ✓ ${check.reason}`));
884
+ console.log(C.dim(` Data age: ${check.dataAge} | Recommended: ${check.recommendedAction}`));
885
+ }
886
+ else {
887
+ // status
888
+ const status = liveWatcher.getWatcherStatus(project);
889
+ const active = liveWatcher.getActiveWatchers();
890
+ if (status && status.active) {
891
+ console.log(C.success(` ● ${project}: ${C.bold('LIVE')} — ${status.eventCount} events, last: ${status.lastEventAt || 'never'}`));
892
+ }
893
+ else {
894
+ console.log(C.dim(` ○ ${project}: not watched`));
895
+ }
896
+ if (active.length > 1 || (active.length === 1 && active[0]?.project !== project)) {
897
+ console.log();
898
+ console.log(C.bold(' Other active watchers:'));
899
+ for (const a of active) {
900
+ if (a.project !== project)
901
+ console.log(` ● ${a.project} (${a.eventCount} events)`);
902
+ }
903
+ }
904
+ }
905
+ }
906
+ catch (err) {
907
+ const msg = err instanceof Error ? err.message : String(err);
908
+ console.log(C.warn(` Watch error: ${msg}`));
909
+ }
910
+ console.log();
911
+ }
912
+ // ─── cell blindspots ────────────────────────────────────────────────────────
913
+ function doBlindspots() {
914
+ console.log();
915
+ console.log(C.bold(' Cell Blind Spots'));
916
+ console.log(C.dim(' ────────────────'));
917
+ console.log();
918
+ const dir = args[1] || process.cwd();
919
+ const maxFiles = parseInt(args[2] || '200', 10);
920
+ try {
921
+ const { scanDirectoryForBlindSpots, formatBlindSpotReport, summarizeBlindSpots } = require('./core/enhanced-blind-spots');
922
+ console.log(C.dim(` Scanning ${dir} (max ${maxFiles} files)...`));
923
+ const spots = scanDirectoryForBlindSpots(dir, maxFiles);
924
+ console.log();
925
+ console.log(formatBlindSpotReport(spots));
926
+ const summary = summarizeBlindSpots(spots);
927
+ if (Object.keys(summary.byCategory).length > 0) {
928
+ console.log();
929
+ console.log(C.dim(' By category:'));
930
+ for (const [cat, count] of Object.entries(summary.byCategory)) {
931
+ console.log(` ${C.num(String(count))} ${cat}`);
932
+ }
933
+ }
934
+ }
935
+ catch (err) {
936
+ const msg = err instanceof Error ? err.message : String(err);
937
+ console.log(C.warn(` Blind spot scan failed: ${msg}`));
938
+ }
939
+ console.log();
940
+ }
941
+ // Long-lived watcher daemon — auto-attaches to current project, runs forever.
942
+ // Used by fivo-cell-daemon.bat to keep a watcher alive in the background.
943
+ function runWatchDaemon(project, dir) {
944
+ const liveWatcher = require('./core/live-watcher');
945
+ const result = liveWatcher.startWatcher(project, dir);
946
+ if (!result.started) {
947
+ // "already running" means the daemon process already has a watcher; keep this process alive anyway
948
+ console.log(` Watcher for ${project}: ${result.message}`);
949
+ }
950
+ else {
951
+ console.log(` ✓ Watcher attached: ${result.message}`);
952
+ }
953
+ console.log(` Watching ${dir} for changes. Press Ctrl+C to stop.`);
954
+ console.log();
955
+ // Keep the process alive — the file watcher uses fs.watch which keeps the event loop busy,
956
+ // but we add an explicit interval as a belt-and-braces guard against premature exit.
957
+ const keepAlive = setInterval(() => { }, 60_000);
958
+ process.on('SIGINT', () => {
959
+ clearInterval(keepAlive);
960
+ liveWatcher.stopWatcher(project);
961
+ console.log(`\n Watcher stopped for ${project}.`);
962
+ process.exit(0);
963
+ });
964
+ process.on('SIGTERM', () => {
965
+ clearInterval(keepAlive);
966
+ liveWatcher.stopWatcher(project);
967
+ process.exit(0);
968
+ });
969
+ }
477
970
  // ─── cell community ─────────────────────────────────────────────────────────
478
971
  function doCommunity() {
479
972
  console.log();
@@ -546,9 +1039,13 @@ function doHelp() {
546
1039
  console.log(` ${C.primary('cell start')} Start daemon + MCP (port 9876)`);
547
1040
  console.log(` ${C.primary('cell stop')} Stop daemon`);
548
1041
  console.log(` ${C.primary('cell scan')} Scan codebase + build layers`);
1042
+ console.log(` ${C.primary('cell analyze')} AI prompts from scan data`);
549
1043
  console.log(` ${C.primary('cell status')} What Cell knows about you`);
550
1044
  console.log(` ${C.primary('cell team')} Team collaboration (git-based)`);
551
- console.log(` ${C.primary('cell community')} Community features`);
1045
+ console.log(` ${C.primary('cell community')} Community patterns + benchmarks`);
1046
+ console.log(` ${C.primary('cell watch [start|stop|events|check|status] [proj] [dir]')} Live file watcher`);
1047
+ console.log(` ${C.primary('cell watch daemon [proj] [dir]')} Run as long-lived watcher (for .bat)`);
1048
+ console.log(` ${C.primary('cell blindspots [dir] [maxFiles]')} Scan for blind spots (15+ types)`);
552
1049
  console.log(` ${C.primary('cell help')} Show this help`);
553
1050
  console.log();
554
1051
  console.log(C.dim(' Install: npm i -g fivocell'));