@girardmedia/bootspring 2.0.21 → 2.0.22

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 (147) hide show
  1. package/cli/preseed/index.js +16 -0
  2. package/cli/preseed/interactive.js +143 -0
  3. package/cli/preseed/templates.js +227 -0
  4. package/cli/seed/builders/ai-context-builder.js +85 -0
  5. package/cli/seed/builders/index.js +13 -0
  6. package/cli/seed/builders/seed-builder.js +272 -0
  7. package/cli/seed/extractors/content-extractors.js +383 -0
  8. package/cli/seed/extractors/index.js +47 -0
  9. package/cli/seed/extractors/metadata-extractors.js +167 -0
  10. package/cli/seed/extractors/section-extractor.js +54 -0
  11. package/cli/seed/extractors/stack-extractors.js +228 -0
  12. package/cli/seed/index.js +18 -0
  13. package/cli/seed/utils/folder-structure.js +84 -0
  14. package/cli/seed/utils/index.js +11 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.js +3220 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/context-McpJQa_2.d.ts +5710 -0
  19. package/dist/core/index.d.ts +635 -0
  20. package/dist/core/index.js +2593 -0
  21. package/dist/core/index.js.map +1 -0
  22. package/dist/index-QqbeEiDm.d.ts +857 -0
  23. package/dist/index-UiYCgwiH.d.ts +174 -0
  24. package/dist/index.d.ts +453 -0
  25. package/dist/index.js +44228 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/mcp/index.d.ts +1 -0
  28. package/dist/mcp/index.js +41173 -0
  29. package/dist/mcp/index.js.map +1 -0
  30. package/generators/index.ts +82 -0
  31. package/intelligence/orchestrator/config/failure-signatures.js +48 -0
  32. package/intelligence/orchestrator/config/index.js +20 -0
  33. package/intelligence/orchestrator/config/phases.js +111 -0
  34. package/intelligence/orchestrator/config/remediation.js +150 -0
  35. package/intelligence/orchestrator/config/workflows.js +168 -0
  36. package/intelligence/orchestrator/core/index.js +16 -0
  37. package/intelligence/orchestrator/core/state-manager.js +88 -0
  38. package/intelligence/orchestrator/core/telemetry.js +24 -0
  39. package/intelligence/orchestrator/index.js +17 -0
  40. package/mcp/contracts/mcp-contract.v1.json +1 -1
  41. package/package.json +16 -3
  42. package/src/cli/agent.ts +703 -0
  43. package/src/cli/analyze.ts +640 -0
  44. package/src/cli/audit.ts +707 -0
  45. package/src/cli/auth.ts +930 -0
  46. package/src/cli/billing.ts +364 -0
  47. package/src/cli/build.ts +1089 -0
  48. package/src/cli/business.ts +508 -0
  49. package/src/cli/checkpoint-utils.ts +236 -0
  50. package/src/cli/checkpoint.ts +757 -0
  51. package/src/cli/cloud-sync.ts +534 -0
  52. package/src/cli/content.ts +273 -0
  53. package/src/cli/context.ts +667 -0
  54. package/src/cli/dashboard.ts +133 -0
  55. package/src/cli/deploy.ts +704 -0
  56. package/src/cli/doctor.ts +480 -0
  57. package/src/cli/fundraise.ts +494 -0
  58. package/src/cli/generate.ts +346 -0
  59. package/src/cli/github-cmd.ts +566 -0
  60. package/src/cli/health.ts +599 -0
  61. package/src/cli/index.ts +113 -0
  62. package/src/cli/init.ts +838 -0
  63. package/src/cli/legal.ts +495 -0
  64. package/src/cli/log.ts +316 -0
  65. package/src/cli/loop.ts +1660 -0
  66. package/src/cli/manager.ts +878 -0
  67. package/src/cli/mcp.ts +275 -0
  68. package/src/cli/memory.ts +346 -0
  69. package/src/cli/metrics.ts +590 -0
  70. package/src/cli/monitor.ts +960 -0
  71. package/src/cli/mvp.ts +662 -0
  72. package/src/cli/onboard.ts +663 -0
  73. package/src/cli/orchestrator.ts +622 -0
  74. package/src/cli/plugin.ts +483 -0
  75. package/src/cli/prd.ts +671 -0
  76. package/src/cli/preseed-start.ts +1633 -0
  77. package/src/cli/preseed.ts +2434 -0
  78. package/src/cli/project.ts +526 -0
  79. package/src/cli/quality.ts +885 -0
  80. package/src/cli/security.ts +1079 -0
  81. package/src/cli/seed.ts +1224 -0
  82. package/src/cli/skill.ts +537 -0
  83. package/src/cli/suggest.ts +1225 -0
  84. package/src/cli/switch.ts +518 -0
  85. package/src/cli/task.ts +780 -0
  86. package/src/cli/telemetry.ts +172 -0
  87. package/src/cli/todo.ts +627 -0
  88. package/src/cli/types.ts +15 -0
  89. package/src/cli/update.ts +334 -0
  90. package/src/cli/visualize.ts +609 -0
  91. package/src/cli/watch.ts +895 -0
  92. package/src/cli/workspace.ts +709 -0
  93. package/src/core/action-recorder.ts +673 -0
  94. package/src/core/analyze-workflow.ts +1453 -0
  95. package/src/core/api-client.ts +1120 -0
  96. package/src/core/audit-workflow.ts +1681 -0
  97. package/src/core/auth.ts +471 -0
  98. package/src/core/build-orchestrator.ts +509 -0
  99. package/src/core/build-state.ts +621 -0
  100. package/src/core/checkpoint-engine.ts +482 -0
  101. package/src/core/config.ts +1285 -0
  102. package/src/core/context-loader.ts +694 -0
  103. package/src/core/context.ts +410 -0
  104. package/src/core/deploy-workflow.ts +1085 -0
  105. package/src/core/entitlements.ts +322 -0
  106. package/src/core/github-sync.ts +720 -0
  107. package/src/core/index.ts +981 -0
  108. package/src/core/ingest.ts +1186 -0
  109. package/src/core/metrics-engine.ts +886 -0
  110. package/src/core/mvp.ts +847 -0
  111. package/src/core/onboard-workflow.ts +1293 -0
  112. package/src/core/policies.ts +81 -0
  113. package/src/core/preseed-workflow.ts +1163 -0
  114. package/src/core/preseed.ts +1826 -0
  115. package/src/core/project-context.ts +380 -0
  116. package/src/core/project-state.ts +699 -0
  117. package/src/core/r2-sync.ts +691 -0
  118. package/src/core/scaffold.ts +1715 -0
  119. package/src/core/session.ts +286 -0
  120. package/src/core/task-extractor.ts +799 -0
  121. package/src/core/telemetry.ts +371 -0
  122. package/src/core/tier-enforcement.ts +737 -0
  123. package/src/core/utils.ts +437 -0
  124. package/src/index.ts +29 -0
  125. package/src/intelligence/agent-collab.ts +2376 -0
  126. package/src/intelligence/auto-suggest.ts +713 -0
  127. package/src/intelligence/content-gen.ts +1351 -0
  128. package/src/intelligence/cross-project.ts +1692 -0
  129. package/src/intelligence/git-memory.ts +529 -0
  130. package/src/intelligence/index.ts +318 -0
  131. package/src/intelligence/orchestrator.ts +534 -0
  132. package/src/intelligence/prd.ts +466 -0
  133. package/src/intelligence/recommendations.ts +982 -0
  134. package/src/intelligence/workflow-composer.ts +1472 -0
  135. package/src/mcp/capabilities.ts +233 -0
  136. package/src/mcp/index.ts +37 -0
  137. package/src/mcp/registry.ts +1268 -0
  138. package/src/mcp/response-formatter.ts +797 -0
  139. package/src/mcp/server.ts +240 -0
  140. package/src/types/agent.ts +69 -0
  141. package/src/types/config.ts +86 -0
  142. package/src/types/context.ts +77 -0
  143. package/src/types/index.ts +53 -0
  144. package/src/types/mcp.ts +91 -0
  145. package/src/types/skills.ts +47 -0
  146. package/src/types/workflow.ts +155 -0
  147. package/generators/index.js +0 -18
