cmp-standards 3.5.1 → 3.7.1

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 (139) hide show
  1. package/README.md +399 -633
  2. package/dist/analytics/CrossProjectAnalytics.js +65 -65
  3. package/dist/cli/index.js +255 -12
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/dashboard/tokens.js +173 -173
  6. package/dist/db/cloud.d.ts +1 -0
  7. package/dist/db/cloud.d.ts.map +1 -1
  8. package/dist/db/migrations.js +256 -256
  9. package/dist/db/turso-client.js +2 -2
  10. package/dist/db/upstash-client.d.ts +9 -0
  11. package/dist/db/upstash-client.d.ts.map +1 -1
  12. package/dist/db/upstash-client.js +11 -0
  13. package/dist/db/upstash-client.js.map +1 -1
  14. package/dist/eslint/rules/no-async-useeffect.js +6 -6
  15. package/dist/experts/ExpertVotePersistence.js +9 -9
  16. package/dist/hooks/auto-learning-hook.d.ts +48 -0
  17. package/dist/hooks/auto-learning-hook.d.ts.map +1 -0
  18. package/dist/hooks/auto-learning-hook.js +258 -0
  19. package/dist/hooks/auto-learning-hook.js.map +1 -0
  20. package/dist/hooks/cloud-post-tool-use.d.ts.map +1 -1
  21. package/dist/hooks/cloud-post-tool-use.js +72 -10
  22. package/dist/hooks/cloud-post-tool-use.js.map +1 -1
  23. package/dist/hooks/cloud-pre-tool-use.d.ts +12 -9
  24. package/dist/hooks/cloud-pre-tool-use.d.ts.map +1 -1
  25. package/dist/hooks/cloud-pre-tool-use.js +227 -99
  26. package/dist/hooks/cloud-pre-tool-use.js.map +1 -1
  27. package/dist/hooks/cloud-session-start.js +5 -5
  28. package/dist/hooks/fast-session-start.d.ts +24 -0
  29. package/dist/hooks/fast-session-start.d.ts.map +1 -0
  30. package/dist/hooks/fast-session-start.js +354 -0
  31. package/dist/hooks/fast-session-start.js.map +1 -0
  32. package/dist/hooks/resilient-hook-runner.d.ts +78 -0
  33. package/dist/hooks/resilient-hook-runner.d.ts.map +1 -0
  34. package/dist/hooks/resilient-hook-runner.js +201 -0
  35. package/dist/hooks/resilient-hook-runner.js.map +1 -0
  36. package/dist/hooks/session-end.js +14 -14
  37. package/dist/index.d.ts +12 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +17 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/patterns/registry.js +90 -90
  42. package/dist/schema/codewiki-types.d.ts +10 -10
  43. package/dist/schema/docs-types.d.ts +8 -8
  44. package/dist/schema/ecosystem-types.d.ts +12 -12
  45. package/dist/services/BootstrapService.d.ts +123 -0
  46. package/dist/services/BootstrapService.d.ts.map +1 -0
  47. package/dist/services/BootstrapService.js +309 -0
  48. package/dist/services/BootstrapService.js.map +1 -0
  49. package/dist/services/CodeWikiIndexer.js +3 -3
  50. package/dist/services/ContextGenerator.js +7 -7
  51. package/dist/services/FeedbackCollector.js +11 -11
  52. package/dist/services/GitIntegration.js +9 -9
  53. package/dist/services/HookVerifier.js +70 -70
  54. package/dist/services/KnowledgeGapDetector.d.ts +122 -0
  55. package/dist/services/KnowledgeGapDetector.d.ts.map +1 -0
  56. package/dist/services/KnowledgeGapDetector.js +530 -0
  57. package/dist/services/KnowledgeGapDetector.js.map +1 -0
  58. package/dist/services/ProjectScaffold.d.ts.map +1 -1
  59. package/dist/services/ProjectScaffold.js +79 -78
  60. package/dist/services/ProjectScaffold.js.map +1 -1
  61. package/dist/services/auto-evolution-trigger.d.ts +101 -0
  62. package/dist/services/auto-evolution-trigger.d.ts.map +1 -0
  63. package/dist/services/auto-evolution-trigger.js +359 -0
  64. package/dist/services/auto-evolution-trigger.js.map +1 -0
  65. package/dist/services/cloud-memory-service.d.ts +101 -0
  66. package/dist/services/cloud-memory-service.d.ts.map +1 -0
  67. package/dist/services/cloud-memory-service.js +363 -0
  68. package/dist/services/cloud-memory-service.js.map +1 -0
  69. package/dist/services/index.d.ts +4 -0
  70. package/dist/services/index.d.ts.map +1 -1
  71. package/dist/services/index.js +6 -0
  72. package/dist/services/index.js.map +1 -1
  73. package/dist/services/knowledge-graph.d.ts +121 -0
  74. package/dist/services/knowledge-graph.d.ts.map +1 -0
  75. package/dist/services/knowledge-graph.js +446 -0
  76. package/dist/services/knowledge-graph.js.map +1 -0
  77. package/dist/services/memory-keeper-client.d.ts +106 -0
  78. package/dist/services/memory-keeper-client.d.ts.map +1 -0
  79. package/dist/services/memory-keeper-client.js +319 -0
  80. package/dist/services/memory-keeper-client.js.map +1 -0
  81. package/dist/services/memory-router.d.ts +25 -0
  82. package/dist/services/memory-router.d.ts.map +1 -1
  83. package/dist/services/memory-router.js +236 -98
  84. package/dist/services/memory-router.js.map +1 -1
  85. package/dist/services/pattern-learning.d.ts +79 -0
  86. package/dist/services/pattern-learning.d.ts.map +1 -0
  87. package/dist/services/pattern-learning.js +312 -0
  88. package/dist/services/pattern-learning.js.map +1 -0
  89. package/dist/services/pattern-tracker.js +95 -95
  90. package/dist/services/semantic-search.js +2 -2
  91. package/dist/services/skill-learning-bridge.d.ts +100 -0
  92. package/dist/services/skill-learning-bridge.d.ts.map +1 -0
  93. package/dist/services/skill-learning-bridge.js +331 -0
  94. package/dist/services/skill-learning-bridge.js.map +1 -0
  95. package/dist/services/unified-memory-router.d.ts +123 -0
  96. package/dist/services/unified-memory-router.d.ts.map +1 -0
  97. package/dist/services/unified-memory-router.js +555 -0
  98. package/dist/services/unified-memory-router.js.map +1 -0
  99. package/package.json +124 -116
  100. package/standards/README.md +94 -50
  101. package/standards/experts/expert-routing.md +215 -215
  102. package/standards/general/code-quality.md +86 -86
  103. package/standards/general/ecosystem.md +243 -0
  104. package/standards/general/learning-loop.md +192 -0
  105. package/standards/general/memory-usage.md +205 -205
  106. package/standards/general/project-onboarding.md +339 -0
  107. package/standards/general/sync-workflow.md +235 -235
  108. package/standards/general/workflow.md +82 -82
  109. package/standards/hooks/mandatory-tracking.md +446 -446
  110. package/standards/infrastructure/cloud-database.md +287 -287
  111. package/standards/mcp/server-design.md +243 -243
  112. package/standards/mcp/tool-patterns.md +354 -354
  113. package/standards/skills/skill-structure.md +286 -286
  114. package/standards/skills/workflow-design.md +323 -323
  115. package/standards/tools/tool-design.md +297 -297
  116. package/templates/agents/architecture-expert.md +61 -61
  117. package/templates/agents/database-expert.md +62 -62
  118. package/templates/agents/documentation-expert.md +57 -57
  119. package/templates/agents/ecosystem-expert.md +104 -0
  120. package/templates/agents/memory-expert.md +88 -88
  121. package/templates/agents/performance-expert.md +61 -61
  122. package/templates/agents/security-expert.md +59 -59
  123. package/templates/agents/ux-expert.md +63 -63
  124. package/templates/agents/worker.md +75 -75
  125. package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
  126. package/templates/claude-settings.json +72 -72
  127. package/templates/commands/experts.md +138 -138
  128. package/templates/hooks/README.md +158 -158
  129. package/templates/hooks/project.config.json.template +77 -77
  130. package/templates/hooks/settings.local.json.template +57 -57
  131. package/templates/hooks.config.json +21 -0
  132. package/templates/memory-config.json +56 -56
  133. package/templates/memory-config.schema.json +212 -212
  134. package/templates/settings.json +58 -58
  135. package/templates/skills/continue.md +205 -205
  136. package/templates/workflows/business-improvement.md +264 -264
  137. package/templates/workflows/expert-review.md +153 -153
  138. package/templates/workflows/internal-app.md +245 -245
  139. package/templates/workflows/sync-docs.md +187 -187
