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,540 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spec-gen drift command
|
|
3
|
+
*
|
|
4
|
+
* Detects spec drift: finds code changes not reflected in specs.
|
|
5
|
+
* Can be used standalone or as a pre-commit hook.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { access, mkdir, readFile, writeFile, chmod } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { logger } from '../../utils/logger.js';
|
|
11
|
+
import { readSpecGenConfig } from '../../core/services/config-manager.js';
|
|
12
|
+
import { getChangedFiles, isGitRepository, buildSpecMap, buildADRMap, detectDrift, } from '../../core/drift/index.js';
|
|
13
|
+
import { createLLMService } from '../../core/services/llm-service.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// TYPES
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// DriftOptions (extends GlobalOptions) already has all fields including verbose
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// HELPER FUNCTIONS
|
|
20
|
+
// ============================================================================
|
|
21
|
+
function parseList(value) {
|
|
22
|
+
return value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
23
|
+
}
|
|
24
|
+
async function fileExists(path) {
|
|
25
|
+
try {
|
|
26
|
+
await access(path);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function formatDuration(ms) {
|
|
34
|
+
if (ms < 1000)
|
|
35
|
+
return `${ms}ms`;
|
|
36
|
+
if (ms < 60000)
|
|
37
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
38
|
+
const minutes = Math.floor(ms / 60000);
|
|
39
|
+
const seconds = Math.floor((ms % 60000) / 1000);
|
|
40
|
+
return `${minutes}m ${seconds}s`;
|
|
41
|
+
}
|
|
42
|
+
function severityLabel(severity) {
|
|
43
|
+
switch (severity) {
|
|
44
|
+
case 'error': return 'ERROR';
|
|
45
|
+
case 'warning': return 'WARNING';
|
|
46
|
+
case 'info': return 'INFO';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function severityIcon(severity) {
|
|
50
|
+
switch (severity) {
|
|
51
|
+
case 'error': return '✗';
|
|
52
|
+
case 'warning': return '⚠';
|
|
53
|
+
case 'info': return '→';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function kindLabel(kind) {
|
|
57
|
+
switch (kind) {
|
|
58
|
+
case 'gap': return 'gap';
|
|
59
|
+
case 'stale': return 'stale';
|
|
60
|
+
case 'uncovered': return 'uncovered';
|
|
61
|
+
case 'orphaned-spec': return 'orphaned';
|
|
62
|
+
case 'adr-gap': return 'adr-gap';
|
|
63
|
+
case 'adr-orphaned': return 'adr-orphaned';
|
|
64
|
+
default: return kind;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function displayIssue(issue, verbose) {
|
|
68
|
+
const icon = severityIcon(issue.severity);
|
|
69
|
+
const sev = severityLabel(issue.severity);
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(` ${icon} [${sev}] ${kindLabel(issue.kind)}: ${issue.filePath}`);
|
|
72
|
+
if (issue.domain) {
|
|
73
|
+
console.log(` Spec: ${issue.specPath ?? issue.domain}`);
|
|
74
|
+
}
|
|
75
|
+
if (verbose || issue.severity === 'error') {
|
|
76
|
+
console.log(` ${issue.message}`);
|
|
77
|
+
}
|
|
78
|
+
if (issue.changedLines) {
|
|
79
|
+
console.log(` +${issue.changedLines.added}/-${issue.changedLines.removed} lines`);
|
|
80
|
+
}
|
|
81
|
+
console.log(` -> ${issue.suggestion}`);
|
|
82
|
+
}
|
|
83
|
+
function displaySummary(result) {
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(' ──────────────────────────────────────');
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log(' Summary:');
|
|
88
|
+
const parts = [];
|
|
89
|
+
if (result.summary.gaps > 0)
|
|
90
|
+
parts.push(`Gaps: ${result.summary.gaps}`);
|
|
91
|
+
if (result.summary.stale > 0)
|
|
92
|
+
parts.push(`Stale: ${result.summary.stale}`);
|
|
93
|
+
if (result.summary.uncovered > 0)
|
|
94
|
+
parts.push(`Uncovered: ${result.summary.uncovered}`);
|
|
95
|
+
if (result.summary.orphanedSpecs > 0)
|
|
96
|
+
parts.push(`Orphaned: ${result.summary.orphanedSpecs}`);
|
|
97
|
+
if (result.summary.adrGaps > 0)
|
|
98
|
+
parts.push(`ADR gaps: ${result.summary.adrGaps}`);
|
|
99
|
+
if (result.summary.adrOrphaned > 0)
|
|
100
|
+
parts.push(`ADR orphaned: ${result.summary.adrOrphaned}`);
|
|
101
|
+
if (parts.length === 0) {
|
|
102
|
+
console.log(' No issues found');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
for (const part of parts) {
|
|
106
|
+
console.log(` ${part}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
console.log('');
|
|
110
|
+
}
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// HOOK MANAGEMENT
|
|
113
|
+
// ============================================================================
|
|
114
|
+
const HOOK_MARKER = '# spec-gen-drift-hook';
|
|
115
|
+
const HOOK_CONTENT = `
|
|
116
|
+
${HOOK_MARKER}
|
|
117
|
+
# Automatically check for spec drift before committing
|
|
118
|
+
# Installed by: spec-gen drift --install-hook
|
|
119
|
+
|
|
120
|
+
# Run spec-gen drift in static mode (fast, no LLM)
|
|
121
|
+
# Use --json for machine-parseable output, suppress only npx banner noise
|
|
122
|
+
DRIFT_OUTPUT=$(npx --yes spec-gen drift --fail-on warning --json 2>/dev/null)
|
|
123
|
+
DRIFT_EXIT=$?
|
|
124
|
+
|
|
125
|
+
if [ $DRIFT_EXIT -ne 0 ]; then
|
|
126
|
+
echo ""
|
|
127
|
+
echo "spec-gen: Spec drift detected! Commit blocked."
|
|
128
|
+
echo ""
|
|
129
|
+
# Show concise summary from JSON output
|
|
130
|
+
if command -v python3 > /dev/null 2>&1; then
|
|
131
|
+
echo "$DRIFT_OUTPUT" | python3 -c "
|
|
132
|
+
import sys, json
|
|
133
|
+
try:
|
|
134
|
+
d = json.load(sys.stdin)
|
|
135
|
+
s = d.get('summary', {})
|
|
136
|
+
parts = []
|
|
137
|
+
if s.get('gaps', 0): parts.append(str(s['gaps']) + ' gap(s)')
|
|
138
|
+
if s.get('stale', 0): parts.append(str(s['stale']) + ' stale')
|
|
139
|
+
if s.get('uncovered', 0): parts.append(str(s['uncovered']) + ' uncovered')
|
|
140
|
+
if s.get('orphanedSpecs', 0): parts.append(str(s['orphanedSpecs']) + ' orphaned')
|
|
141
|
+
print(' Issues: ' + ', '.join(parts))
|
|
142
|
+
for i in d.get('issues', [])[:5]:
|
|
143
|
+
sev = i['severity'].upper()
|
|
144
|
+
print(' [' + sev + '] ' + i['kind'] + ': ' + i['filePath'])
|
|
145
|
+
if len(d.get('issues', [])) > 5:
|
|
146
|
+
print(' ... and ' + str(len(d['issues']) - 5) + ' more')
|
|
147
|
+
except: pass
|
|
148
|
+
" 2>/dev/null
|
|
149
|
+
else
|
|
150
|
+
echo " (Install python3 for detailed issue summary in hook output)"
|
|
151
|
+
fi
|
|
152
|
+
echo ""
|
|
153
|
+
echo " Run 'spec-gen drift' for full details."
|
|
154
|
+
echo " To skip this check: git commit --no-verify"
|
|
155
|
+
echo ""
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
158
|
+
# end-spec-gen-drift-hook
|
|
159
|
+
`.trimStart();
|
|
160
|
+
async function installPreCommitHook(rootPath) {
|
|
161
|
+
const hooksDir = join(rootPath, '.git', 'hooks');
|
|
162
|
+
const hookPath = join(hooksDir, 'pre-commit');
|
|
163
|
+
if (!(await fileExists(join(rootPath, '.git')))) {
|
|
164
|
+
logger.error('Not a git repository. Cannot install hook.');
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Ensure hooks directory exists (may not in bare clones or some CI setups)
|
|
169
|
+
await mkdir(hooksDir, { recursive: true });
|
|
170
|
+
// Check if hook already exists
|
|
171
|
+
let existingContent = '';
|
|
172
|
+
if (await fileExists(hookPath)) {
|
|
173
|
+
existingContent = await readFile(hookPath, 'utf-8');
|
|
174
|
+
if (existingContent.includes(HOOK_MARKER)) {
|
|
175
|
+
logger.success('Pre-commit hook is already installed.');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Append to existing hook
|
|
179
|
+
logger.discovery('Existing pre-commit hook found. Appending spec-gen drift check.');
|
|
180
|
+
const newContent = existingContent.trimEnd() + '\n\n' + HOOK_CONTENT;
|
|
181
|
+
await writeFile(hookPath, newContent, 'utf-8');
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Create new hook
|
|
185
|
+
const newContent = '#!/bin/sh\n\n' + HOOK_CONTENT;
|
|
186
|
+
await writeFile(hookPath, newContent, 'utf-8');
|
|
187
|
+
}
|
|
188
|
+
await chmod(hookPath, 0o755);
|
|
189
|
+
logger.success('Pre-commit hook installed at .git/hooks/pre-commit');
|
|
190
|
+
logger.discovery('Drift will be checked before each commit. Use --no-verify to skip.');
|
|
191
|
+
}
|
|
192
|
+
async function uninstallPreCommitHook(rootPath) {
|
|
193
|
+
const hookPath = join(rootPath, '.git', 'hooks', 'pre-commit');
|
|
194
|
+
if (!(await fileExists(hookPath))) {
|
|
195
|
+
logger.warning('No pre-commit hook found.');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const content = await readFile(hookPath, 'utf-8');
|
|
199
|
+
if (!content.includes(HOOK_MARKER)) {
|
|
200
|
+
logger.warning('Pre-commit hook does not contain spec-gen drift check.');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// Remove the spec-gen block
|
|
204
|
+
const newContent = content
|
|
205
|
+
.replace(/\n*# spec-gen-drift-hook[\s\S]*?# end-spec-gen-drift-hook\n*/g, '')
|
|
206
|
+
.trim();
|
|
207
|
+
if (!newContent || newContent === '#!/bin/sh') {
|
|
208
|
+
// Hook file is now empty — remove the shebang-only file
|
|
209
|
+
const { unlink } = await import('node:fs/promises');
|
|
210
|
+
await unlink(hookPath);
|
|
211
|
+
logger.success('Pre-commit hook removed (file deleted — was only spec-gen).');
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
await writeFile(hookPath, newContent + '\n', 'utf-8');
|
|
215
|
+
logger.success('Spec-gen drift check removed from pre-commit hook.');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// ============================================================================
|
|
219
|
+
// COMMAND
|
|
220
|
+
// ============================================================================
|
|
221
|
+
export const driftCommand = new Command('drift')
|
|
222
|
+
.description('Detect spec drift: find code changes not reflected in specs')
|
|
223
|
+
.option('--base <ref>', 'Git ref to compare against (default: auto-detect main/master)', 'auto')
|
|
224
|
+
.option('--files <paths>', 'Specific files to check (comma-separated)', parseList)
|
|
225
|
+
.option('--domains <list>', 'Only check specific domains', parseList)
|
|
226
|
+
.option('--use-llm', 'Use LLM for deeper semantic comparison (slower)', false)
|
|
227
|
+
.option('--json', 'Output results as JSON only', false)
|
|
228
|
+
.option('--install-hook', 'Install pre-commit hook for drift detection', false)
|
|
229
|
+
.option('--uninstall-hook', 'Remove pre-commit hook', false)
|
|
230
|
+
.option('--fail-on <severity>', 'Exit non-zero on issues at this severity or above (error, warning, info)', 'warning')
|
|
231
|
+
.option('--max-files <n>', 'Maximum changed files to analyze', '100')
|
|
232
|
+
.option('--verbose', 'Show detailed issue information', false)
|
|
233
|
+
.addHelpText('after', `
|
|
234
|
+
Examples:
|
|
235
|
+
$ spec-gen drift Check for drift against main branch
|
|
236
|
+
$ spec-gen drift --base develop Compare against develop branch
|
|
237
|
+
$ spec-gen drift --json Output JSON for CI integration
|
|
238
|
+
$ spec-gen drift --fail-on error Only fail on error-level drift
|
|
239
|
+
$ spec-gen drift --use-llm Use LLM for semantic analysis
|
|
240
|
+
$ spec-gen drift --install-hook Install as pre-commit hook
|
|
241
|
+
$ spec-gen drift --uninstall-hook Remove pre-commit hook
|
|
242
|
+
|
|
243
|
+
Drift categories:
|
|
244
|
+
gap: Code changed but spec not updated
|
|
245
|
+
stale: Spec references deleted/heavily modified code
|
|
246
|
+
uncovered: New files with no matching spec
|
|
247
|
+
orphaned-spec: Spec references non-existent files
|
|
248
|
+
|
|
249
|
+
Pre-commit hook:
|
|
250
|
+
Install with --install-hook to automatically check for drift
|
|
251
|
+
before each commit. The hook runs in static mode (no LLM)
|
|
252
|
+
for fast execution.
|
|
253
|
+
`)
|
|
254
|
+
.action(async function (options) {
|
|
255
|
+
const startTime = Date.now();
|
|
256
|
+
const rootPath = process.cwd();
|
|
257
|
+
// Inherit global options from parent command (--quiet, --verbose, --no-color, --config)
|
|
258
|
+
const globalOpts = this.optsWithGlobals?.() ?? {};
|
|
259
|
+
// Normalize options
|
|
260
|
+
const opts = {
|
|
261
|
+
base: typeof options.base === 'string' ? options.base : 'auto',
|
|
262
|
+
files: options.files ?? [],
|
|
263
|
+
domains: options.domains ?? [],
|
|
264
|
+
useLlm: options.useLlm ?? false,
|
|
265
|
+
json: options.json ?? false,
|
|
266
|
+
installHook: options.installHook ?? false,
|
|
267
|
+
uninstallHook: options.uninstallHook ?? false,
|
|
268
|
+
failOn: options.failOn ?? 'warning',
|
|
269
|
+
maxFiles: (() => {
|
|
270
|
+
// Commander routes --max-files to parent when both parent and subcommand define it.
|
|
271
|
+
// Check globalOpts first for the user-provided value, fall back to subcommand default.
|
|
272
|
+
const raw = globalOpts.maxFiles ?? options.maxFiles ?? '100';
|
|
273
|
+
return typeof raw === 'string' ? parseInt(raw, 10) : raw;
|
|
274
|
+
})(),
|
|
275
|
+
verbose: options.verbose ?? globalOpts.verbose ?? false,
|
|
276
|
+
quiet: globalOpts.quiet ?? false,
|
|
277
|
+
noColor: globalOpts.color === false,
|
|
278
|
+
config: globalOpts.config ?? '.spec-gen/config.json',
|
|
279
|
+
};
|
|
280
|
+
// Validate failOn
|
|
281
|
+
if (!['error', 'warning', 'info'].includes(opts.failOn)) {
|
|
282
|
+
logger.error('--fail-on must be one of: error, warning, info');
|
|
283
|
+
process.exitCode = 1;
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
// ========================================================================
|
|
288
|
+
// PHASE 0: HOOK MANAGEMENT (early return)
|
|
289
|
+
// ========================================================================
|
|
290
|
+
if (opts.installHook) {
|
|
291
|
+
await installPreCommitHook(rootPath);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (opts.uninstallHook) {
|
|
295
|
+
await uninstallPreCommitHook(rootPath);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// ========================================================================
|
|
299
|
+
// PHASE 1: VALIDATION
|
|
300
|
+
// ========================================================================
|
|
301
|
+
if (!opts.json) {
|
|
302
|
+
logger.section('Spec Drift Detection');
|
|
303
|
+
}
|
|
304
|
+
// Check git repo
|
|
305
|
+
if (!(await isGitRepository(rootPath))) {
|
|
306
|
+
logger.error('Not a git repository. Drift detection requires git.');
|
|
307
|
+
process.exitCode = 1;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
// Load spec-gen config
|
|
311
|
+
const specGenConfig = await readSpecGenConfig(rootPath);
|
|
312
|
+
if (!specGenConfig) {
|
|
313
|
+
logger.error('No spec-gen configuration found. Run "spec-gen init" first.');
|
|
314
|
+
process.exitCode = 1;
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
// Create LLM service if --use-llm is specified
|
|
318
|
+
let llm;
|
|
319
|
+
if (opts.useLlm) {
|
|
320
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
321
|
+
const openaiKey = process.env.OPENAI_API_KEY;
|
|
322
|
+
if (!anthropicKey && !openaiKey) {
|
|
323
|
+
logger.error('No LLM API key found. --use-llm requires an API key.');
|
|
324
|
+
logger.discovery('Set ANTHROPIC_API_KEY or OPENAI_API_KEY environment variable.');
|
|
325
|
+
logger.discovery(' export ANTHROPIC_API_KEY=sk-ant-...');
|
|
326
|
+
logger.discovery(' export OPENAI_API_KEY=sk-...');
|
|
327
|
+
process.exitCode = 1;
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const provider = anthropicKey ? 'anthropic' : 'openai';
|
|
331
|
+
try {
|
|
332
|
+
llm = createLLMService({
|
|
333
|
+
provider,
|
|
334
|
+
apiBase: globalOpts.apiBase ?? specGenConfig.llm?.apiBase,
|
|
335
|
+
sslVerify: globalOpts.insecure != null ? !globalOpts.insecure : specGenConfig.llm?.sslVerify ?? true,
|
|
336
|
+
enableLogging: true,
|
|
337
|
+
logDir: join(rootPath, '.spec-gen', 'logs'),
|
|
338
|
+
});
|
|
339
|
+
if (!opts.json) {
|
|
340
|
+
logger.discovery(`LLM enabled (${provider}) — gap issues will be semantically analyzed`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
logger.error(`Failed to create LLM service: ${error.message}`);
|
|
345
|
+
process.exitCode = 1;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Determine openspec path
|
|
350
|
+
const openspecPath = join(rootPath, specGenConfig.openspecPath ?? 'openspec');
|
|
351
|
+
const specsPath = join(openspecPath, 'specs');
|
|
352
|
+
// Check if specs exist
|
|
353
|
+
if (!(await fileExists(specsPath))) {
|
|
354
|
+
logger.error('No specs found. Run "spec-gen generate" first.');
|
|
355
|
+
process.exitCode = 1;
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
// ========================================================================
|
|
359
|
+
// PHASE 2: GIT DELTA
|
|
360
|
+
// ========================================================================
|
|
361
|
+
if (!opts.json) {
|
|
362
|
+
logger.discovery('Analyzing git changes...');
|
|
363
|
+
}
|
|
364
|
+
const gitResult = await getChangedFiles({
|
|
365
|
+
rootPath,
|
|
366
|
+
baseRef: opts.base,
|
|
367
|
+
pathFilter: opts.files.length > 0 ? opts.files : undefined,
|
|
368
|
+
includeUnstaged: true,
|
|
369
|
+
});
|
|
370
|
+
if (!opts.json) {
|
|
371
|
+
logger.info('Base ref', `${gitResult.resolvedBase}`);
|
|
372
|
+
logger.info('Branch', gitResult.currentBranch);
|
|
373
|
+
logger.info('Changed files', gitResult.files.length);
|
|
374
|
+
logger.blank();
|
|
375
|
+
}
|
|
376
|
+
if (gitResult.files.length === 0) {
|
|
377
|
+
if (opts.json) {
|
|
378
|
+
const emptyResult = {
|
|
379
|
+
timestamp: new Date().toISOString(),
|
|
380
|
+
baseRef: gitResult.resolvedBase,
|
|
381
|
+
totalChangedFiles: 0,
|
|
382
|
+
specRelevantFiles: 0,
|
|
383
|
+
issues: [],
|
|
384
|
+
summary: { gaps: 0, stale: 0, uncovered: 0, orphanedSpecs: 0, adrGaps: 0, adrOrphaned: 0, total: 0 },
|
|
385
|
+
hasDrift: false,
|
|
386
|
+
duration: Date.now() - startTime,
|
|
387
|
+
mode: 'static',
|
|
388
|
+
};
|
|
389
|
+
console.log(JSON.stringify(emptyResult, null, 2));
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
logger.success('No changes detected. Specs are up to date.');
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
// Apply max-files limit
|
|
397
|
+
const actualChangedFiles = gitResult.files.length;
|
|
398
|
+
if (gitResult.files.length > opts.maxFiles) {
|
|
399
|
+
if (!opts.json) {
|
|
400
|
+
logger.warning(`Analyzing first ${opts.maxFiles} of ${gitResult.files.length} changed files. Use --max-files to increase.`);
|
|
401
|
+
}
|
|
402
|
+
gitResult.files = gitResult.files.slice(0, opts.maxFiles);
|
|
403
|
+
}
|
|
404
|
+
// ========================================================================
|
|
405
|
+
// PHASE 3: SPEC MAPPING
|
|
406
|
+
// ========================================================================
|
|
407
|
+
if (!opts.json) {
|
|
408
|
+
logger.discovery('Loading spec mappings...');
|
|
409
|
+
}
|
|
410
|
+
// Check for repo-structure.json for enhanced mapping
|
|
411
|
+
const repoStructurePath = join(rootPath, '.spec-gen', 'analysis', 'repo-structure.json');
|
|
412
|
+
const hasRepoStructure = await fileExists(repoStructurePath);
|
|
413
|
+
if (!hasRepoStructure && !opts.json) {
|
|
414
|
+
logger.debug('No prior analysis found. Using spec headers only for file mapping. Run "spec-gen analyze" for better detection.');
|
|
415
|
+
}
|
|
416
|
+
const specMap = await buildSpecMap({
|
|
417
|
+
rootPath,
|
|
418
|
+
openspecPath,
|
|
419
|
+
repoStructurePath: hasRepoStructure ? repoStructurePath : undefined,
|
|
420
|
+
});
|
|
421
|
+
// Build ADR map (if decisions directory exists)
|
|
422
|
+
const adrMap = await buildADRMap({
|
|
423
|
+
rootPath,
|
|
424
|
+
openspecPath,
|
|
425
|
+
repoStructurePath: hasRepoStructure ? repoStructurePath : undefined,
|
|
426
|
+
});
|
|
427
|
+
if (!opts.json) {
|
|
428
|
+
logger.info('Spec domains', specMap.domainCount);
|
|
429
|
+
logger.info('Mapped source files', specMap.totalMappedFiles);
|
|
430
|
+
if (adrMap) {
|
|
431
|
+
logger.info('ADRs tracked', adrMap.byId.size);
|
|
432
|
+
}
|
|
433
|
+
logger.blank();
|
|
434
|
+
}
|
|
435
|
+
// ========================================================================
|
|
436
|
+
// PHASE 4: DRIFT DETECTION
|
|
437
|
+
// ========================================================================
|
|
438
|
+
if (!opts.json) {
|
|
439
|
+
logger.analysis('Detecting drift...');
|
|
440
|
+
}
|
|
441
|
+
const result = await detectDrift({
|
|
442
|
+
rootPath,
|
|
443
|
+
specMap,
|
|
444
|
+
changedFiles: gitResult.files,
|
|
445
|
+
failOn: opts.failOn,
|
|
446
|
+
domainFilter: opts.domains.length > 0 ? opts.domains : undefined,
|
|
447
|
+
openspecRelPath: specGenConfig.openspecPath ?? 'openspec',
|
|
448
|
+
llm,
|
|
449
|
+
baseRef: gitResult.resolvedBase,
|
|
450
|
+
adrMap: adrMap ?? undefined,
|
|
451
|
+
});
|
|
452
|
+
// Fill in the base ref and actual total count (before --max-files truncation)
|
|
453
|
+
result.baseRef = gitResult.resolvedBase;
|
|
454
|
+
result.totalChangedFiles = actualChangedFiles;
|
|
455
|
+
// ========================================================================
|
|
456
|
+
// PHASE 5: DISPLAY RESULTS
|
|
457
|
+
// ========================================================================
|
|
458
|
+
if (opts.json) {
|
|
459
|
+
console.log(JSON.stringify(result, null, 2));
|
|
460
|
+
}
|
|
461
|
+
else if (opts.quiet) {
|
|
462
|
+
// Quiet mode: only show the final pass/fail line
|
|
463
|
+
if (result.hasDrift) {
|
|
464
|
+
const errorCount = result.issues.filter(i => i.severity === 'error').length;
|
|
465
|
+
const warnCount = result.issues.filter(i => i.severity === 'warning').length;
|
|
466
|
+
const infoCount = result.issues.filter(i => i.severity === 'info').length;
|
|
467
|
+
const parts = [];
|
|
468
|
+
if (errorCount > 0)
|
|
469
|
+
parts.push(`${errorCount} error${errorCount > 1 ? 's' : ''}`);
|
|
470
|
+
if (warnCount > 0)
|
|
471
|
+
parts.push(`${warnCount} warning${warnCount > 1 ? 's' : ''}`);
|
|
472
|
+
if (infoCount > 0 && errorCount === 0 && warnCount === 0)
|
|
473
|
+
parts.push(`${infoCount} info`);
|
|
474
|
+
logger.error(`Drift detected: ${parts.join(', ')}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
if (result.issues.length === 0) {
|
|
479
|
+
logger.blank();
|
|
480
|
+
logger.success('No spec drift detected. Specs are in sync with code changes.');
|
|
481
|
+
const duration = Date.now() - startTime;
|
|
482
|
+
logger.info('Duration', formatDuration(duration));
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
console.log('');
|
|
486
|
+
console.log(` Issues Found: ${result.summary.total}`);
|
|
487
|
+
for (const issue of result.issues) {
|
|
488
|
+
displayIssue(issue, opts.verbose ?? false);
|
|
489
|
+
}
|
|
490
|
+
displaySummary(result);
|
|
491
|
+
const duration = Date.now() - startTime;
|
|
492
|
+
logger.info('Duration', formatDuration(duration));
|
|
493
|
+
logger.blank();
|
|
494
|
+
if (result.hasDrift) {
|
|
495
|
+
const errorCount = result.issues.filter(i => i.severity === 'error').length;
|
|
496
|
+
const warnCount = result.issues.filter(i => i.severity === 'warning').length;
|
|
497
|
+
const infoCount = result.issues.filter(i => i.severity === 'info').length;
|
|
498
|
+
const parts = [];
|
|
499
|
+
if (errorCount > 0)
|
|
500
|
+
parts.push(`${errorCount} error${errorCount > 1 ? 's' : ''}`);
|
|
501
|
+
if (warnCount > 0)
|
|
502
|
+
parts.push(`${warnCount} warning${warnCount > 1 ? 's' : ''}`);
|
|
503
|
+
if (infoCount > 0 && errorCount === 0 && warnCount === 0)
|
|
504
|
+
parts.push(`${infoCount} info`);
|
|
505
|
+
logger.error(`Drift detected: ${parts.join(', ')}`);
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
logger.success('No drift above threshold. Specs are acceptable.');
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// Show LLM usage stats if applicable
|
|
513
|
+
if (llm) {
|
|
514
|
+
const usage = llm.getTokenUsage();
|
|
515
|
+
if (!opts.json && usage.requests > 0) {
|
|
516
|
+
logger.blank();
|
|
517
|
+
logger.info('LLM calls', usage.requests);
|
|
518
|
+
logger.info('Tokens used', `${usage.totalTokens} (in: ${usage.inputTokens}, out: ${usage.outputTokens})`);
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
await llm.saveLogs();
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
// Non-fatal — log saving is best-effort
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
// Set exit code based on drift detection
|
|
528
|
+
if (result.hasDrift) {
|
|
529
|
+
process.exitCode = 1;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch (error) {
|
|
533
|
+
logger.error(`Drift detection failed: ${error.message}`);
|
|
534
|
+
if (process.env.DEBUG) {
|
|
535
|
+
console.error(error);
|
|
536
|
+
}
|
|
537
|
+
process.exitCode = 1;
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
//# sourceMappingURL=drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../../src/cli/commands/drift.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
export declare const generateCommand: Command;
|
|
9
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgOpC,eAAO,MAAM,eAAe,SAuiBxB,CAAC"}
|