@@ -0,0 +1,640 @@
1
+ /**
2
+ * Bootspring Analyze CLI
3
+ *
4
+ * Deep codebase analysis for understanding architecture,
5
+ * dependencies, patterns, and code flows.
6
+ *
7
+ * @package bootspring
8
+ * @module cli/analyze
9
+ */
10
+
11
+ // Import JS modules with type interfaces
12
+ interface ParsedArgs {
13
+ _: string[];
14
+ depth?: string | undefined;
15
+ phase?: string | undefined;
16
+ include?: string | undefined;
17
+ exclude?: string | undefined;
18
+ }
19
+
20
+ interface AnalysisDepthConfig {
21
+ description: string;
22
+ }
23
+
24
+ interface PhaseConfig {
25
+ name: string;
26
+ description: string;
27
+ required: boolean;
28
+ }
29
+
30
+ interface StructureResult {
31
+ totalFiles: number;
32
+ totalDirs: number;
33
+ structureType?: { pattern: string } | undefined;
34
+ keyDirectories: string[];
35
+ entryPoints: number;
36
+ }
37
+
38
+ interface ArchitectureResult {
39
+ patterns: Array<{ name: string; confidence: number }>;
40
+ layers: string[];
41
+ modules: number;
42
+ }
43
+
44
+ interface DependencyResult {
45
+ skipped?: boolean | undefined;
46
+ fileCount: number;
47
+ circularCount: number;
48
+ unusedCount: number;
49
+ externalPackages: number;
50
+ mostImported: Array<{ file: string; importCount: number }>;
51
+ }
52
+
53
+ interface PatternResult {
54
+ designPatterns: number;
55
+ antiPatterns: number;
56
+ }
57
+
58
+ interface FlowResult {
59
+ entryPoints: number;
60
+ apiEndpoints: number;
61
+ }
62
+
63
+ interface ComponentResult {
64
+ total: number;
65
+ }
66
+
67
+ interface ReportResult {
68
+ reportPath: string;
69
+ }
70
+
71
+ interface OverallProgress {
72
+ completed: number;
73
+ total: number;
74
+ percentage: number;
75
+ }
76
+
77
+ interface PhaseProgress {
78
+ name: string;
79
+ status: string;
80
+ required: boolean;
81
+ }
82
+
83
+ interface WorkflowProgress {
84
+ overall: OverallProgress;
85
+ isComplete: boolean;
86
+ currentPhase?: string | undefined;
87
+ depth: string;
88
+ phases: PhaseProgress[];
89
+ startedAt?: string | undefined;
90
+ lastUpdated?: string | undefined;
91
+ summary?: {
92
+ reportPath?: string | undefined;
93
+ } | undefined;
94
+ }
95
+
96
+ interface ResumePoint {
97
+ phaseName: string;
98
+ }
99
+
100
+ interface AnalyzeWorkflowEngineClass {
101
+ new (projectRoot: string, options?: { depth?: string | undefined }): AnalyzeWorkflowEngine;
102
+ }
103
+
104
+ interface AnalyzeWorkflowEngine {
105
+ hasWorkflow(): boolean;
106
+ loadState(): void;
107
+ initializeWorkflow(depth: string): void;
108
+ getProgress(): WorkflowProgress;
109
+ getResumePoint(): ResumePoint | null;
110
+ getNextPhase(): string | null;
111
+ startPhase(phaseId: string): void;
112
+ completePhase(phaseId: string, result: unknown): void;
113
+ failPhase(phaseId: string, error: string): void;
114
+ skipPhase(phaseId: string): void;
115
+ resetWorkflow(): void;
116
+ runStructureMapping(): Promise<StructureResult>;
117
+ runArchitectureAnalysis(): Promise<ArchitectureResult>;
118
+ runDependencyAnalysis(): Promise<DependencyResult>;
119
+ runPatternDetection(): Promise<PatternResult>;
120
+ runFlowTracing(): Promise<FlowResult>;
121
+ runComponentAnalysis(): Promise<ComponentResult>;
122
+ runReportGeneration(): Promise<ReportResult>;
123
+ }
124
+
125
+ interface AnalyzeWorkflowModule {
126
+ AnalyzeWorkflowEngine: AnalyzeWorkflowEngineClass;
127
+ ANALYZE_PHASES: Record<string, PhaseConfig>;
128
+ ANALYSIS_DEPTH: Record<string, AnalysisDepthConfig>;
129
+ }
130
+
131
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
132
+ const utils = require('../../core/utils') as typeof import('../core/utils');
133
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
134
+ const analyzeWorkflowModule = require('../../core/analyze-workflow') as AnalyzeWorkflowModule;
135
+
136
+ const { AnalyzeWorkflowEngine, ANALYZE_PHASES, ANALYSIS_DEPTH } = analyzeWorkflowModule;
137
+
138
+ // Get project root
139
+ const projectRoot = process.cwd();
140
+
141
+ /**
142
+ * Show analyze help
143
+ */
144
+ function showHelp(): void {
145
+ console.log(`
146
+ ${utils.COLORS.bold}Bootspring Analyze${utils.COLORS.reset}
147
+ Deep codebase analysis for understanding
148
+
149
+ ${utils.COLORS.bold}Usage:${utils.COLORS.reset}
150
+ bootspring analyze Full analysis
151
+ bootspring analyze status Show progress
152
+ bootspring analyze resume Continue from checkpoint
153
+ bootspring analyze reset Reset workflow
154
+
155
+ ${utils.COLORS.bold}Options:${utils.COLORS.reset}
156
+ --depth=<level> Analysis depth: shallow, standard, deep
157
+ --phase=<phase> Run specific phase only
158
+ --include=<glob> Include pattern (e.g., "src/**")
159
+ --exclude=<glob> Exclude pattern
160
+
161
+ ${utils.COLORS.bold}Depth Levels:${utils.COLORS.reset}
162
+ shallow Quick scan - structure and architecture only
163
+ standard Standard analysis with patterns and dependencies
164
+ deep Comprehensive with flow tracing and components
165
+
166
+ ${utils.COLORS.bold}Notes:${utils.COLORS.reset}
167
+ Large codebases (500+ files) automatically skip heavy dependency
168
+ analysis for performance. Use --depth=deep to force full analysis.
169
+
170
+ ${utils.COLORS.bold}Examples:${utils.COLORS.reset}
171
+ bootspring analyze Auto-adjusts for codebase size
172
+ bootspring analyze --depth=shallow
173
+ bootspring analyze --depth=deep
174
+ bootspring analyze status
175
+ `);
176
+ }
177
+
178
+ /**
179
+ * Start analysis workflow
180
+ */
181
+ async function analyzeStart(args: ParsedArgs): Promise<void> {
182
+ const depth = args.depth || 'standard';
183
+
184
+ if (!ANALYSIS_DEPTH[depth]) {
185
+ utils.print.error(`Unknown depth level: ${depth}`);
186
+ utils.print.info('Valid options: shallow, standard, deep');
187
+ return;
188
+ }
189
+
190
+ const workflow = new AnalyzeWorkflowEngine(projectRoot, { depth });
191
+
192
+ // Check for existing workflow
193
+ if (workflow.hasWorkflow()) {
194
+ workflow.loadState();
195
+ const progress = workflow.getProgress();
196
+
197
+ if (!progress.isComplete) {
198
+ utils.print.info('Existing analysis workflow found.');
199
+ console.log(` Progress: ${progress.overall.percentage}% complete`);
200
+ console.log(` Current phase: ${progress.currentPhase || 'none'}`);
201
+ console.log('');
202
+ utils.print.info('Use "bootspring analyze resume" to continue');
203
+ utils.print.info('Use "bootspring analyze reset" to start fresh');
204
+ return;
205
+ }
206
+ }
207
+
208
+ // Initialize new workflow
209
+ utils.print.header('Codebase Analysis');
210
+ const depthConfig = ANALYSIS_DEPTH[depth];
211
+ console.log(`Analysis depth: ${depth} (${depthConfig?.description || 'unknown'})`);
212
+ console.log('');
213
+
214
+ workflow.initializeWorkflow(depth);
215
+
216
+ // Run workflow
217
+ await runWorkflowLoop(workflow);
218
+ }
219
+
220
+ /**
221
+ * Resume analysis workflow
222
+ */
223
+ async function analyzeResume(): Promise<void> {
224
+ const workflow = new AnalyzeWorkflowEngine(projectRoot);
225
+
226
+ if (!workflow.hasWorkflow()) {
227
+ utils.print.error('No existing workflow found.');
228
+ utils.print.info('Run "bootspring analyze" to start.');
229
+ return;
230
+ }
231
+
232
+ workflow.loadState();
233
+ const resumePoint = workflow.getResumePoint();
234
+
235
+ if (!resumePoint) {
236
+ utils.print.success('Analysis workflow already complete!');
237
+ displayCompletionSummary(workflow);
238
+ return;
239
+ }
240
+
241
+ utils.print.header('Resuming Analysis');
242
+ console.log(`Continuing from: ${resumePoint.phaseName}`);
243
+ console.log('');
244
+
245
+ await runWorkflowLoop(workflow);
246
+ }
247
+
248
+ /**
249
+ * Run the workflow loop
250
+ */
251
+ async function runWorkflowLoop(workflow: AnalyzeWorkflowEngine): Promise<void> {
252
+ while (true) {
253
+ const nextPhaseId = workflow.getNextPhase();
254
+
255
+ if (!nextPhaseId) {
256
+ // Workflow complete
257
+ break;
258
+ }
259
+
260
+ const phase = ANALYZE_PHASES[nextPhaseId];
261
+ if (!phase) {
262
+ continue;
263
+ }
264
+
265
+ // Run the phase
266
+ workflow.startPhase(nextPhaseId);
267
+ const spinner = utils.createSpinner(`Running: ${phase.name}`).start();
268
+
269
+ try {
270
+ let result: unknown;
271
+
272
+ switch (nextPhaseId) {
273
+ case 'structure': {
274
+ const structureResult = await workflow.runStructureMapping();
275
+ spinner.succeed(`Structure mapped: ${structureResult.totalFiles} files, ${structureResult.totalDirs} directories`);
276
+ displayStructureResults(structureResult);
277
+ result = structureResult;
278
+ break;
279
+ }
280
+
281
+ case 'architecture': {
282
+ const archResult = await workflow.runArchitectureAnalysis();
283
+ spinner.succeed(`Architecture analyzed: ${archResult.patterns.length} patterns found`);
284
+ displayArchitectureResults(archResult);
285
+ result = archResult;
286
+ break;
287
+ }
288
+
289
+ case 'dependencies': {
290
+ const depResult = await workflow.runDependencyAnalysis();
291
+ if (depResult.skipped) {
292
+ spinner.succeed(`Dependencies skipped: Large codebase (${depResult.fileCount} files)`);
293
+ console.log('');
294
+ console.log(` ${utils.COLORS.dim}Use --depth=deep to force full analysis${utils.COLORS.reset}`);
295
+ } else {
296
+ spinner.succeed(`Dependencies analyzed: ${depResult.fileCount} files`);
297
+ displayDependencyResults(depResult);
298
+ }
299
+ result = depResult;
300
+ break;
301
+ }
302
+
303
+ case 'patterns': {
304
+ const patternResult = await workflow.runPatternDetection();
305
+ spinner.succeed('Pattern detection complete');
306
+ displayPatternResults(patternResult);
307
+ result = patternResult;
308
+ break;
309
+ }
310
+
311
+ case 'flows': {
312
+ const flowResult = await workflow.runFlowTracing();
313
+ spinner.succeed(`Flow tracing complete: ${flowResult.entryPoints} entry points, ${flowResult.apiEndpoints} API endpoints`);
314
+ result = flowResult;
315
+ break;
316
+ }
317
+
318
+ case 'components': {
319
+ const componentResult = await workflow.runComponentAnalysis();
320
+ spinner.succeed(`Component analysis complete: ${componentResult.total} components`);
321
+ result = componentResult;
322
+ break;
323
+ }
324
+
325
+ case 'report': {
326
+ const reportResult = await workflow.runReportGeneration();
327
+ spinner.succeed('Report generated');
328
+ displayReportResults(reportResult);
329
+ result = reportResult;
330
+ break;
331
+ }
332
+
333
+ default:
334
+ spinner.warn(`Unknown phase: ${nextPhaseId}`);
335
+ continue;
336
+ }
337
+
338
+ workflow.completePhase(nextPhaseId, result);
339
+
340
+ } catch (error) {
341
+ spinner.fail(`Failed: ${(error as Error).message}`);
342
+ workflow.failPhase(nextPhaseId, (error as Error).message);
343
+
344
+ if (phase.required) {
345
+ utils.print.error('Required phase failed. Cannot continue.');
346
+ return;
347
+ }
348
+ }
349
+
350
+ console.log('');
351
+ }
352
+
353
+ // Workflow complete
354
+ displayCompletionSummary(workflow);
355
+ }
356
+
357
+ /**
358
+ * Display structure results
359
+ */
360
+ function displayStructureResults(result: StructureResult): void {
361
+ console.log('');
362
+ console.log(` ${utils.COLORS.cyan}Structure:${utils.COLORS.reset} ${result.structureType?.pattern || 'flat'}`);
363
+
364
+ if (result.keyDirectories.length > 0) {
365
+ console.log(` ${utils.COLORS.cyan}Key dirs:${utils.COLORS.reset} ${result.keyDirectories.slice(0, 5).join(', ')}`);
366
+ }
367
+
368
+ if (result.entryPoints > 0) {
369
+ console.log(` ${utils.COLORS.cyan}Entry points:${utils.COLORS.reset} ${result.entryPoints}`);
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Display architecture results
375
+ */
376
+ function displayArchitectureResults(result: ArchitectureResult): void {
377
+ if (result.patterns.length > 0) {
378
+ console.log('');
379
+ console.log(' Detected patterns:');
380
+ for (const pattern of result.patterns.slice(0, 3)) {
381
+ console.log(` - ${pattern.name} (${pattern.confidence}%)`);
382
+ }
383
+ }
384
+
385
+ if (result.layers.length > 0) {
386
+ console.log('');
387
+ console.log(` ${utils.COLORS.cyan}Layers:${utils.COLORS.reset} ${result.layers.join(', ')}`);
388
+ }
389
+
390
+ if (result.modules > 0) {
391
+ console.log(` ${utils.COLORS.cyan}Modules:${utils.COLORS.reset} ${result.modules}`);
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Display dependency results
397
+ */
398
+ function displayDependencyResults(result: DependencyResult): void {
399
+ console.log('');
400
+
401
+ if (result.circularCount > 0) {
402
+ console.log(` ${utils.COLORS.yellow}⚠${utils.COLORS.reset} Circular dependencies: ${result.circularCount}`);
403
+ } else {
404
+ console.log(` ${utils.COLORS.green}✓${utils.COLORS.reset} No circular dependencies`);
405
+ }
406
+
407
+ if (result.unusedCount > 0) {
408
+ console.log(` ${utils.COLORS.yellow}○${utils.COLORS.reset} Potentially unused packages: ${result.unusedCount}`);
409
+ }
410
+
411
+ console.log(` ${utils.COLORS.cyan}External packages:${utils.COLORS.reset} ${result.externalPackages}`);
412
+
413
+ if (result.mostImported.length > 0) {
414
+ console.log('');
415
+ console.log(' Most imported files:');
416
+ for (const file of result.mostImported.slice(0, 3)) {
417
+ console.log(` - ${file.file} (${file.importCount} imports)`);
418
+ }
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Display pattern results
424
+ */
425
+ function displayPatternResults(result: PatternResult): void {
426
+ console.log('');
427
+ console.log(` ${utils.COLORS.cyan}Design patterns:${utils.COLORS.reset} ${result.designPatterns}`);
428
+ console.log(` ${utils.COLORS.cyan}Anti-patterns:${utils.COLORS.reset} ${result.antiPatterns}`);
429
+ }
430
+
431
+ /**
432
+ * Display report results
433
+ */
434
+ function displayReportResults(result: ReportResult): void {
435
+ console.log('');
436
+ utils.print.success(`Report saved to: ${result.reportPath}`);
437
+ }
438
+
439
+ /**
440
+ * Display completion summary
441
+ */
442
+ function displayCompletionSummary(workflow: AnalyzeWorkflowEngine): void {
443
+ const progress = workflow.getProgress();
444
+
445
+ console.log('');
446
+ utils.print.success('Analysis complete!');
447
+ console.log('');
448
+
449
+ // Show summary
450
+ utils.print.header('Summary');
451
+ console.log(` Phases completed: ${progress.overall.completed}/${progress.overall.total}`);
452
+ console.log(` Depth: ${progress.depth}`);
453
+
454
+ if (progress.summary?.reportPath) {
455
+ console.log('');
456
+ console.log(' Reports generated:');
457
+ console.log(` ${utils.COLORS.green}✓${utils.COLORS.reset} ${progress.summary.reportPath}`);
458
+ console.log(` ${utils.COLORS.green}✓${utils.COLORS.reset} .bootspring/analyze/reports/architecture.md`);
459
+ console.log(` ${utils.COLORS.green}✓${utils.COLORS.reset} .bootspring/analyze/reports/dependencies.md`);
460
+ }
461
+
462
+ console.log('');
463
+ utils.print.info('Next steps:');
464
+ console.log(' 1. Review the analysis report');
465
+ console.log(' 2. Run "bootspring audit" for quality & security checks');
466
+ }
467
+
468
+ /**
469
+ * Show analysis status
470
+ */
471
+ async function analyzeStatus(): Promise<void> {
472
+ const workflow = new AnalyzeWorkflowEngine(projectRoot);
473
+
474
+ if (!workflow.hasWorkflow()) {
475
+ utils.print.info('No analysis workflow started.');
476
+ utils.print.info('Run "bootspring analyze" to begin.');
477
+ return;
478
+ }
479
+
480
+ workflow.loadState();
481
+ const progress = workflow.getProgress();
482
+
483
+ utils.print.header('Analysis Status');
484
+
485
+ // Overall progress
486
+ console.log(`Progress: ${progress.overall.percentage}% complete`);
487
+ console.log(`Depth: ${progress.depth}`);
488
+ console.log(`Started: ${progress.startedAt ? new Date(progress.startedAt).toLocaleString() : 'N/A'}`);
489
+ console.log(`Last updated: ${progress.lastUpdated ? utils.formatRelativeTime(new Date(progress.lastUpdated)) : 'N/A'}`);
490
+ console.log('');
491
+
492
+ // Phase status
493
+ console.log('Phases:');
494
+ for (const phase of progress.phases) {
495
+ const statusIcon = getStatusIcon(phase.status);
496
+ const required = phase.required ? '' : ' (optional)';
497
+ console.log(` ${statusIcon} ${phase.name}${required}`);
498
+ }
499
+
500
+ if (progress.summary?.reportPath) {
501
+ console.log('');
502
+ console.log(`Report: ${progress.summary.reportPath}`);
503
+ }
504
+
505
+ if (!progress.isComplete) {
506
+ console.log('');
507
+ utils.print.info('Run "bootspring analyze resume" to continue');
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Run specific phase
513
+ */
514
+ async function analyzePhase(args: ParsedArgs): Promise<void> {
515
+ const phaseId = args.phase;
516
+
517
+ if (!phaseId || !ANALYZE_PHASES[phaseId]) {
518
+ utils.print.error(`Unknown phase: ${phaseId}`);
519
+ console.log('');
520
+ console.log('Available phases:');
521
+ for (const [id, phase] of Object.entries(ANALYZE_PHASES)) {
522
+ console.log(` ${id}: ${phase.description}`);
523
+ }
524
+ return;
525
+ }
526
+
527
+ const workflow = new AnalyzeWorkflowEngine(projectRoot);
528
+
529
+ if (!workflow.hasWorkflow()) {
530
+ workflow.initializeWorkflow('standard');
531
+ } else {
532
+ workflow.loadState();
533
+ }
534
+
535
+ const phase = ANALYZE_PHASES[phaseId];
536
+ if (!phase) return;
537
+
538
+ const spinner = utils.createSpinner(`Running: ${phase.name}`).start();
539
+
540
+ try {
541
+ let result: unknown;
542
+
543
+ switch (phaseId) {
544
+ case 'structure':
545
+ result = await workflow.runStructureMapping();
546
+ break;
547
+ case 'architecture':
548
+ result = await workflow.runArchitectureAnalysis();
549
+ break;
550
+ case 'dependencies':
551
+ result = await workflow.runDependencyAnalysis();
552
+ break;
553
+ case 'patterns':
554
+ result = await workflow.runPatternDetection();
555
+ break;
556
+ case 'flows':
557
+ result = await workflow.runFlowTracing();
558
+ break;
559
+ case 'components':
560
+ result = await workflow.runComponentAnalysis();
561
+ break;
562
+ case 'report':
563
+ result = await workflow.runReportGeneration();
564
+ break;
565
+ }
566
+
567
+ spinner.succeed(`${phase.name} complete`);
568
+ console.log('');
569
+ console.log('Result:', JSON.stringify(result, null, 2));
570
+
571
+ } catch (error) {
572
+ spinner.fail(`Failed: ${(error as Error).message}`);
573
+ }
574
+ }
575
+
576
+ /**
577
+ * Reset analysis workflow
578
+ */
579
+ async function analyzeReset(): Promise<void> {
580
+ const workflow = new AnalyzeWorkflowEngine(projectRoot);
581
+
582
+ if (!workflow.hasWorkflow()) {
583
+ utils.print.info('No workflow to reset.');
584
+ return;
585
+ }
586
+
587
+ workflow.resetWorkflow();
588
+ utils.print.success('Analysis workflow reset.');
589
+ }
590
+
591
+ /**
592
+ * Get status icon
593
+ */
594
+ function getStatusIcon(status: string): string {
595
+ switch (status) {
596
+ case 'completed':
597
+ return `${utils.COLORS.green}✓${utils.COLORS.reset}`;
598
+ case 'in_progress':
599
+ return `${utils.COLORS.cyan}●${utils.COLORS.reset}`;
600
+ case 'failed':
601
+ return `${utils.COLORS.red}✗${utils.COLORS.reset}`;
602
+ case 'skipped':
603
+ return `${utils.COLORS.dim}○${utils.COLORS.reset}`;
604
+ default:
605
+ return `${utils.COLORS.dim}○${utils.COLORS.reset}`;
606
+ }
607
+ }
608
+
609
+ /**
610
+ * Main entry point
611
+ */
612
+ export async function run(args: string[]): Promise<void> {
613
+ const parsedArgs = utils.parseArgs(args) as ParsedArgs;
614
+ const subcommand = parsedArgs._[0];
615
+
616
+ // Handle --phase flag
617
+ if (parsedArgs.phase) {
618
+ return analyzePhase(parsedArgs);
619
+ }
620
+
621
+ switch (subcommand) {
622
+ case 'status':
623
+ return analyzeStatus();
624
+
625
+ case 'resume':
626
+ return analyzeResume();
627
+
628
+ case 'reset':
629
+ return analyzeReset();
630
+
631
+ case 'help':
632
+ case '--help':
633
+ case '-h':
634
+ return showHelp();
635
+
636
+ default:
637
+ // Start analysis
638
+ return analyzeStart(parsedArgs);
639
+ }
640
+ }