@@ -28,8 +28,8 @@ export class CrossProjectAnalyticsService {
28
28
  const db = turso.getClient();
29
29
  const metrics = [];
30
30
  // Get all systems
31
- const systemsResult = await db.execute(`
32
- SELECT DISTINCT system FROM items WHERE status = 'active'
31
+ const systemsResult = await db.execute(`
32
+ SELECT DISTINCT system FROM items WHERE status = 'active'
33
33
  `);
34
34
  const systems = systemsResult.rows
35
35
  .map(r => r.system)
@@ -37,14 +37,14 @@ export class CrossProjectAnalyticsService {
37
37
  for (const system of systems) {
38
38
  const [itemsResult, sessionsResult, lastActivityResult] = await Promise.all([
39
39
  db.execute({
40
- sql: `SELECT type, COUNT(*) as count FROM items
41
- WHERE system = ? AND status = 'active'
40
+ sql: `SELECT type, COUNT(*) as count FROM items
41
+ WHERE system = ? AND status = 'active'
42
42
  GROUP BY type`,
43
43
  args: [system],
44
44
  }),
45
45
  db.execute({
46
- sql: `SELECT COUNT(*) as count FROM items
47
- WHERE system = ? AND type = 'agent_session'
46
+ sql: `SELECT COUNT(*) as count FROM items
47
+ WHERE system = ? AND type = 'agent_session'
48
48
  AND created_at > datetime('now', '-7 days')`,
49
49
  args: [system],
50
50
  }),
@@ -117,18 +117,18 @@ export class CrossProjectAnalyticsService {
117
117
  const insights = [];
118
118
  const db = turso.getClient();
119
119
  // Find shared patterns across projects
120
- const sharedPatternsResult = await db.execute(`
121
- SELECT
122
- json_extract(content, '$.patternId') as patternId,
123
- COUNT(DISTINCT system) as systemCount,
124
- GROUP_CONCAT(DISTINCT system) as systems,
125
- SUM(json_extract(content, '$.count')) as totalCount
126
- FROM items
127
- WHERE type = 'pattern' AND status = 'active'
128
- GROUP BY patternId
129
- HAVING systemCount > 1
130
- ORDER BY totalCount DESC
131
- LIMIT 10
120
+ const sharedPatternsResult = await db.execute(`
121
+ SELECT
122
+ json_extract(content, '$.patternId') as patternId,
123
+ COUNT(DISTINCT system) as systemCount,
124
+ GROUP_CONCAT(DISTINCT system) as systems,
125
+ SUM(json_extract(content, '$.count')) as totalCount
126
+ FROM items
127
+ WHERE type = 'pattern' AND status = 'active'
128
+ GROUP BY patternId
129
+ HAVING systemCount > 1
130
+ ORDER BY totalCount DESC
131
+ LIMIT 10
132
132
  `);
133
133
  for (const row of sharedPatternsResult.rows) {
134
134
  // Skip rows with missing or invalid systems data
@@ -187,15 +187,15 @@ export class CrossProjectAnalyticsService {
187
187
  async comparePatterns(options) {
188
188
  const db = turso.getClient();
189
189
  const comparisons = [];
190
- const result = await db.execute(`
191
- SELECT
192
- json_extract(content, '$.patternId') as patternId,
193
- json_extract(content, '$.description') as description,
194
- system,
195
- json_extract(content, '$.count') as count
196
- FROM items
197
- WHERE type = 'pattern' AND status = 'active'
198
- ORDER BY patternId
190
+ const result = await db.execute(`
191
+ SELECT
192
+ json_extract(content, '$.patternId') as patternId,
193
+ json_extract(content, '$.description') as description,
194
+ system,
195
+ json_extract(content, '$.count') as count
196
+ FROM items
197
+ WHERE type = 'pattern' AND status = 'active'
198
+ ORDER BY patternId
199
199
  `);
200
200
  // Group by pattern
201
201
  const patternGroups = new Map();
@@ -236,25 +236,25 @@ export class CrossProjectAnalyticsService {
236
236
  const db = turso.getClient();
237
237
  const opportunities = [];
238
238
  // Find high-value memories that could benefit other projects
239
- const memoriesResult = await db.execute(`
240
- SELECT
241
- id,
242
- system,
243
- json_extract(content, '$.title') as title,
244
- json_extract(content, '$.domain') as domain,
245
- json_extract(content, '$.feedbackScore') as feedbackScore,
246
- json_extract(content, '$.accessCount') as accessCount
247
- FROM items
248
- WHERE type = 'memory'
249
- AND status = 'active'
250
- AND COALESCE(json_extract(content, '$.feedbackScore'), 0.5) >= 0.7
251
- AND COALESCE(json_extract(content, '$.accessCount'), 0) >= 3
252
- ORDER BY feedbackScore DESC, accessCount DESC
253
- LIMIT 50
239
+ const memoriesResult = await db.execute(`
240
+ SELECT
241
+ id,
242
+ system,
243
+ json_extract(content, '$.title') as title,
244
+ json_extract(content, '$.domain') as domain,
245
+ json_extract(content, '$.feedbackScore') as feedbackScore,
246
+ json_extract(content, '$.accessCount') as accessCount
247
+ FROM items
248
+ WHERE type = 'memory'
249
+ AND status = 'active'
250
+ AND COALESCE(json_extract(content, '$.feedbackScore'), 0.5) >= 0.7
251
+ AND COALESCE(json_extract(content, '$.accessCount'), 0) >= 3
252
+ ORDER BY feedbackScore DESC, accessCount DESC
253
+ LIMIT 50
254
254
  `);
255
255
  // Get all active systems
256
- const systemsResult = await db.execute(`
257
- SELECT DISTINCT system FROM items WHERE status = 'active'
256
+ const systemsResult = await db.execute(`
257
+ SELECT DISTINCT system FROM items WHERE status = 'active'
258
258
  `);
259
259
  const allSystems = systemsResult.rows.map(r => r.system);
260
260
  for (const row of memoriesResult.rows) {
@@ -288,16 +288,16 @@ export class CrossProjectAnalyticsService {
288
288
  async getActivityTimeline(days = 30) {
289
289
  const db = turso.getClient();
290
290
  const result = await db.execute({
291
- sql: `
292
- SELECT
293
- DATE(created_at) as date,
294
- system,
295
- COUNT(*) as itemsCreated,
296
- SUM(CASE WHEN type = 'agent_session' THEN 1 ELSE 0 END) as sessionsStarted
297
- FROM items
298
- WHERE created_at > datetime('now', '-' || ? || ' days')
299
- GROUP BY DATE(created_at), system
300
- ORDER BY date DESC
291
+ sql: `
292
+ SELECT
293
+ DATE(created_at) as date,
294
+ system,
295
+ COUNT(*) as itemsCreated,
296
+ SUM(CASE WHEN type = 'agent_session' THEN 1 ELSE 0 END) as sessionsStarted
297
+ FROM items
298
+ WHERE created_at > datetime('now', '-' || ? || ' days')
299
+ GROUP BY DATE(created_at), system
300
+ ORDER BY date DESC
301
301
  `,
302
302
  args: [days],
303
303
  });
@@ -314,17 +314,17 @@ export class CrossProjectAnalyticsService {
314
314
  async getTopContributors(limit = 5) {
315
315
  const db = turso.getClient();
316
316
  const result = await db.execute({
317
- sql: `
318
- SELECT
319
- system,
320
- SUM(CASE WHEN type = 'memory' THEN 1 ELSE 0 END) as memoriesCreated,
321
- SUM(CASE WHEN type = 'task' AND json_extract(content, '$.status') = 'completed' THEN 1 ELSE 0 END) as tasksCompleted,
322
- SUM(CASE WHEN type = 'pattern' THEN 1 ELSE 0 END) as patternsDetected
323
- FROM items
324
- WHERE status = 'active' AND created_at > datetime('now', '-30 days')
325
- GROUP BY system
326
- ORDER BY memoriesCreated DESC
327
- LIMIT ?
317
+ sql: `
318
+ SELECT
319
+ system,
320
+ SUM(CASE WHEN type = 'memory' THEN 1 ELSE 0 END) as memoriesCreated,
321
+ SUM(CASE WHEN type = 'task' AND json_extract(content, '$.status') = 'completed' THEN 1 ELSE 0 END) as tasksCompleted,
322
+ SUM(CASE WHEN type = 'pattern' THEN 1 ELSE 0 END) as patternsDetected
323
+ FROM items
324
+ WHERE status = 'active' AND created_at > datetime('now', '-30 days')
325
+ GROUP BY system
326
+ ORDER BY memoriesCreated DESC
327
+ LIMIT ?
328
328
  `,
329
329
  args: [limit],
330
330
  });
package/dist/cli/index.js CHANGED
@@ -394,21 +394,44 @@ program
394
394
  ui.dim('Run: cmp-standards init');
395
395
  return;
396
396
  }
397
- // Check registry
398
- const registryPath = path.join(projectRoot, '.claude/knowledge/registry.json');
399
- try {
400
- const registryContent = await fs.readFile(registryPath, 'utf-8');
401
- const registry = JSON.parse(registryContent);
402
- ui.success('Registry found');
403
- ui.keyValue({
404
- 'Sections': registry.sections.length,
405
- 'Generated': registry.generatedAt || 'pending',
406
- });
397
+ // Check registry - now in .claude/cache (not knowledge)
398
+ const registryPath = path.join(projectRoot, '.claude/cache/registry.json');
399
+ const legacyRegistryPath = path.join(projectRoot, '.claude/knowledge/registry.json');
400
+ let foundRegistry = false;
401
+ for (const regPath of [registryPath, legacyRegistryPath]) {
402
+ try {
403
+ const registryContent = await fs.readFile(regPath, 'utf-8');
404
+ const registry = JSON.parse(registryContent);
405
+ ui.success('Registry found');
406
+ ui.keyValue({
407
+ 'Sections': registry.sections.length,
408
+ 'Generated': registry.generatedAt || 'pending',
409
+ });
410
+ foundRegistry = true;
411
+ break;
412
+ }
413
+ catch {
414
+ // Continue to next path
415
+ }
407
416
  }
408
- catch {
417
+ if (!foundRegistry) {
409
418
  ui.warning('No registry found');
410
419
  ui.dim('Run: cmp-standards generate');
411
420
  }
421
+ // Check for LOCAL knowledge files (VIOLATION of Cloud > Local philosophy)
422
+ const knowledgeDir = path.join(projectRoot, '.claude/knowledge');
423
+ try {
424
+ const knowledgeFiles = await fs.readdir(knowledgeDir);
425
+ const mdFiles = knowledgeFiles.filter(f => f.endsWith('.md'));
426
+ if (mdFiles.length > 0) {
427
+ console.log(chalk.red(`\n āš ļø PHILOSOPHY VIOLATION: ${mdFiles.length} local knowledge files found`));
428
+ console.log(chalk.gray(' Cloud > Local - knowledge should be in Turso, not local files'));
429
+ console.log(chalk.yellow(' Run: cmp-standards cloud push-knowledge --delete-local'));
430
+ }
431
+ }
432
+ catch {
433
+ // No knowledge directory = good (cloud-first)
434
+ }
412
435
  // Check hooks
413
436
  const hooksDir = getHooksDir(projectRoot);
414
437
  try {
@@ -1100,6 +1123,127 @@ cloudCmd
1100
1123
  }
1101
1124
  }
1102
1125
  });
1126
+ cloudCmd
1127
+ .command('push-knowledge')
1128
+ .description('Push local knowledge files to Turso cloud (Cloud > Local philosophy)')
1129
+ .option('-s, --system <system>', 'System identifier')
1130
+ .option('--delete-local', 'Delete local files after successful push')
1131
+ .option('--dry-run', 'Show what would be pushed without pushing')
1132
+ .action(async (options) => {
1133
+ const projectRoot = await getProjectRoot();
1134
+ let system = options.system;
1135
+ if (!system) {
1136
+ try {
1137
+ const config = await loadConfig(projectRoot);
1138
+ system = config.system;
1139
+ }
1140
+ catch {
1141
+ console.log(chalk.red('Error: No system specified and no config found'));
1142
+ process.exit(1);
1143
+ }
1144
+ }
1145
+ const knowledgeDir = path.join(projectRoot, '.claude/knowledge');
1146
+ const domainsDir = path.join(knowledgeDir, 'domains');
1147
+ // Check for local knowledge files
1148
+ const fsSync = await import('fs');
1149
+ const files = [];
1150
+ if (fsSync.existsSync(knowledgeDir)) {
1151
+ for (const file of fsSync.readdirSync(knowledgeDir)) {
1152
+ if (file.endsWith('.md') && !file.startsWith('.')) {
1153
+ files.push({ file: path.join(knowledgeDir, file), domain: 'general' });
1154
+ }
1155
+ }
1156
+ }
1157
+ if (fsSync.existsSync(domainsDir)) {
1158
+ for (const file of fsSync.readdirSync(domainsDir)) {
1159
+ if (file.endsWith('.md')) {
1160
+ const domain = file.replace('.md', '');
1161
+ files.push({ file: path.join(domainsDir, file), domain });
1162
+ }
1163
+ }
1164
+ }
1165
+ if (files.length === 0) {
1166
+ console.log(chalk.green('ā˜ļø No local knowledge files found - already cloud-first!'));
1167
+ return;
1168
+ }
1169
+ console.log(chalk.yellow(`\nāš ļø Found ${files.length} local knowledge files`));
1170
+ console.log(chalk.gray(' Philosophy: Cloud > Local - knowledge should be in Turso\n'));
1171
+ if (options.dryRun) {
1172
+ console.log(chalk.blue('šŸ“‹ Dry run - would push:\n'));
1173
+ for (const { file, domain } of files) {
1174
+ const content = fsSync.readFileSync(file, 'utf-8');
1175
+ const titleMatch = content.match(/^#\s+(.+)$/m);
1176
+ const title = titleMatch ? titleMatch[1] : path.basename(file, '.md');
1177
+ console.log(` → ${title} (${domain})`);
1178
+ }
1179
+ return;
1180
+ }
1181
+ // Initialize cloud
1182
+ const { cloud } = await import('../db/cloud.js');
1183
+ await cloud.init();
1184
+ let migrated = 0;
1185
+ let skipped = 0;
1186
+ for (const { file, domain } of files) {
1187
+ const content = fsSync.readFileSync(file, 'utf-8');
1188
+ const filename = path.basename(file, '.md');
1189
+ const titleMatch = content.match(/^#\s+(.+)$/m);
1190
+ const title = titleMatch ? titleMatch[1] : filename;
1191
+ const sections = content.match(/^##\s+(.+)$/gm) || [];
1192
+ const tags = sections.map(s => s.replace('## ', '').toLowerCase().replace(/\s+/g, '-'));
1193
+ let importance = 'normal';
1194
+ if (filename.includes('critical') || content.toLowerCase().includes('critical')) {
1195
+ importance = 'critical';
1196
+ }
1197
+ const knowledgeContent = {
1198
+ title,
1199
+ domain,
1200
+ body: content,
1201
+ tags: [...new Set([domain, ...tags])],
1202
+ importance,
1203
+ source: 'migration',
1204
+ createdAt: new Date().toISOString()
1205
+ };
1206
+ // Check if exists using raw client
1207
+ const client = cloud.turso.getClient();
1208
+ const existing = await client.execute({
1209
+ sql: `SELECT id FROM items WHERE system = ? AND type = 'knowledge' AND json_extract(content, '$.title') = ?`,
1210
+ args: [system, title]
1211
+ });
1212
+ if (existing.rows.length > 0) {
1213
+ console.log(chalk.gray(` ā­ļø Skipped: ${title} (already in cloud)`));
1214
+ skipped++;
1215
+ continue;
1216
+ }
1217
+ await cloud.turso.create('knowledge', system, knowledgeContent, 'active');
1218
+ console.log(chalk.green(` āœ… Pushed: ${title} (${domain})`));
1219
+ migrated++;
1220
+ }
1221
+ console.log(chalk.blue(`\nšŸ“Š Push complete:`));
1222
+ console.log(` Pushed: ${migrated}`);
1223
+ console.log(` Skipped: ${skipped}`);
1224
+ if (options.deleteLocal && migrated > 0) {
1225
+ console.log(chalk.yellow('\nšŸ—‘ļø Deleting local files (Cloud > Local)...'));
1226
+ for (const { file } of files) {
1227
+ fsSync.unlinkSync(file);
1228
+ console.log(chalk.gray(` Deleted: ${path.basename(file)}`));
1229
+ }
1230
+ // Clean up empty directories
1231
+ if (fsSync.existsSync(domainsDir) && fsSync.readdirSync(domainsDir).length === 0) {
1232
+ fsSync.rmdirSync(domainsDir);
1233
+ }
1234
+ const remaining = fsSync.readdirSync(knowledgeDir).filter(f => f.endsWith('.md'));
1235
+ if (remaining.length === 0 && fsSync.existsSync(domainsDir) === false) {
1236
+ // Only remove if truly empty (no registry.json, etc.)
1237
+ const allFiles = fsSync.readdirSync(knowledgeDir);
1238
+ if (allFiles.every(f => f === 'registry.json' || f.startsWith('.'))) {
1239
+ console.log(chalk.green('\nāœ“ Local knowledge directory cleaned'));
1240
+ }
1241
+ }
1242
+ }
1243
+ else if (migrated > 0 && !options.deleteLocal) {
1244
+ console.log(chalk.yellow('\nšŸ’” Tip: Run with --delete-local to remove local files after push'));
1245
+ }
1246
+ });
1103
1247
  // =============================================================================
1104
1248
  // QUICKSTART WIZARD
1105
1249
  // =============================================================================
@@ -1966,6 +2110,104 @@ wikiCmd
1966
2110
  }
1967
2111
  });
1968
2112
  // =============================================================================
2113
+ // BOOTSTRAP COMMAND
2114
+ // =============================================================================
2115
+ program
2116
+ .command('bootstrap')
2117
+ .description('Full project bootstrap: scaffold → index → docs → sync → gaps')
2118
+ .requiredOption('-s, --system <system>', 'System identifier (PANEL, SWARMSCALE, etc.)')
2119
+ .option('-n, --name <name>', 'Project name')
2120
+ .option('-f, --force', 'Overwrite existing files')
2121
+ .option('--phases <phases>', 'Phases to run (comma-separated: scan,scaffold,index,docs,sync,gaps)', 'scan,scaffold,index,docs,sync,gaps')
2122
+ .option('--depth <depth>', 'Index depth: quick, standard, thorough', 'standard')
2123
+ .option('--skip-agents', 'Skip installing standard agents')
2124
+ .option('--skip-hooks', 'Skip installing hooks')
2125
+ .option('--skip-commands', 'Skip installing commands')
2126
+ .option('-v, --verbose', 'Show detailed progress')
2127
+ .action(async (options) => {
2128
+ const { BootstrapService } = await import('../services/BootstrapService.js');
2129
+ const projectRoot = await getProjectRoot();
2130
+ const bootstrap = new BootstrapService(projectRoot);
2131
+ const phases = options.phases.split(',').map((p) => p.trim());
2132
+ await bootstrap.run({
2133
+ system: options.system.toUpperCase(),
2134
+ projectName: options.name,
2135
+ phases,
2136
+ force: options.force,
2137
+ skipAgents: options.skipAgents,
2138
+ skipHooks: options.skipHooks,
2139
+ skipCommands: options.skipCommands,
2140
+ indexDepth: options.depth,
2141
+ verbose: options.verbose,
2142
+ });
2143
+ });
2144
+ // =============================================================================
2145
+ // GAPS COMMAND
2146
+ // =============================================================================
2147
+ program
2148
+ .command('gaps')
2149
+ .description('Analyze knowledge gaps in the project')
2150
+ .requiredOption('-s, --system <system>', 'System identifier (PANEL, SWARMSCALE, etc.)')
2151
+ .option('--json', 'Output as JSON')
2152
+ .action(async (options) => {
2153
+ const { KnowledgeGapDetector } = await import('../services/KnowledgeGapDetector.js');
2154
+ const projectRoot = await getProjectRoot();
2155
+ console.log(chalk.cyan('\nšŸ”Ž Analyzing Knowledge Gaps\n'));
2156
+ const detector = new KnowledgeGapDetector(options.system.toUpperCase(), projectRoot);
2157
+ const analysis = await detector.analyze();
2158
+ if (options.json) {
2159
+ console.log(JSON.stringify(analysis, null, 2));
2160
+ return;
2161
+ }
2162
+ // Summary
2163
+ console.log(chalk.white(' Coverage Scores:'));
2164
+ console.log(` Structure: ${analysis.coverage.structureCoverage}%`);
2165
+ console.log(` Patterns: ${analysis.coverage.patternCoverage}%`);
2166
+ console.log(` Integrations: ${analysis.coverage.integrationCoverage}%`);
2167
+ console.log(chalk.cyan(` Overall: ${analysis.coverage.overallScore}%`));
2168
+ console.log();
2169
+ // Gaps by severity
2170
+ const bySeverity = {
2171
+ critical: analysis.gaps.filter(g => g.severity === 'critical'),
2172
+ high: analysis.gaps.filter(g => g.severity === 'high'),
2173
+ medium: analysis.gaps.filter(g => g.severity === 'medium'),
2174
+ low: analysis.gaps.filter(g => g.severity === 'low'),
2175
+ };
2176
+ if (bySeverity.critical.length > 0) {
2177
+ console.log(chalk.red(` šŸ”“ Critical (${bySeverity.critical.length}):`));
2178
+ for (const gap of bySeverity.critical) {
2179
+ console.log(chalk.red(` • ${gap.title}`));
2180
+ console.log(chalk.gray(` ${gap.suggestedAction}`));
2181
+ }
2182
+ console.log();
2183
+ }
2184
+ if (bySeverity.high.length > 0) {
2185
+ console.log(chalk.yellow(` 🟠 High (${bySeverity.high.length}):`));
2186
+ for (const gap of bySeverity.high) {
2187
+ console.log(chalk.yellow(` • ${gap.title}`));
2188
+ }
2189
+ console.log();
2190
+ }
2191
+ if (bySeverity.medium.length > 0) {
2192
+ console.log(chalk.blue(` šŸ”µ Medium (${bySeverity.medium.length}):`));
2193
+ for (const gap of bySeverity.medium.slice(0, 5)) {
2194
+ console.log(chalk.blue(` • ${gap.title}`));
2195
+ }
2196
+ if (bySeverity.medium.length > 5) {
2197
+ console.log(chalk.dim(` ... and ${bySeverity.medium.length - 5} more`));
2198
+ }
2199
+ console.log();
2200
+ }
2201
+ // Recommendations
2202
+ if (analysis.recommendations.length > 0) {
2203
+ console.log(chalk.white(' Recommendations:'));
2204
+ for (const rec of analysis.recommendations) {
2205
+ console.log(chalk.dim(` ${rec}`));
2206
+ }
2207
+ }
2208
+ console.log();
2209
+ });
2210
+ // =============================================================================
1969
2211
  // COMPLETION COMMAND
1970
2212
  // =============================================================================
1971
2213
  program
@@ -1977,7 +2219,8 @@ program
1977
2219
  'init', 'sync', 'validate', 'verify-hooks', 'generate', 'scan', 'improve',
1978
2220
  'status', 'dashboard', 'mcp', 'analytics', 'cross-analytics', 'feedback',
1979
2221
  'tasks', 'ideas', 'improvements', 'plan', 'capture', 'export',
1980
- 'cloud', 'quickstart', 'doctor', 'opportunities', 'completion'
2222
+ 'cloud', 'quickstart', 'doctor', 'opportunities', 'wiki',
2223
+ 'bootstrap', 'gaps', 'completion'
1981
2224
  ];
1982
2225
  const subcommands = {
1983
2226
  cloud: ['status', 'init', 'improvements', 'tasks', 'session']