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,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenSpec Compatibility Layer
|
|
3
|
+
*
|
|
4
|
+
* Ensures perfect compatibility with OpenSpec's tooling and conventions.
|
|
5
|
+
* Handles config.yaml integration, validation, and context injection.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile, mkdir, access, readdir } from 'node:fs/promises';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
|
10
|
+
import logger from '../../utils/logger.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// OPENSPEC VALIDATION
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* OpenSpec validator for specs and configuration
|
|
16
|
+
*/
|
|
17
|
+
export class OpenSpecValidator {
|
|
18
|
+
/**
|
|
19
|
+
* Validate the complete spec structure
|
|
20
|
+
*/
|
|
21
|
+
validateSpecStructure(content) {
|
|
22
|
+
const errors = [];
|
|
23
|
+
const warnings = [];
|
|
24
|
+
// Check for title (# heading at start)
|
|
25
|
+
if (!content.match(/^#\s+.+/m)) {
|
|
26
|
+
errors.push('Missing title (# heading)');
|
|
27
|
+
}
|
|
28
|
+
// Check for Purpose section
|
|
29
|
+
if (!content.includes('## Purpose')) {
|
|
30
|
+
warnings.push('Missing Purpose section (recommended)');
|
|
31
|
+
}
|
|
32
|
+
// Check for Requirements section (except overview which may have Domains instead)
|
|
33
|
+
if (!content.includes('## Requirements') && !content.includes('## Domains') && !content.includes('## Key Capabilities')) {
|
|
34
|
+
warnings.push('Missing Requirements section');
|
|
35
|
+
}
|
|
36
|
+
// Check for delta markers (should not be in generated specs)
|
|
37
|
+
if (content.match(/\[ADDED\]|\[MODIFIED\]|\[REMOVED\]/)) {
|
|
38
|
+
errors.push('Generated specs should not contain delta markers ([ADDED], [MODIFIED], [REMOVED])');
|
|
39
|
+
}
|
|
40
|
+
// Check markdown structure is valid
|
|
41
|
+
const headingLevels = this.checkHeadingHierarchy(content);
|
|
42
|
+
if (!headingLevels.valid) {
|
|
43
|
+
warnings.push(...headingLevels.issues);
|
|
44
|
+
}
|
|
45
|
+
// Check for broken links
|
|
46
|
+
const brokenLinks = this.checkMarkdownLinks(content);
|
|
47
|
+
if (brokenLinks.length > 0) {
|
|
48
|
+
warnings.push(...brokenLinks.map(link => `Potentially malformed link: ${link}`));
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
valid: errors.length === 0,
|
|
52
|
+
errors,
|
|
53
|
+
warnings,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate requirement format follows RFC 2119
|
|
58
|
+
*/
|
|
59
|
+
validateRequirementFormat(requirement) {
|
|
60
|
+
const errors = [];
|
|
61
|
+
const warnings = [];
|
|
62
|
+
// Check for RFC 2119 keywords
|
|
63
|
+
const rfc2119Keywords = /\b(SHALL|MUST|SHOULD|MAY|SHALL NOT|MUST NOT|SHOULD NOT|MAY NOT)\b/;
|
|
64
|
+
if (!rfc2119Keywords.test(requirement)) {
|
|
65
|
+
warnings.push('Requirement does not use RFC 2119 keywords (SHALL, MUST, SHOULD, MAY)');
|
|
66
|
+
}
|
|
67
|
+
// Check for imperative form
|
|
68
|
+
if (requirement.match(/^The system\s+/i) === null && requirement.match(/^The\s+\w+\s+(SHALL|MUST|SHOULD|MAY)/i) === null) {
|
|
69
|
+
warnings.push('Requirement should start with "The system" or "The [component]"');
|
|
70
|
+
}
|
|
71
|
+
// Check it's not too short (likely incomplete)
|
|
72
|
+
if (requirement.split(/\s+/).length < 5) {
|
|
73
|
+
warnings.push('Requirement may be too brief');
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
valid: errors.length === 0,
|
|
77
|
+
errors,
|
|
78
|
+
warnings,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validate scenario format (Given/When/Then)
|
|
83
|
+
*/
|
|
84
|
+
validateScenarioFormat(scenario) {
|
|
85
|
+
const errors = [];
|
|
86
|
+
const warnings = [];
|
|
87
|
+
// Check for scenario heading with exactly 4 hashtags
|
|
88
|
+
if (!scenario.match(/^####\s+Scenario:/m)) {
|
|
89
|
+
errors.push('Scenario heading must use exactly 4 hashtags (####)');
|
|
90
|
+
}
|
|
91
|
+
// Check for GIVEN
|
|
92
|
+
if (!scenario.includes('**GIVEN**') && !scenario.includes('- **GIVEN**')) {
|
|
93
|
+
errors.push('Scenario missing GIVEN clause');
|
|
94
|
+
}
|
|
95
|
+
// Check for WHEN
|
|
96
|
+
if (!scenario.includes('**WHEN**') && !scenario.includes('- **WHEN**')) {
|
|
97
|
+
errors.push('Scenario missing WHEN clause');
|
|
98
|
+
}
|
|
99
|
+
// Check for THEN
|
|
100
|
+
if (!scenario.includes('**THEN**') && !scenario.includes('- **THEN**')) {
|
|
101
|
+
errors.push('Scenario missing THEN clause');
|
|
102
|
+
}
|
|
103
|
+
// AND is optional but if present should be formatted correctly
|
|
104
|
+
if (scenario.includes('AND') && !scenario.match(/\*\*AND\*\*/)) {
|
|
105
|
+
warnings.push('AND clause should be bolded (**AND**)');
|
|
106
|
+
}
|
|
107
|
+
// Check order: GIVEN should come before WHEN, WHEN before THEN
|
|
108
|
+
const givenIndex = scenario.indexOf('**GIVEN**');
|
|
109
|
+
const whenIndex = scenario.indexOf('**WHEN**');
|
|
110
|
+
const thenIndex = scenario.indexOf('**THEN**');
|
|
111
|
+
if (givenIndex !== -1 && whenIndex !== -1 && givenIndex > whenIndex) {
|
|
112
|
+
errors.push('GIVEN must come before WHEN');
|
|
113
|
+
}
|
|
114
|
+
if (whenIndex !== -1 && thenIndex !== -1 && whenIndex > thenIndex) {
|
|
115
|
+
errors.push('WHEN must come before THEN');
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
valid: errors.length === 0,
|
|
119
|
+
errors,
|
|
120
|
+
warnings,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate config.yaml structure
|
|
125
|
+
*/
|
|
126
|
+
validateConfigYaml(config) {
|
|
127
|
+
const errors = [];
|
|
128
|
+
const warnings = [];
|
|
129
|
+
if (typeof config !== 'object' || config === null) {
|
|
130
|
+
errors.push('Config must be an object');
|
|
131
|
+
return { valid: false, errors, warnings };
|
|
132
|
+
}
|
|
133
|
+
const configObj = config;
|
|
134
|
+
// Check schema field
|
|
135
|
+
if (configObj.schema !== undefined && typeof configObj.schema !== 'string') {
|
|
136
|
+
errors.push('schema must be a string');
|
|
137
|
+
}
|
|
138
|
+
// Check context field
|
|
139
|
+
if (configObj.context !== undefined && typeof configObj.context !== 'string') {
|
|
140
|
+
errors.push('context must be a string');
|
|
141
|
+
}
|
|
142
|
+
// Check rules field
|
|
143
|
+
if (configObj.rules !== undefined) {
|
|
144
|
+
if (typeof configObj.rules !== 'object' || configObj.rules === null) {
|
|
145
|
+
errors.push('rules must be an object');
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const rules = configObj.rules;
|
|
149
|
+
const allowedRuleKeys = ['proposal', 'specs', 'design', 'tasks'];
|
|
150
|
+
for (const key of Object.keys(rules)) {
|
|
151
|
+
if (!allowedRuleKeys.includes(key)) {
|
|
152
|
+
warnings.push(`Unknown rule key: ${key}`);
|
|
153
|
+
}
|
|
154
|
+
if (!Array.isArray(rules[key])) {
|
|
155
|
+
errors.push(`rules.${key} must be an array`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Check spec-gen metadata if present
|
|
161
|
+
if (configObj['spec-gen'] !== undefined) {
|
|
162
|
+
const specGen = configObj['spec-gen'];
|
|
163
|
+
if (typeof specGen.version !== 'string') {
|
|
164
|
+
warnings.push('spec-gen.version should be a string');
|
|
165
|
+
}
|
|
166
|
+
if (typeof specGen.generatedAt !== 'string') {
|
|
167
|
+
warnings.push('spec-gen.generatedAt should be a string');
|
|
168
|
+
}
|
|
169
|
+
if (!Array.isArray(specGen.domains)) {
|
|
170
|
+
warnings.push('spec-gen.domains should be an array');
|
|
171
|
+
}
|
|
172
|
+
if (typeof specGen.confidence !== 'number') {
|
|
173
|
+
warnings.push('spec-gen.confidence should be a number');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
valid: errors.length === 0,
|
|
178
|
+
errors,
|
|
179
|
+
warnings,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check heading hierarchy is valid (no skipped levels)
|
|
184
|
+
*/
|
|
185
|
+
checkHeadingHierarchy(content) {
|
|
186
|
+
const issues = [];
|
|
187
|
+
const headings = content.match(/^#{1,6}\s+.+/gm) || [];
|
|
188
|
+
let lastLevel = 0;
|
|
189
|
+
for (const heading of headings) {
|
|
190
|
+
const match = heading.match(/^(#{1,6})/);
|
|
191
|
+
if (match) {
|
|
192
|
+
const level = match[1].length;
|
|
193
|
+
if (level > lastLevel + 1 && lastLevel !== 0) {
|
|
194
|
+
issues.push(`Heading level jumped from ${lastLevel} to ${level}: "${heading.slice(0, 50)}..."`);
|
|
195
|
+
}
|
|
196
|
+
lastLevel = level;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { valid: issues.length === 0, issues };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check for malformed markdown links
|
|
203
|
+
*/
|
|
204
|
+
checkMarkdownLinks(content) {
|
|
205
|
+
const malformed = [];
|
|
206
|
+
// Find all markdown links
|
|
207
|
+
const linkPattern = /\[([^\]]*)\]\(([^)]*)\)/g;
|
|
208
|
+
let match;
|
|
209
|
+
while ((match = linkPattern.exec(content)) !== null) {
|
|
210
|
+
const [fullMatch, text, url] = match;
|
|
211
|
+
// Check for empty text or URL
|
|
212
|
+
if (!text.trim()) {
|
|
213
|
+
malformed.push(fullMatch);
|
|
214
|
+
}
|
|
215
|
+
if (!url.trim()) {
|
|
216
|
+
malformed.push(fullMatch);
|
|
217
|
+
}
|
|
218
|
+
// Check for obviously broken URLs
|
|
219
|
+
if (url.includes(' ') && !url.startsWith('http')) {
|
|
220
|
+
malformed.push(fullMatch);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return malformed;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// CONFIG.YAML MANAGER
|
|
228
|
+
// ============================================================================
|
|
229
|
+
/**
|
|
230
|
+
* OpenSpec config.yaml manager
|
|
231
|
+
*/
|
|
232
|
+
export class OpenSpecConfigManager {
|
|
233
|
+
configPath;
|
|
234
|
+
openspecRoot;
|
|
235
|
+
constructor(projectRoot) {
|
|
236
|
+
this.openspecRoot = join(projectRoot, 'openspec');
|
|
237
|
+
this.configPath = join(this.openspecRoot, 'config.yaml');
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Check if OpenSpec is initialized
|
|
241
|
+
*/
|
|
242
|
+
async isInitialized() {
|
|
243
|
+
try {
|
|
244
|
+
await access(this.openspecRoot);
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Check if config.yaml exists
|
|
253
|
+
*/
|
|
254
|
+
async hasConfig() {
|
|
255
|
+
try {
|
|
256
|
+
await access(this.configPath);
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Read existing config.yaml
|
|
265
|
+
*/
|
|
266
|
+
async readConfig() {
|
|
267
|
+
try {
|
|
268
|
+
const content = await readFile(this.configPath, 'utf-8');
|
|
269
|
+
return parseYaml(content);
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Write config.yaml, preserving user content
|
|
277
|
+
*/
|
|
278
|
+
async writeConfig(config) {
|
|
279
|
+
await mkdir(this.openspecRoot, { recursive: true });
|
|
280
|
+
const content = stringifyYaml(config, { lineWidth: 100 });
|
|
281
|
+
await writeFile(this.configPath, content, 'utf-8');
|
|
282
|
+
logger.success(`Updated ${this.configPath}`);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Update config with spec-gen metadata while preserving user content
|
|
286
|
+
*/
|
|
287
|
+
async updateWithSpecGenMetadata(metadata, detectedContext, options = {
|
|
288
|
+
preserveUserContext: true,
|
|
289
|
+
appendDetectedInfo: true,
|
|
290
|
+
version: '1.0.0',
|
|
291
|
+
}) {
|
|
292
|
+
let config = await this.readConfig();
|
|
293
|
+
if (!config) {
|
|
294
|
+
config = {
|
|
295
|
+
schema: 'spec-driven',
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
// Add spec-gen metadata
|
|
299
|
+
config['spec-gen'] = metadata;
|
|
300
|
+
// Update context if we have detected info and user approves
|
|
301
|
+
if (detectedContext && options.appendDetectedInfo) {
|
|
302
|
+
config.context = this.buildContext(config.context, detectedContext, options.preserveUserContext);
|
|
303
|
+
}
|
|
304
|
+
await this.writeConfig(config);
|
|
305
|
+
return config;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Build context string combining user and detected info
|
|
309
|
+
*/
|
|
310
|
+
buildContext(existingContext, detected, preserveUser) {
|
|
311
|
+
const lines = [];
|
|
312
|
+
// Preserve user context if it exists
|
|
313
|
+
if (preserveUser && existingContext) {
|
|
314
|
+
lines.push('# User-provided context (preserved)');
|
|
315
|
+
lines.push(existingContext.trim());
|
|
316
|
+
lines.push('');
|
|
317
|
+
}
|
|
318
|
+
// Add auto-detected context
|
|
319
|
+
lines.push('# Auto-detected by spec-gen');
|
|
320
|
+
lines.push(`Tech stack: ${detected.techStack}`);
|
|
321
|
+
lines.push(`Architecture: ${detected.architecture}`);
|
|
322
|
+
lines.push(`Domains: ${detected.domains.join(', ')}`);
|
|
323
|
+
if (detected.patterns.length > 0) {
|
|
324
|
+
lines.push(`Key patterns: ${detected.patterns.join(', ')}`);
|
|
325
|
+
}
|
|
326
|
+
return lines.join('\n');
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get existing user context from config
|
|
330
|
+
*/
|
|
331
|
+
async getUserContext() {
|
|
332
|
+
const config = await this.readConfig();
|
|
333
|
+
return config?.context ?? null;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get existing domains from specs directory
|
|
337
|
+
*/
|
|
338
|
+
async getExistingDomains() {
|
|
339
|
+
const specsDir = join(this.openspecRoot, 'specs');
|
|
340
|
+
try {
|
|
341
|
+
const entries = await readdir(specsDir, { withFileTypes: true });
|
|
342
|
+
return entries
|
|
343
|
+
.filter(e => e.isDirectory())
|
|
344
|
+
.map(e => e.name)
|
|
345
|
+
.filter(name => !['overview', 'architecture', 'api'].includes(name));
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// ============================================================================
|
|
353
|
+
// CONTEXT INJECTION
|
|
354
|
+
// ============================================================================
|
|
355
|
+
/**
|
|
356
|
+
* Build detected context from analysis results
|
|
357
|
+
*/
|
|
358
|
+
export function buildDetectedContext(survey) {
|
|
359
|
+
// Build tech stack description
|
|
360
|
+
const techStack = [survey.primaryLanguage, ...survey.frameworks].join(', ');
|
|
361
|
+
// Build architecture description
|
|
362
|
+
const archPatterns = {
|
|
363
|
+
layered: 'Layered (routes → controllers → services → repositories)',
|
|
364
|
+
hexagonal: 'Hexagonal/Ports & Adapters',
|
|
365
|
+
microservices: 'Microservices',
|
|
366
|
+
monolith: 'Monolithic',
|
|
367
|
+
serverless: 'Serverless',
|
|
368
|
+
'event-driven': 'Event-Driven',
|
|
369
|
+
mvc: 'Model-View-Controller',
|
|
370
|
+
other: 'Custom architecture',
|
|
371
|
+
};
|
|
372
|
+
const architecture = archPatterns[survey.architecturePattern] || survey.architecturePattern;
|
|
373
|
+
// Detect common patterns from frameworks
|
|
374
|
+
const patterns = [];
|
|
375
|
+
if (survey.frameworks.some(f => f.toLowerCase().includes('typeorm') || f.toLowerCase().includes('prisma'))) {
|
|
376
|
+
patterns.push('Repository pattern');
|
|
377
|
+
}
|
|
378
|
+
if (survey.frameworks.some(f => f.toLowerCase().includes('inversify') || f.toLowerCase().includes('tsyringe'))) {
|
|
379
|
+
patterns.push('Dependency injection');
|
|
380
|
+
}
|
|
381
|
+
if (survey.frameworks.some(f => f.toLowerCase().includes('express') || f.toLowerCase().includes('fastify'))) {
|
|
382
|
+
patterns.push('Middleware pipeline');
|
|
383
|
+
}
|
|
384
|
+
if (survey.frameworks.some(f => f.toLowerCase().includes('react') || f.toLowerCase().includes('vue'))) {
|
|
385
|
+
patterns.push('Component-based UI');
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
techStack,
|
|
389
|
+
architecture,
|
|
390
|
+
domains: survey.suggestedDomains,
|
|
391
|
+
patterns,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
// ============================================================================
|
|
395
|
+
// DOMAIN NAMING
|
|
396
|
+
// ============================================================================
|
|
397
|
+
/**
|
|
398
|
+
* Normalize domain name to OpenSpec conventions
|
|
399
|
+
*/
|
|
400
|
+
export function normalizeDomainName(name) {
|
|
401
|
+
return name
|
|
402
|
+
.toLowerCase()
|
|
403
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
404
|
+
.replace(/^-+|-+$/g, '')
|
|
405
|
+
.replace(/--+/g, '-');
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Check if domain name follows conventions
|
|
409
|
+
*/
|
|
410
|
+
export function isValidDomainName(name) {
|
|
411
|
+
// Must be lowercase kebab-case
|
|
412
|
+
if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(name) && !/^[a-z]$/.test(name)) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
// Avoid generic names
|
|
416
|
+
const genericNames = ['misc', 'other', 'utils', 'common', 'shared', 'general', 'helpers'];
|
|
417
|
+
if (genericNames.includes(name)) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Match suggested domains against existing domains
|
|
424
|
+
*/
|
|
425
|
+
export function matchExistingDomains(suggestedDomains, existingDomains) {
|
|
426
|
+
const matches = new Map();
|
|
427
|
+
for (const suggested of suggestedDomains) {
|
|
428
|
+
const normalized = normalizeDomainName(suggested);
|
|
429
|
+
// Exact match
|
|
430
|
+
if (existingDomains.includes(normalized)) {
|
|
431
|
+
matches.set(suggested, normalized);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
// Partial match (suggested is substring or vice versa)
|
|
435
|
+
for (const existing of existingDomains) {
|
|
436
|
+
if (existing.includes(normalized) || normalized.includes(existing)) {
|
|
437
|
+
matches.set(suggested, existing);
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return matches;
|
|
443
|
+
}
|
|
444
|
+
// ============================================================================
|
|
445
|
+
// FULL SPEC VALIDATION
|
|
446
|
+
// ============================================================================
|
|
447
|
+
/**
|
|
448
|
+
* Validate a complete spec file
|
|
449
|
+
*/
|
|
450
|
+
export function validateFullSpec(content) {
|
|
451
|
+
const validator = new OpenSpecValidator();
|
|
452
|
+
const result = validator.validateSpecStructure(content);
|
|
453
|
+
// Also validate all requirements in the spec
|
|
454
|
+
const requirementBlocks = content.match(/###\s+Requirement:[^\n]+[\s\S]*?(?=###\s+Requirement:|## |$)/g) || [];
|
|
455
|
+
for (const block of requirementBlocks) {
|
|
456
|
+
const reqResult = validator.validateRequirementFormat(block);
|
|
457
|
+
result.warnings.push(...reqResult.warnings);
|
|
458
|
+
result.errors.push(...reqResult.errors);
|
|
459
|
+
}
|
|
460
|
+
// Validate all scenarios
|
|
461
|
+
const scenarioBlocks = content.match(/####\s+Scenario:[^\n]+[\s\S]*?(?=####\s+Scenario:|###\s+Requirement:|## |$)/g) || [];
|
|
462
|
+
for (const block of scenarioBlocks) {
|
|
463
|
+
const scenResult = validator.validateScenarioFormat(block);
|
|
464
|
+
result.warnings.push(...scenResult.warnings);
|
|
465
|
+
result.errors.push(...scenResult.errors);
|
|
466
|
+
}
|
|
467
|
+
// Update valid status
|
|
468
|
+
result.valid = result.errors.length === 0;
|
|
469
|
+
return result;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Validate all specs in a directory
|
|
473
|
+
*/
|
|
474
|
+
export async function validateSpecsDirectory(specsDir) {
|
|
475
|
+
const results = new Map();
|
|
476
|
+
let allValid = true;
|
|
477
|
+
try {
|
|
478
|
+
const entries = await readdir(specsDir, { withFileTypes: true });
|
|
479
|
+
for (const entry of entries) {
|
|
480
|
+
if (entry.isDirectory()) {
|
|
481
|
+
const specPath = join(specsDir, entry.name, 'spec.md');
|
|
482
|
+
try {
|
|
483
|
+
const content = await readFile(specPath, 'utf-8');
|
|
484
|
+
const result = validateFullSpec(content);
|
|
485
|
+
results.set(entry.name, result);
|
|
486
|
+
if (!result.valid) {
|
|
487
|
+
allValid = false;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch {
|
|
491
|
+
// spec.md doesn't exist in this directory
|
|
492
|
+
results.set(entry.name, {
|
|
493
|
+
valid: false,
|
|
494
|
+
errors: ['spec.md not found'],
|
|
495
|
+
warnings: [],
|
|
496
|
+
});
|
|
497
|
+
allValid = false;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
catch {
|
|
503
|
+
// specs directory doesn't exist
|
|
504
|
+
return {
|
|
505
|
+
valid: false,
|
|
506
|
+
results: new Map([['specs', { valid: false, errors: ['specs directory not found'], warnings: [] }]]),
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
return { valid: allValid, results };
|
|
510
|
+
}
|
|
511
|
+
// ============================================================================
|
|
512
|
+
// CONVENIENCE EXPORTS
|
|
513
|
+
// ============================================================================
|
|
514
|
+
/**
|
|
515
|
+
* Create a new OpenSpec compatibility helper
|
|
516
|
+
*/
|
|
517
|
+
export function createOpenSpecCompat(projectRoot) {
|
|
518
|
+
return {
|
|
519
|
+
validator: new OpenSpecValidator(),
|
|
520
|
+
configManager: new OpenSpecConfigManager(projectRoot),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
//# sourceMappingURL=openspec-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openspec-compat.js","sourceRoot":"","sources":["../../../src/core/generator/openspec-compat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenSpec Format Generator
|
|
3
|
+
*
|
|
4
|
+
* Takes structured LLM outputs and formats them into clean OpenSpec-compatible
|
|
5
|
+
* specification files.
|
|
6
|
+
*/
|
|
7
|
+
import type { PipelineResult } from './spec-pipeline.js';
|
|
8
|
+
/**
|
|
9
|
+
* Generated spec file
|
|
10
|
+
*/
|
|
11
|
+
export interface GeneratedSpec {
|
|
12
|
+
path: string;
|
|
13
|
+
content: string;
|
|
14
|
+
domain: string;
|
|
15
|
+
type: 'overview' | 'domain' | 'architecture' | 'api' | 'adr';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generator options
|
|
19
|
+
*/
|
|
20
|
+
export interface GeneratorOptions {
|
|
21
|
+
/** Version string for headers */
|
|
22
|
+
version?: string;
|
|
23
|
+
/** Output style */
|
|
24
|
+
style?: 'minimal' | 'detailed';
|
|
25
|
+
/** Include confidence indicators */
|
|
26
|
+
includeConfidence?: boolean;
|
|
27
|
+
/** Include technical notes */
|
|
28
|
+
includeTechnicalNotes?: boolean;
|
|
29
|
+
/** Maximum line width for wrapping */
|
|
30
|
+
maxLineWidth?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* OpenSpec Format Generator
|
|
34
|
+
*/
|
|
35
|
+
export declare class OpenSpecFormatGenerator {
|
|
36
|
+
private options;
|
|
37
|
+
constructor(options?: GeneratorOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Generate all spec files from pipeline result
|
|
40
|
+
*/
|
|
41
|
+
generateSpecs(result: PipelineResult): GeneratedSpec[];
|
|
42
|
+
/**
|
|
43
|
+
* Group entities, services, and endpoints by domain
|
|
44
|
+
*/
|
|
45
|
+
private groupByDomain;
|
|
46
|
+
/**
|
|
47
|
+
* Infer domain from name and location
|
|
48
|
+
*/
|
|
49
|
+
private inferDomain;
|
|
50
|
+
/**
|
|
51
|
+
* Generate the overview spec
|
|
52
|
+
*/
|
|
53
|
+
private generateOverviewSpec;
|
|
54
|
+
/**
|
|
55
|
+
* Generate a domain spec
|
|
56
|
+
*/
|
|
57
|
+
private generateDomainSpec;
|
|
58
|
+
/**
|
|
59
|
+
* Generate the architecture spec
|
|
60
|
+
*/
|
|
61
|
+
private generateArchitectureSpec;
|
|
62
|
+
/**
|
|
63
|
+
* Generate the API spec
|
|
64
|
+
*/
|
|
65
|
+
private generateApiSpec;
|
|
66
|
+
/**
|
|
67
|
+
* Add a scenario to the lines array
|
|
68
|
+
*/
|
|
69
|
+
private addScenario;
|
|
70
|
+
/**
|
|
71
|
+
* Format a requirement name (PascalCase, no spaces)
|
|
72
|
+
*/
|
|
73
|
+
private formatRequirementName;
|
|
74
|
+
/**
|
|
75
|
+
* Format a relationship for display
|
|
76
|
+
*/
|
|
77
|
+
private formatRelationship;
|
|
78
|
+
/**
|
|
79
|
+
* Format project category for display
|
|
80
|
+
*/
|
|
81
|
+
private formatCategory;
|
|
82
|
+
/**
|
|
83
|
+
* Format architecture pattern for display
|
|
84
|
+
*/
|
|
85
|
+
private formatArchitecture;
|
|
86
|
+
/**
|
|
87
|
+
* Capitalize first letter
|
|
88
|
+
*/
|
|
89
|
+
private capitalize;
|
|
90
|
+
/**
|
|
91
|
+
* Wrap text at max line width
|
|
92
|
+
*/
|
|
93
|
+
private wrapText;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validation result
|
|
97
|
+
*/
|
|
98
|
+
export interface ValidationResult {
|
|
99
|
+
valid: boolean;
|
|
100
|
+
errors: string[];
|
|
101
|
+
warnings: string[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validate a generated spec against OpenSpec conventions
|
|
105
|
+
*/
|
|
106
|
+
export declare function validateSpec(content: string): ValidationResult;
|
|
107
|
+
/**
|
|
108
|
+
* Generate OpenSpec files from pipeline result
|
|
109
|
+
*/
|
|
110
|
+
export declare function generateOpenSpecs(result: PipelineResult, options?: GeneratorOptions): GeneratedSpec[];
|
|
111
|
+
//# sourceMappingURL=openspec-format-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openspec-format-generator.d.ts","sourceRoot":"","sources":["../../../src/core/generator/openspec-format-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EAOf,MAAM,oBAAoB,CAAC;AAM5B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,KAAK,GAAG,KAAK,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,KAAK,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8BD;;GAEG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAA6B;gBAEhC,OAAO,GAAE,gBAAqB;IAI1C;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,EAAE;IAuBtD;;OAEG;IACH,OAAO,CAAC,aAAa;IAmGrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAenB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA2G5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAuM1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA+IhC;;OAEG;IACH,OAAO,CAAC,eAAe;IAwGvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAcnB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAQ7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAiBtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAuBjB;AAMD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CA2D9D;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,aAAa,EAAE,CAGjB"}
|