spec-gen-cli 1.0.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/LICENSE +21 -0
- package/README.md +1078 -0
- package/dist/api/analyze.d.ts +17 -0
- package/dist/api/analyze.d.ts.map +1 -0
- package/dist/api/analyze.js +109 -0
- package/dist/api/analyze.js.map +1 -0
- package/dist/api/drift.d.ts +21 -0
- package/dist/api/drift.d.ts.map +1 -0
- package/dist/api/drift.js +145 -0
- package/dist/api/drift.js.map +1 -0
- package/dist/api/generate.d.ts +18 -0
- package/dist/api/generate.d.ts.map +1 -0
- package/dist/api/generate.js +251 -0
- package/dist/api/generate.js.map +1 -0
- package/dist/api/index.d.ts +39 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +32 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/init.d.ts +18 -0
- package/dist/api/init.d.ts.map +1 -0
- package/dist/api/init.js +82 -0
- package/dist/api/init.js.map +1 -0
- package/dist/api/run.d.ts +19 -0
- package/dist/api/run.d.ts.map +1 -0
- package/dist/api/run.js +291 -0
- package/dist/api/run.js.map +1 -0
- package/dist/api/specs.d.ts +49 -0
- package/dist/api/specs.d.ts.map +1 -0
- package/dist/api/specs.js +136 -0
- package/dist/api/specs.js.map +1 -0
- package/dist/api/types.d.ts +176 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/verify.d.ts +20 -0
- package/dist/api/verify.d.ts.map +1 -0
- package/dist/api/verify.js +117 -0
- package/dist/api/verify.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +27 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +485 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/drift.d.ts +9 -0
- package/dist/cli/commands/drift.d.ts.map +1 -0
- package/dist/cli/commands/drift.js +540 -0
- package/dist/cli/commands/drift.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +633 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +171 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +638 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +574 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/run.d.ts +24 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +546 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +9 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +417 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/view.d.ts +9 -0
- package/dist/cli/commands/view.d.ts.map +1 -0
- package/dist/cli/commands/view.js +511 -0
- package/dist/cli/commands/view.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +83 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/analyzer/architecture-writer.d.ts +67 -0
- package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
- package/dist/core/analyzer/architecture-writer.js +209 -0
- package/dist/core/analyzer/architecture-writer.js.map +1 -0
- package/dist/core/analyzer/artifact-generator.d.ts +222 -0
- package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
- package/dist/core/analyzer/artifact-generator.js +726 -0
- package/dist/core/analyzer/artifact-generator.js.map +1 -0
- package/dist/core/analyzer/call-graph.d.ts +83 -0
- package/dist/core/analyzer/call-graph.d.ts.map +1 -0
- package/dist/core/analyzer/call-graph.js +827 -0
- package/dist/core/analyzer/call-graph.js.map +1 -0
- package/dist/core/analyzer/code-shaper.d.ts +33 -0
- package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
- package/dist/core/analyzer/code-shaper.js +149 -0
- package/dist/core/analyzer/code-shaper.js.map +1 -0
- package/dist/core/analyzer/dependency-graph.d.ts +179 -0
- package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
- package/dist/core/analyzer/dependency-graph.js +574 -0
- package/dist/core/analyzer/dependency-graph.js.map +1 -0
- package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
- package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
- package/dist/core/analyzer/duplicate-detector.js +279 -0
- package/dist/core/analyzer/duplicate-detector.js.map +1 -0
- package/dist/core/analyzer/embedding-service.d.ts +50 -0
- package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
- package/dist/core/analyzer/embedding-service.js +104 -0
- package/dist/core/analyzer/embedding-service.js.map +1 -0
- package/dist/core/analyzer/file-walker.d.ts +78 -0
- package/dist/core/analyzer/file-walker.d.ts.map +1 -0
- package/dist/core/analyzer/file-walker.js +531 -0
- package/dist/core/analyzer/file-walker.js.map +1 -0
- package/dist/core/analyzer/import-parser.d.ts +91 -0
- package/dist/core/analyzer/import-parser.d.ts.map +1 -0
- package/dist/core/analyzer/import-parser.js +720 -0
- package/dist/core/analyzer/import-parser.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +10 -0
- package/dist/core/analyzer/index.d.ts.map +1 -0
- package/dist/core/analyzer/index.js +10 -0
- package/dist/core/analyzer/index.js.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts +80 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.js +339 -0
- package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
- package/dist/core/analyzer/repository-mapper.d.ts +150 -0
- package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
- package/dist/core/analyzer/repository-mapper.js +731 -0
- package/dist/core/analyzer/repository-mapper.js.map +1 -0
- package/dist/core/analyzer/signature-extractor.d.ts +31 -0
- package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/signature-extractor.js +387 -0
- package/dist/core/analyzer/signature-extractor.js.map +1 -0
- package/dist/core/analyzer/significance-scorer.d.ts +79 -0
- package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
- package/dist/core/analyzer/significance-scorer.js +407 -0
- package/dist/core/analyzer/significance-scorer.js.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts +43 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.js +129 -0
- package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
- package/dist/core/analyzer/vector-index.d.ts +63 -0
- package/dist/core/analyzer/vector-index.d.ts.map +1 -0
- package/dist/core/analyzer/vector-index.js +169 -0
- package/dist/core/analyzer/vector-index.js.map +1 -0
- package/dist/core/drift/drift-detector.d.ts +102 -0
- package/dist/core/drift/drift-detector.d.ts.map +1 -0
- package/dist/core/drift/drift-detector.js +597 -0
- package/dist/core/drift/drift-detector.js.map +1 -0
- package/dist/core/drift/git-diff.d.ts +55 -0
- package/dist/core/drift/git-diff.d.ts.map +1 -0
- package/dist/core/drift/git-diff.js +356 -0
- package/dist/core/drift/git-diff.js.map +1 -0
- package/dist/core/drift/index.d.ts +12 -0
- package/dist/core/drift/index.d.ts.map +1 -0
- package/dist/core/drift/index.js +9 -0
- package/dist/core/drift/index.js.map +1 -0
- package/dist/core/drift/spec-mapper.d.ts +73 -0
- package/dist/core/drift/spec-mapper.d.ts.map +1 -0
- package/dist/core/drift/spec-mapper.js +353 -0
- package/dist/core/drift/spec-mapper.js.map +1 -0
- package/dist/core/generator/adr-generator.d.ts +32 -0
- package/dist/core/generator/adr-generator.d.ts.map +1 -0
- package/dist/core/generator/adr-generator.js +192 -0
- package/dist/core/generator/adr-generator.js.map +1 -0
- package/dist/core/generator/index.d.ts +9 -0
- package/dist/core/generator/index.d.ts.map +1 -0
- package/dist/core/generator/index.js +12 -0
- package/dist/core/generator/index.js.map +1 -0
- package/dist/core/generator/mapping-generator.d.ts +54 -0
- package/dist/core/generator/mapping-generator.d.ts.map +1 -0
- package/dist/core/generator/mapping-generator.js +239 -0
- package/dist/core/generator/mapping-generator.js.map +1 -0
- package/dist/core/generator/openspec-compat.d.ts +160 -0
- package/dist/core/generator/openspec-compat.d.ts.map +1 -0
- package/dist/core/generator/openspec-compat.js +523 -0
- package/dist/core/generator/openspec-compat.js.map +1 -0
- package/dist/core/generator/openspec-format-generator.d.ts +111 -0
- package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
- package/dist/core/generator/openspec-format-generator.js +817 -0
- package/dist/core/generator/openspec-format-generator.js.map +1 -0
- package/dist/core/generator/openspec-writer.d.ts +131 -0
- package/dist/core/generator/openspec-writer.d.ts.map +1 -0
- package/dist/core/generator/openspec-writer.js +379 -0
- package/dist/core/generator/openspec-writer.js.map +1 -0
- package/dist/core/generator/prompts.d.ts +35 -0
- package/dist/core/generator/prompts.d.ts.map +1 -0
- package/dist/core/generator/prompts.js +212 -0
- package/dist/core/generator/prompts.js.map +1 -0
- package/dist/core/generator/spec-pipeline.d.ts +94 -0
- package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
- package/dist/core/generator/spec-pipeline.js +474 -0
- package/dist/core/generator/spec-pipeline.js.map +1 -0
- package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
- package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
- package/dist/core/generator/stages/stage1-survey.js +105 -0
- package/dist/core/generator/stages/stage1-survey.js.map +1 -0
- package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
- package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
- package/dist/core/generator/stages/stage2-entities.js +67 -0
- package/dist/core/generator/stages/stage2-entities.js.map +1 -0
- package/dist/core/generator/stages/stage3-services.d.ts +11 -0
- package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
- package/dist/core/generator/stages/stage3-services.js +75 -0
- package/dist/core/generator/stages/stage3-services.js.map +1 -0
- package/dist/core/generator/stages/stage4-api.d.ts +11 -0
- package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
- package/dist/core/generator/stages/stage4-api.js +65 -0
- package/dist/core/generator/stages/stage4-api.js.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts +10 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.js +62 -0
- package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
- package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
- package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
- package/dist/core/generator/stages/stage6-adr.js +41 -0
- package/dist/core/generator/stages/stage6-adr.js.map +1 -0
- package/dist/core/services/chat-agent.d.ts +45 -0
- package/dist/core/services/chat-agent.d.ts.map +1 -0
- package/dist/core/services/chat-agent.js +310 -0
- package/dist/core/services/chat-agent.js.map +1 -0
- package/dist/core/services/chat-tools.d.ts +32 -0
- package/dist/core/services/chat-tools.d.ts.map +1 -0
- package/dist/core/services/chat-tools.js +270 -0
- package/dist/core/services/chat-tools.js.map +1 -0
- package/dist/core/services/config-manager.d.ts +61 -0
- package/dist/core/services/config-manager.d.ts.map +1 -0
- package/dist/core/services/config-manager.js +143 -0
- package/dist/core/services/config-manager.js.map +1 -0
- package/dist/core/services/gitignore-manager.d.ts +29 -0
- package/dist/core/services/gitignore-manager.d.ts.map +1 -0
- package/dist/core/services/gitignore-manager.js +106 -0
- package/dist/core/services/gitignore-manager.js.map +1 -0
- package/dist/core/services/index.d.ts +8 -0
- package/dist/core/services/index.d.ts.map +1 -0
- package/dist/core/services/index.js +8 -0
- package/dist/core/services/index.js.map +1 -0
- package/dist/core/services/llm-service.d.ts +336 -0
- package/dist/core/services/llm-service.d.ts.map +1 -0
- package/dist/core/services/llm-service.js +1155 -0
- package/dist/core/services/llm-service.js.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts +42 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.js +300 -0
- package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
- package/dist/core/services/mcp-handlers/graph.d.ts +65 -0
- package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/graph.js +509 -0
- package/dist/core/services/mcp-handlers/graph.js.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts +38 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.js +172 -0
- package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
- package/dist/core/services/mcp-handlers/utils.d.ts +21 -0
- package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/utils.js +62 -0
- package/dist/core/services/mcp-handlers/utils.js.map +1 -0
- package/dist/core/services/project-detector.d.ts +32 -0
- package/dist/core/services/project-detector.d.ts.map +1 -0
- package/dist/core/services/project-detector.js +111 -0
- package/dist/core/services/project-detector.js.map +1 -0
- package/dist/core/verifier/index.d.ts +5 -0
- package/dist/core/verifier/index.d.ts.map +1 -0
- package/dist/core/verifier/index.js +5 -0
- package/dist/core/verifier/index.js.map +1 -0
- package/dist/core/verifier/verification-engine.d.ts +226 -0
- package/dist/core/verifier/verification-engine.d.ts.map +1 -0
- package/dist/core/verifier/verification-engine.js +681 -0
- package/dist/core/verifier/verification-engine.js.map +1 -0
- package/dist/types/index.d.ts +252 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pipeline.d.ts +148 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +5 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +128 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +149 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +331 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/progress.d.ts +142 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +280 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/prompts.d.ts +53 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +199 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/shutdown.d.ts +89 -0
- package/dist/utils/shutdown.d.ts.map +1 -0
- package/dist/utils/shutdown.js +237 -0
- package/dist/utils/shutdown.js.map +1 -0
- package/package.json +114 -0
- package/src/viewer/InteractiveGraphViewer.jsx +1486 -0
- package/src/viewer/app/index.html +17 -0
- package/src/viewer/app/main.jsx +13 -0
- package/src/viewer/components/ArchitectureView.jsx +177 -0
- package/src/viewer/components/ChatPanel.jsx +448 -0
- package/src/viewer/components/ClusterGraph.jsx +441 -0
- package/src/viewer/components/FilterBar.jsx +179 -0
- package/src/viewer/components/FlatGraph.jsx +275 -0
- package/src/viewer/components/MicroComponents.jsx +83 -0
- package/src/viewer/hooks/usePanZoom.js +79 -0
- package/src/viewer/utils/constants.js +47 -0
- package/src/viewer/utils/graph-helpers.js +291 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spec-gen generate command
|
|
3
|
+
*
|
|
4
|
+
* Generates OpenSpec specification files from analysis results using LLM.
|
|
5
|
+
* Outputs to openspec/specs/ directory in standard OpenSpec format.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { access, readFile, stat } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { logger } from '../../utils/logger.js';
|
|
11
|
+
import { readSpecGenConfig, readOpenSpecConfig, } from '../../core/services/config-manager.js';
|
|
12
|
+
import { createLLMService, lookupPricing, } from '../../core/services/llm-service.js';
|
|
13
|
+
import { SpecGenerationPipeline, } from '../../core/generator/spec-pipeline.js';
|
|
14
|
+
import { OpenSpecFormatGenerator, } from '../../core/generator/openspec-format-generator.js';
|
|
15
|
+
import { OpenSpecWriter, } from '../../core/generator/openspec-writer.js';
|
|
16
|
+
import { ADRGenerator } from '../../core/generator/adr-generator.js';
|
|
17
|
+
import { MappingGenerator } from '../../core/generator/mapping-generator.js';
|
|
18
|
+
import { createProgress } from '../../utils/progress.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// HELPER FUNCTIONS
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Parse comma-separated domain list
|
|
24
|
+
*/
|
|
25
|
+
function parseDomains(value) {
|
|
26
|
+
return value.split(',').map((d) => d.trim()).filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if a file exists
|
|
30
|
+
*/
|
|
31
|
+
async function fileExists(path) {
|
|
32
|
+
try {
|
|
33
|
+
await access(path);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Format time duration for display
|
|
42
|
+
*/
|
|
43
|
+
function formatDuration(ms) {
|
|
44
|
+
if (ms < 1000)
|
|
45
|
+
return `${ms}ms`;
|
|
46
|
+
if (ms < 60000)
|
|
47
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
48
|
+
const minutes = Math.floor(ms / 60000);
|
|
49
|
+
const seconds = Math.floor((ms % 60000) / 1000);
|
|
50
|
+
return `${minutes}m ${seconds}s`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Format age in human-readable form
|
|
54
|
+
*/
|
|
55
|
+
function formatAge(ms) {
|
|
56
|
+
if (ms < 60000)
|
|
57
|
+
return 'just now';
|
|
58
|
+
if (ms < 3600000)
|
|
59
|
+
return `${Math.floor(ms / 60000)} minutes ago`;
|
|
60
|
+
if (ms < 86400000)
|
|
61
|
+
return `${Math.floor(ms / 3600000)} hours ago`;
|
|
62
|
+
return `${Math.floor(ms / 86400000)} days ago`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load analysis data from disk
|
|
66
|
+
*/
|
|
67
|
+
async function loadAnalysis(analysisPath) {
|
|
68
|
+
try {
|
|
69
|
+
const repoStructurePath = join(analysisPath, 'repo-structure.json');
|
|
70
|
+
const llmContextPath = join(analysisPath, 'llm-context.json');
|
|
71
|
+
// Check if analysis exists
|
|
72
|
+
if (!(await fileExists(repoStructurePath))) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
// Load repo structure
|
|
76
|
+
const repoStructureContent = await readFile(repoStructurePath, 'utf-8');
|
|
77
|
+
const repoStructure = JSON.parse(repoStructureContent);
|
|
78
|
+
// Load LLM context
|
|
79
|
+
let llmContext;
|
|
80
|
+
if (await fileExists(llmContextPath)) {
|
|
81
|
+
const llmContextContent = await readFile(llmContextPath, 'utf-8');
|
|
82
|
+
llmContext = JSON.parse(llmContextContent);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Create minimal context if not available
|
|
86
|
+
llmContext = {
|
|
87
|
+
phase1_survey: { purpose: 'Initial survey', files: [], estimatedTokens: 0 },
|
|
88
|
+
phase2_deep: { purpose: 'Deep analysis', files: [], totalTokens: 0 },
|
|
89
|
+
phase3_validation: { purpose: 'Validation', files: [], totalTokens: 0 },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Try to load dependency graph
|
|
93
|
+
let depGraph;
|
|
94
|
+
const depGraphPath = join(analysisPath, 'dependency-graph.json');
|
|
95
|
+
if (await fileExists(depGraphPath)) {
|
|
96
|
+
const depGraphContent = await readFile(depGraphPath, 'utf-8');
|
|
97
|
+
depGraph = JSON.parse(depGraphContent);
|
|
98
|
+
}
|
|
99
|
+
// Get analysis age
|
|
100
|
+
const stats = await stat(repoStructurePath);
|
|
101
|
+
const age = Date.now() - stats.mtime.getTime();
|
|
102
|
+
const timestamp = stats.mtime.toISOString();
|
|
103
|
+
return { repoStructure, llmContext, depGraph, age, timestamp };
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
logger.warning(`Failed to load analysis: ${error.message}`);
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Estimate cost for the full generation pipeline (all stages).
|
|
112
|
+
*
|
|
113
|
+
* The pipeline makes multiple LLM calls:
|
|
114
|
+
* Stage 1 — 1 call (survey)
|
|
115
|
+
* Stage 2 — 1 call per phase2_deep file (entity extraction)
|
|
116
|
+
* Stage 3 — 1 call per phase2_deep file (service analysis, same files as Stage 2)
|
|
117
|
+
* Stage 4 — 1 call (API extraction, condensed context)
|
|
118
|
+
* Stage 5 — 1 call (architecture synthesis, full context)
|
|
119
|
+
* Stage 6 — 1 call (ADR, optional — not counted here)
|
|
120
|
+
*/
|
|
121
|
+
function estimateCost(llmContext, provider, model) {
|
|
122
|
+
const OVERHEAD = 500; // system prompt per call (tokens)
|
|
123
|
+
const OUTPUT_RATIO = 0.4; // output ≈ 40% of input for spec tasks
|
|
124
|
+
const phase2Files = llmContext.phase2_deep.files;
|
|
125
|
+
const phase2Total = phase2Files.reduce((s, f) => s + f.tokens, 0);
|
|
126
|
+
const fileOverhead = OVERHEAD * phase2Files.length;
|
|
127
|
+
const stage1Input = (llmContext.phase1_survey.estimatedTokens ?? 2000) + OVERHEAD;
|
|
128
|
+
const stage2Input = phase2Total + fileOverhead; // entity extraction
|
|
129
|
+
const stage3Input = phase2Total + fileOverhead; // service analysis (same files)
|
|
130
|
+
const stage4Input = Math.ceil(phase2Total * 0.5) + OVERHEAD; // API extraction
|
|
131
|
+
const stage5Input = Math.ceil((stage1Input + stage2Input) * 0.3) + OVERHEAD; // architecture
|
|
132
|
+
const totalInput = stage1Input + stage2Input + stage3Input + stage4Input + stage5Input;
|
|
133
|
+
const totalOutput = Math.ceil(totalInput * OUTPUT_RATIO);
|
|
134
|
+
const modelPricing = lookupPricing(provider, model);
|
|
135
|
+
const cost = (totalInput / 1_000_000) * modelPricing.input
|
|
136
|
+
+ (totalOutput / 1_000_000) * modelPricing.output;
|
|
137
|
+
return { tokens: totalInput + totalOutput, cost };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Prompt user for confirmation
|
|
141
|
+
*/
|
|
142
|
+
async function promptConfirmation(message, autoYes) {
|
|
143
|
+
if (autoYes) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
// In a real CLI, we'd use readline here
|
|
147
|
+
// For now, we assume yes in non-interactive mode
|
|
148
|
+
logger.discovery(message);
|
|
149
|
+
logger.discovery('Use --yes or -y to skip confirmation prompts');
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Verify LLM API connectivity
|
|
154
|
+
*/
|
|
155
|
+
async function verifyApiConnectivity(llm) {
|
|
156
|
+
try {
|
|
157
|
+
logger.debug('Verifying LLM API connectivity...');
|
|
158
|
+
await llm.complete({
|
|
159
|
+
systemPrompt: 'You are a test assistant.',
|
|
160
|
+
userPrompt: 'Reply with just: OK',
|
|
161
|
+
maxTokens: 5,
|
|
162
|
+
temperature: 0,
|
|
163
|
+
});
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
logger.error(`LLM API verification failed: ${error.message}`);
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// COMMAND
|
|
173
|
+
// ============================================================================
|
|
174
|
+
export const generateCommand = new Command('generate')
|
|
175
|
+
.description('Generate OpenSpec files from analysis using LLM')
|
|
176
|
+
.option('--analysis <path>', 'Path to existing analysis (skips re-analysis)', '.spec-gen/analysis/')
|
|
177
|
+
.option('--model <name>', 'LLM model to use for generation (default depends on provider)')
|
|
178
|
+
.option('--dry-run', 'Show what would be generated without writing files', false)
|
|
179
|
+
.option('--domains <list>', 'Only generate specific domains (comma-separated)', parseDomains)
|
|
180
|
+
.option('--reanalyze', 'Force fresh analysis even if recent exists', false)
|
|
181
|
+
.option('--merge', 'Use merge strategy for existing specs', false)
|
|
182
|
+
.option('--no-overwrite', 'Skip any existing spec files', false)
|
|
183
|
+
.option('-y, --yes', 'Skip confirmation prompts', false)
|
|
184
|
+
.option('--output-dir <path>', 'Override openspec output location')
|
|
185
|
+
.option('--adr', 'Generate Architecture Decision Records alongside specs', false)
|
|
186
|
+
.option('--adr-only', 'Only generate ADRs (skip spec generation)', false)
|
|
187
|
+
.addHelpText('after', `
|
|
188
|
+
Examples:
|
|
189
|
+
$ spec-gen generate Generate all specs from analysis
|
|
190
|
+
$ spec-gen generate --dry-run Preview without writing files
|
|
191
|
+
$ spec-gen generate --domains auth,api,database
|
|
192
|
+
Only generate specific domains
|
|
193
|
+
$ spec-gen generate --model claude-opus-4-20250514
|
|
194
|
+
Use a different model
|
|
195
|
+
$ spec-gen generate --analysis ./my-analysis
|
|
196
|
+
Use analysis from custom path
|
|
197
|
+
$ spec-gen generate --merge Merge with existing specs
|
|
198
|
+
$ spec-gen generate --no-overwrite Skip existing spec files
|
|
199
|
+
$ spec-gen generate --adr Also generate ADRs
|
|
200
|
+
$ spec-gen generate --adr-only Only generate ADRs
|
|
201
|
+
$ spec-gen generate -y Skip confirmation prompts
|
|
202
|
+
|
|
203
|
+
Output structure (OpenSpec format):
|
|
204
|
+
openspec/
|
|
205
|
+
├── config.yaml Project configuration (updated)
|
|
206
|
+
├── specs/
|
|
207
|
+
│ ├── overview/spec.md System overview
|
|
208
|
+
│ ├── architecture/spec.md System architecture
|
|
209
|
+
│ ├── {domain}/spec.md Domain specifications
|
|
210
|
+
│ └── api/spec.md API specification (if applicable)
|
|
211
|
+
└── decisions/ Architecture Decision Records (with --adr)
|
|
212
|
+
├── index.md ADR index
|
|
213
|
+
└── adr-NNNN-*.md Individual decisions
|
|
214
|
+
|
|
215
|
+
Each spec.md follows OpenSpec conventions:
|
|
216
|
+
- RFC 2119 keywords (SHALL, MUST, SHOULD, MAY)
|
|
217
|
+
- Given/When/Then scenarios with #### headings
|
|
218
|
+
- Technical notes linking to source files
|
|
219
|
+
`)
|
|
220
|
+
.action(async function (options) {
|
|
221
|
+
const startTime = Date.now();
|
|
222
|
+
const rootPath = process.cwd();
|
|
223
|
+
// Inherit global options (--api-base, --insecure, etc.)
|
|
224
|
+
const globalOpts = this.optsWithGlobals?.() ?? {};
|
|
225
|
+
const opts = {
|
|
226
|
+
analysis: options.analysis ?? '.spec-gen/analysis/',
|
|
227
|
+
model: options.model ?? '',
|
|
228
|
+
dryRun: options.dryRun ?? false,
|
|
229
|
+
domains: options.domains ?? [],
|
|
230
|
+
adr: options.adr ?? false,
|
|
231
|
+
adrOnly: options.adrOnly ?? false,
|
|
232
|
+
reanalyze: options.reanalyze ?? false,
|
|
233
|
+
merge: options.merge ?? false,
|
|
234
|
+
noOverwrite: options.noOverwrite ?? false,
|
|
235
|
+
yes: options.yes ?? false,
|
|
236
|
+
outputDir: options.outputDir,
|
|
237
|
+
quiet: false,
|
|
238
|
+
verbose: false,
|
|
239
|
+
noColor: false,
|
|
240
|
+
config: '.spec-gen/config.json',
|
|
241
|
+
};
|
|
242
|
+
try {
|
|
243
|
+
// ========================================================================
|
|
244
|
+
// PHASE 1: CONFIGURATION LOADING
|
|
245
|
+
// ========================================================================
|
|
246
|
+
logger.section('Loading Configuration');
|
|
247
|
+
// Load spec-gen config
|
|
248
|
+
const specGenConfig = await readSpecGenConfig(rootPath);
|
|
249
|
+
if (!specGenConfig) {
|
|
250
|
+
logger.error('No spec-gen configuration found. Run "spec-gen init" first.');
|
|
251
|
+
process.exitCode = 1;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// Determine openspec path
|
|
255
|
+
const openspecPath = opts.outputDir ?? specGenConfig.openspecPath ?? 'openspec';
|
|
256
|
+
const fullOpenspecPath = join(rootPath, openspecPath);
|
|
257
|
+
// Load existing OpenSpec config if present
|
|
258
|
+
const openspecConfig = await readOpenSpecConfig(fullOpenspecPath);
|
|
259
|
+
logger.info('Project', specGenConfig.projectType);
|
|
260
|
+
logger.info('OpenSpec path', openspecPath);
|
|
261
|
+
if (openspecConfig?.context) {
|
|
262
|
+
logger.info('Context', openspecConfig.context.substring(0, 50) + '...');
|
|
263
|
+
}
|
|
264
|
+
logger.blank();
|
|
265
|
+
// ========================================================================
|
|
266
|
+
// PHASE 2: ANALYSIS LOADING
|
|
267
|
+
// ========================================================================
|
|
268
|
+
logger.section('Loading Analysis');
|
|
269
|
+
const analysisPath = join(rootPath, opts.analysis);
|
|
270
|
+
const analysisData = await loadAnalysis(analysisPath);
|
|
271
|
+
if (!analysisData || opts.reanalyze) {
|
|
272
|
+
if (opts.reanalyze) {
|
|
273
|
+
logger.discovery('Forced re-analysis requested');
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
logger.error('No analysis found. Run "spec-gen analyze" first.');
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
// Note: Re-analysis would be implemented here using the analyzer modules
|
|
281
|
+
// For now, we require existing analysis
|
|
282
|
+
if (!analysisData) {
|
|
283
|
+
logger.error('Analysis required. Run "spec-gen analyze" first.');
|
|
284
|
+
process.exitCode = 1;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const { repoStructure, llmContext, depGraph, age } = analysisData;
|
|
289
|
+
logger.discovery(`Using analysis from ${formatAge(age)}`);
|
|
290
|
+
logger.info('Files analyzed', repoStructure.statistics.analyzedFiles);
|
|
291
|
+
logger.info('Domains detected', repoStructure.domains.map(d => d.name).join(', ') || 'None');
|
|
292
|
+
logger.blank();
|
|
293
|
+
// ========================================================================
|
|
294
|
+
// PHASE 3: PRE-FLIGHT CHECKS
|
|
295
|
+
// ========================================================================
|
|
296
|
+
logger.section('Pre-flight Checks');
|
|
297
|
+
// Check for API key
|
|
298
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
299
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
300
|
+
const openaiCompatKey = process.env.OPENAI_COMPAT_API_KEY;
|
|
301
|
+
const geminiKey = process.env.GEMINI_API_KEY;
|
|
302
|
+
// Resolve provider early so we can skip the API key check for claude-code
|
|
303
|
+
const envDetectedProvider = anthropicKey ? 'anthropic'
|
|
304
|
+
: geminiKey ? 'gemini'
|
|
305
|
+
: openaiCompatKey ? 'openai-compat'
|
|
306
|
+
: 'openai';
|
|
307
|
+
const rootConfig = specGenConfig;
|
|
308
|
+
const effectiveProvider = (specGenConfig.generation.provider ?? rootConfig['provider'] ?? envDetectedProvider);
|
|
309
|
+
if (effectiveProvider !== 'claude-code' && effectiveProvider !== 'mistral-vibe' && !anthropicKey && !openaiKey && !openaiCompatKey && !geminiKey) {
|
|
310
|
+
logger.error('No LLM API key found.');
|
|
311
|
+
logger.discovery('Set one of the following environment variables:');
|
|
312
|
+
logger.discovery(' ANTHROPIC_API_KEY → https://console.anthropic.com/');
|
|
313
|
+
logger.discovery(' OPENAI_API_KEY → https://platform.openai.com/');
|
|
314
|
+
logger.discovery(' GEMINI_API_KEY → https://aistudio.google.com/');
|
|
315
|
+
logger.discovery(' OPENAI_COMPAT_API_KEY + OPENAI_COMPAT_BASE_URL → Mistral, Groq, Ollama...');
|
|
316
|
+
logger.discovery(' Or set provider to "claude-code" or "mistral-vibe" to use local CLI tools (no API key needed).');
|
|
317
|
+
process.exitCode = 1;
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
// Resolve model with priority: CLI flag > config > provider default
|
|
321
|
+
const defaultModels = {
|
|
322
|
+
anthropic: 'claude-sonnet-4-20250514',
|
|
323
|
+
gemini: 'gemini-2.0-flash',
|
|
324
|
+
'openai-compat': 'mistral-large-latest',
|
|
325
|
+
openai: 'gpt-4o',
|
|
326
|
+
'claude-code': 'claude-code',
|
|
327
|
+
'mistral-vibe': 'mistral-vibe',
|
|
328
|
+
};
|
|
329
|
+
const effectiveModel = opts.model || specGenConfig.generation.model || defaultModels[effectiveProvider];
|
|
330
|
+
// Resolve openai-compat base URL with priority: env var > config (generation or root)
|
|
331
|
+
const effectiveBaseUrl = process.env.OPENAI_COMPAT_BASE_URL ?? specGenConfig.generation.openaiCompatBaseUrl ?? rootConfig['openaiCompatBaseUrl'];
|
|
332
|
+
// Apply SSL verification setting (CLI --insecure or config skipSslVerify)
|
|
333
|
+
if (globalOpts.insecure || specGenConfig.generation.skipSslVerify || specGenConfig.embedding?.skipSslVerify) {
|
|
334
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
335
|
+
logger.warning('SSL verification disabled');
|
|
336
|
+
}
|
|
337
|
+
// Estimate cost
|
|
338
|
+
const estimate = estimateCost(llmContext, effectiveProvider, effectiveModel);
|
|
339
|
+
logger.info('Model', effectiveModel);
|
|
340
|
+
logger.info('Estimated tokens', estimate.tokens.toLocaleString());
|
|
341
|
+
logger.inference(`Estimated cost: ~$${estimate.cost.toFixed(2)}`);
|
|
342
|
+
logger.blank();
|
|
343
|
+
// Check for existing specs
|
|
344
|
+
const specsPath = join(fullOpenspecPath, 'specs');
|
|
345
|
+
if (await fileExists(specsPath)) {
|
|
346
|
+
if (opts.merge) {
|
|
347
|
+
logger.info('Mode', 'Merge with existing specs');
|
|
348
|
+
}
|
|
349
|
+
else if (opts.noOverwrite) {
|
|
350
|
+
logger.info('Mode', 'Skip existing specs');
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
logger.warning('Existing specs will be replaced (backed up)');
|
|
354
|
+
}
|
|
355
|
+
logger.blank();
|
|
356
|
+
}
|
|
357
|
+
// Dry run notice
|
|
358
|
+
if (opts.dryRun) {
|
|
359
|
+
logger.discovery('DRY RUN - No files will be written');
|
|
360
|
+
logger.blank();
|
|
361
|
+
}
|
|
362
|
+
// Confirmation prompt
|
|
363
|
+
if (!opts.dryRun && estimate.cost > 0.5) {
|
|
364
|
+
const confirmed = await promptConfirmation(`Estimated cost: ~$${estimate.cost.toFixed(2)}. Continue? [Y/n]`, opts.yes ?? false);
|
|
365
|
+
if (!confirmed) {
|
|
366
|
+
logger.discovery('Cancelled by user');
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// ========================================================================
|
|
371
|
+
// PHASE 4: LLM GENERATION
|
|
372
|
+
// ========================================================================
|
|
373
|
+
logger.section('Generating Specifications');
|
|
374
|
+
if (opts.dryRun) {
|
|
375
|
+
// In dry run mode, show what would be generated
|
|
376
|
+
logger.discovery('Would run LLM generation pipeline with:');
|
|
377
|
+
logger.listItem('Stage 1: Project Survey');
|
|
378
|
+
logger.listItem('Stage 2: Entity Extraction');
|
|
379
|
+
logger.listItem('Stage 3: Service Analysis');
|
|
380
|
+
logger.listItem('Stage 4: API Extraction');
|
|
381
|
+
logger.listItem('Stage 5: Architecture Synthesis');
|
|
382
|
+
logger.blank();
|
|
383
|
+
// Show domains that would be generated
|
|
384
|
+
const domainFilter = opts.domains.length > 0 ? opts.domains : repoStructure.domains.map(d => d.name);
|
|
385
|
+
logger.discovery('Domains to generate:');
|
|
386
|
+
for (const domain of domainFilter) {
|
|
387
|
+
logger.listItem(domain);
|
|
388
|
+
}
|
|
389
|
+
logger.blank();
|
|
390
|
+
// Show output paths
|
|
391
|
+
logger.discovery('Would write specs to:');
|
|
392
|
+
logger.listItem(`${openspecPath}/specs/overview/spec.md`);
|
|
393
|
+
logger.listItem(`${openspecPath}/specs/architecture/spec.md`);
|
|
394
|
+
for (const domain of domainFilter) {
|
|
395
|
+
logger.listItem(`${openspecPath}/specs/${domain}/spec.md`);
|
|
396
|
+
}
|
|
397
|
+
logger.listItem(`${openspecPath}/specs/api/spec.md (if applicable)`);
|
|
398
|
+
logger.blank();
|
|
399
|
+
logger.success('Dry run complete. No files were modified.');
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
// Create LLM service (CLI flags > env vars > config file)
|
|
403
|
+
let llm;
|
|
404
|
+
try {
|
|
405
|
+
llm = createLLMService({
|
|
406
|
+
provider: effectiveProvider,
|
|
407
|
+
model: effectiveModel,
|
|
408
|
+
openaiCompatBaseUrl: effectiveBaseUrl,
|
|
409
|
+
apiBase: globalOpts.apiBase ?? specGenConfig.llm?.apiBase,
|
|
410
|
+
sslVerify: globalOpts.insecure != null ? !globalOpts.insecure : specGenConfig.llm?.sslVerify ?? true,
|
|
411
|
+
enableLogging: true,
|
|
412
|
+
logDir: join(rootPath, '.spec-gen', 'logs'),
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
logger.error(`Failed to create LLM service: ${error.message}`);
|
|
417
|
+
process.exitCode = 1;
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
// Verify API connectivity
|
|
421
|
+
if (!(await verifyApiConnectivity(llm))) {
|
|
422
|
+
logger.error('Failed to connect to LLM API. Check your API key and network.');
|
|
423
|
+
process.exitCode = 1;
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
// Run generation pipeline
|
|
427
|
+
const progress = createProgress();
|
|
428
|
+
progress.start('Generating specifications...');
|
|
429
|
+
const pipeline = new SpecGenerationPipeline(llm, {
|
|
430
|
+
outputDir: join(rootPath, '.spec-gen', 'generation'),
|
|
431
|
+
rootPath,
|
|
432
|
+
saveIntermediate: true,
|
|
433
|
+
generateADRs: opts.adr || opts.adrOnly,
|
|
434
|
+
progress,
|
|
435
|
+
});
|
|
436
|
+
let pipelineResult;
|
|
437
|
+
try {
|
|
438
|
+
pipelineResult = await pipeline.run(repoStructure, llmContext, depGraph);
|
|
439
|
+
progress.succeed('Pipeline completed');
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
progress.fail(`Pipeline failed: ${error.message}`);
|
|
443
|
+
// Save logs on failure
|
|
444
|
+
try {
|
|
445
|
+
await llm.saveLogs();
|
|
446
|
+
logger.discovery('LLM logs saved to .spec-gen/logs/');
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
// Ignore log save errors
|
|
450
|
+
}
|
|
451
|
+
process.exitCode = 1;
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
// Show pipeline results
|
|
455
|
+
const { metadata } = pipelineResult;
|
|
456
|
+
logger.blank();
|
|
457
|
+
logger.success('Pipeline completed');
|
|
458
|
+
logger.info('Stages completed', metadata.completedStages.join(', '));
|
|
459
|
+
if (metadata.skippedStages.length > 0) {
|
|
460
|
+
logger.info('Stages skipped', metadata.skippedStages.join(', '));
|
|
461
|
+
}
|
|
462
|
+
logger.info('Total tokens', metadata.totalTokens.toLocaleString());
|
|
463
|
+
logger.info('Cost', `$${metadata.estimatedCost.toFixed(4)}`);
|
|
464
|
+
logger.info('Duration', formatDuration(metadata.duration));
|
|
465
|
+
logger.blank();
|
|
466
|
+
// ========================================================================
|
|
467
|
+
// PHASE 5: FORMAT AND WRITE SPECS
|
|
468
|
+
// ========================================================================
|
|
469
|
+
logger.section('Writing OpenSpec Files');
|
|
470
|
+
// Generate formatted specs
|
|
471
|
+
const formatGenerator = new OpenSpecFormatGenerator({
|
|
472
|
+
version: specGenConfig.version,
|
|
473
|
+
includeConfidence: true,
|
|
474
|
+
includeTechnicalNotes: true,
|
|
475
|
+
});
|
|
476
|
+
let generatedSpecs = opts.adrOnly ? [] : formatGenerator.generateSpecs(pipelineResult);
|
|
477
|
+
// Filter by domains if specified
|
|
478
|
+
if (!opts.adrOnly && opts.domains.length > 0) {
|
|
479
|
+
const domainSet = new Set(opts.domains.map(d => d.toLowerCase()));
|
|
480
|
+
generatedSpecs = generatedSpecs.filter(spec => {
|
|
481
|
+
// Always include overview and architecture
|
|
482
|
+
if (spec.type === 'overview' || spec.type === 'architecture') {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
// Check if domain matches
|
|
486
|
+
return domainSet.has(spec.domain.toLowerCase());
|
|
487
|
+
});
|
|
488
|
+
logger.info('Filtered to domains', opts.domains.join(', '));
|
|
489
|
+
}
|
|
490
|
+
// Generate ADRs if requested
|
|
491
|
+
if (opts.adr || opts.adrOnly) {
|
|
492
|
+
const adrGenerator = new ADRGenerator({
|
|
493
|
+
version: specGenConfig.version,
|
|
494
|
+
includeMermaid: true,
|
|
495
|
+
});
|
|
496
|
+
const adrSpecs = adrGenerator.generateADRs(pipelineResult);
|
|
497
|
+
if (adrSpecs.length > 0) {
|
|
498
|
+
logger.info('ADRs generated', adrSpecs.length);
|
|
499
|
+
generatedSpecs = [...generatedSpecs, ...adrSpecs];
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
logger.warning('No architectural decisions found for ADR generation');
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
logger.info('Total files to write', generatedSpecs.length);
|
|
506
|
+
logger.blank();
|
|
507
|
+
// Determine write mode
|
|
508
|
+
let writeMode = 'replace';
|
|
509
|
+
if (opts.merge) {
|
|
510
|
+
writeMode = 'merge';
|
|
511
|
+
}
|
|
512
|
+
else if (opts.noOverwrite) {
|
|
513
|
+
writeMode = 'skip';
|
|
514
|
+
}
|
|
515
|
+
// Write specs
|
|
516
|
+
const writer = new OpenSpecWriter({
|
|
517
|
+
rootPath,
|
|
518
|
+
writeMode,
|
|
519
|
+
version: specGenConfig.version,
|
|
520
|
+
createBackups: true,
|
|
521
|
+
updateConfig: true,
|
|
522
|
+
validateBeforeWrite: true,
|
|
523
|
+
});
|
|
524
|
+
let report;
|
|
525
|
+
try {
|
|
526
|
+
report = await writer.writeSpecs(generatedSpecs, pipelineResult.survey);
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
logger.error(`Failed to write specs: ${error.message}`);
|
|
530
|
+
process.exitCode = 1;
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
// Generate requirement→function mapping artifact if dep graph is available
|
|
534
|
+
if (depGraph) {
|
|
535
|
+
try {
|
|
536
|
+
// Wire semantic search if a vector index exists for this project
|
|
537
|
+
let semanticSearch;
|
|
538
|
+
const analysisDir = join(rootPath, '.spec-gen', 'analysis');
|
|
539
|
+
const { VectorIndex } = await import('../../core/analyzer/vector-index.js');
|
|
540
|
+
if (VectorIndex.exists(analysisDir)) {
|
|
541
|
+
const { EmbeddingService } = await import('../../core/analyzer/embedding-service.js');
|
|
542
|
+
let embedSvc;
|
|
543
|
+
try {
|
|
544
|
+
embedSvc = EmbeddingService.fromEnv();
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
const svc = EmbeddingService.fromConfig(specGenConfig);
|
|
548
|
+
if (svc)
|
|
549
|
+
embedSvc = svc;
|
|
550
|
+
}
|
|
551
|
+
if (embedSvc) {
|
|
552
|
+
const svc = embedSvc;
|
|
553
|
+
semanticSearch = (query, limit) => VectorIndex.search(analysisDir, query, svc, { limit });
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const mapper = new MappingGenerator(rootPath, specGenConfig.openspecPath, semanticSearch);
|
|
557
|
+
const mapping = await mapper.generate(pipelineResult, depGraph);
|
|
558
|
+
logger.success(`Requirement mapping: ${mapping.stats.mappedRequirements}/${mapping.stats.totalRequirements} requirements mapped, ${mapping.stats.orphanCount} orphan functions → .spec-gen/analysis/mapping.json`);
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
logger.warning(`Could not generate mapping artifact: ${error.message}`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
// ========================================================================
|
|
565
|
+
// PHASE 6: POST-GENERATION
|
|
566
|
+
// ========================================================================
|
|
567
|
+
logger.blank();
|
|
568
|
+
logger.section('Generation Complete');
|
|
569
|
+
const duration = Date.now() - startTime;
|
|
570
|
+
// Summary
|
|
571
|
+
console.log('');
|
|
572
|
+
if (report.filesWritten.length > 0) {
|
|
573
|
+
console.log(` ✓ ${report.filesWritten.length} spec(s) written`);
|
|
574
|
+
}
|
|
575
|
+
if (report.filesMerged.length > 0) {
|
|
576
|
+
console.log(` ✓ ${report.filesMerged.length} spec(s) merged`);
|
|
577
|
+
}
|
|
578
|
+
if (report.filesSkipped.length > 0) {
|
|
579
|
+
console.log(` ○ ${report.filesSkipped.length} spec(s) skipped (already exist)`);
|
|
580
|
+
}
|
|
581
|
+
if (report.filesBackedUp.length > 0) {
|
|
582
|
+
console.log(` ↩ ${report.filesBackedUp.length} backup(s) created`);
|
|
583
|
+
}
|
|
584
|
+
if (report.configUpdated) {
|
|
585
|
+
console.log(' ✓ config.yaml updated');
|
|
586
|
+
}
|
|
587
|
+
// Warnings
|
|
588
|
+
if (report.warnings.length > 0) {
|
|
589
|
+
console.log('');
|
|
590
|
+
console.log(' Warnings:');
|
|
591
|
+
for (const warning of report.warnings.slice(0, 5)) {
|
|
592
|
+
console.log(` ⚠ ${warning}`);
|
|
593
|
+
}
|
|
594
|
+
if (report.warnings.length > 5) {
|
|
595
|
+
console.log(` ... and ${report.warnings.length - 5} more`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
// Validation errors
|
|
599
|
+
if (report.validationErrors.length > 0) {
|
|
600
|
+
console.log('');
|
|
601
|
+
console.log(' Validation errors:');
|
|
602
|
+
for (const error of report.validationErrors.slice(0, 5)) {
|
|
603
|
+
console.log(` ✗ ${error}`);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
// Next steps
|
|
607
|
+
console.log('');
|
|
608
|
+
console.log(' Next steps:');
|
|
609
|
+
for (let i = 0; i < report.nextSteps.length; i++) {
|
|
610
|
+
console.log(` ${i + 1}. ${report.nextSteps[i]}`);
|
|
611
|
+
}
|
|
612
|
+
console.log('');
|
|
613
|
+
console.log(` Total time: ${formatDuration(duration)}`);
|
|
614
|
+
console.log(` Report saved to: .spec-gen/outputs/generation-report.json`);
|
|
615
|
+
console.log('');
|
|
616
|
+
// Save LLM logs
|
|
617
|
+
try {
|
|
618
|
+
await llm.saveLogs();
|
|
619
|
+
}
|
|
620
|
+
catch {
|
|
621
|
+
// Ignore log save errors
|
|
622
|
+
}
|
|
623
|
+
logger.success('Done!');
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
logger.error(`Generate failed: ${error.message}`);
|
|
627
|
+
if (process.env.DEBUG) {
|
|
628
|
+
console.error(error);
|
|
629
|
+
}
|
|
630
|
+
process.exitCode = 1;
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"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"}
|