@specverse/engines 5.0.2 โ 5.1.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/dist/ai/commands/fill.d.ts.map +1 -1
- package/dist/ai/commands/fill.js +16 -7
- package/dist/ai/commands/fill.js.map +1 -1
- package/dist/ai/commands/template.d.ts.map +1 -1
- package/dist/ai/commands/template.js +17 -8
- package/dist/ai/commands/template.js.map +1 -1
- package/dist/bundles/deriveCatalog.d.ts +18 -0
- package/dist/bundles/deriveCatalog.d.ts.map +1 -0
- package/dist/bundles/deriveCatalog.js +263 -0
- package/dist/bundles/deriveCatalog.js.map +1 -0
- package/dist/bundles/index.d.ts +15 -0
- package/dist/bundles/index.d.ts.map +1 -0
- package/dist/bundles/index.js +15 -0
- package/dist/bundles/index.js.map +1 -0
- package/dist/bundles/types.d.ts +53 -0
- package/dist/bundles/types.d.ts.map +1 -0
- package/dist/bundles/types.js +22 -0
- package/dist/bundles/types.js.map +1 -0
- package/dist/bundles/validate.d.ts +55 -0
- package/dist/bundles/validate.d.ts.map +1 -0
- package/dist/bundles/validate.js +471 -0
- package/dist/bundles/validate.js.map +1 -0
- package/dist/inference/quint-transpiler.js +2 -2
- package/dist/inference/quint-transpiler.js.map +1 -1
- package/dist/libs/instance-factories/applications/templates/react/runtime-package-json-generator.js +1 -1
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +43 -0
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +11 -4
- package/libs/instance-factories/applications/templates/react/runtime-package-json-generator.ts +1 -1
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +43 -0
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +10 -3
- package/package.json +9 -5
- package/assets/examples/09-api/ai-spec.yaml +0 -194
- package/assets/examples/09-api/converted.yaml +0 -95
- package/assets/examples/09-api/diagram-architecture.mmd +0 -10
- package/assets/examples/09-api/diagram-er.mmd +0 -10
- package/assets/examples/09-api/documentation.html +0 -104
- package/assets/examples/09-api/documentation.md +0 -95
- package/assets/examples/09-api/inferred-spec.yaml +0 -420
- package/assets/examples/09-api/openapi.json +0 -61
- package/assets/examples/10-api/README.md +0 -216
- package/assets/examples/10-api/ai-spec.yaml +0 -194
- package/assets/examples/10-api/converted.yaml +0 -96
- package/assets/examples/10-api/diagram-architecture.mmd +0 -10
- package/assets/examples/10-api/diagram-er.mmd +0 -10
- package/assets/examples/10-api/documentation.html +0 -104
- package/assets/examples/10-api/documentation.md +0 -95
- package/assets/examples/10-api/inferred-spec.yaml +0 -7
- package/assets/examples/10-api/metadata.yaml +0 -89
- package/assets/examples/10-api/openapi.json +0 -61
- package/assets/examples/10-api/package-integration-test.js +0 -177
- package/assets/examples/10-api/usage-example.js +0 -323
- package/assets/examples/10-api/usage-example.ts +0 -363
- package/assets/examples/10-api/workflow-test.js +0 -113
- package/assets/examples/validate-examples-with-expected-failures.cjs +0 -328
- package/assets/examples/validate-examples.cjs +0 -225
- package/assets/prompts/MOVED.md +0 -35
- package/assets/prompts/SUMMARY-v8-PROMOTION.md +0 -445
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SpecVerse API Workflow Test
|
|
3
|
-
*
|
|
4
|
-
* Focused end-to-end workflow test for the SpecVerse API
|
|
5
|
-
* This is a minimal, streamlined test extracted from test-specverse-api
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { SpecVerseParser, LogicalInferenceEngine } from '../../dist/index.js';
|
|
9
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
10
|
-
|
|
11
|
-
// Simple test specification
|
|
12
|
-
const testSpec = `components:
|
|
13
|
-
UserManagement:
|
|
14
|
-
version: "1.0.0"
|
|
15
|
-
description: "User management system"
|
|
16
|
-
|
|
17
|
-
models:
|
|
18
|
-
User:
|
|
19
|
-
description: "User model for API testing"
|
|
20
|
-
attributes:
|
|
21
|
-
id: UUID required
|
|
22
|
-
name: String required
|
|
23
|
-
email: Email unique required
|
|
24
|
-
created_at: DateTime auto=now
|
|
25
|
-
|
|
26
|
-
lifecycles:
|
|
27
|
-
status:
|
|
28
|
-
flow: inactive -> active -> suspended
|
|
29
|
-
|
|
30
|
-
deployments: {}`;
|
|
31
|
-
|
|
32
|
-
async function testFullWorkflow() {
|
|
33
|
-
console.log('๐งช Testing full API workflow...');
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
// 1. Parse the spec
|
|
37
|
-
console.log('1๏ธโฃ Parsing specification...');
|
|
38
|
-
|
|
39
|
-
const schema = JSON.parse(readFileSync('schema/SPECVERSE-SCHEMA.json', 'utf8'));
|
|
40
|
-
const parser = new SpecVerseParser(schema);
|
|
41
|
-
const result = parser.parseContent(testSpec, 'test.specly');
|
|
42
|
-
|
|
43
|
-
if (result.errors.length > 0) {
|
|
44
|
-
throw new Error('Parse failed: ' + result.errors.map(e => e.message).join(', '));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const ast = result.ast;
|
|
48
|
-
console.log('โ
Parsed successfully');
|
|
49
|
-
|
|
50
|
-
// 2. Run inference
|
|
51
|
-
console.log('2๏ธโฃ Running inference...');
|
|
52
|
-
const config = {
|
|
53
|
-
logical: {
|
|
54
|
-
generateControllers: true,
|
|
55
|
-
generateServices: true,
|
|
56
|
-
generateEvents: true,
|
|
57
|
-
generateViews: true,
|
|
58
|
-
generateTypes: true
|
|
59
|
-
},
|
|
60
|
-
rules: {
|
|
61
|
-
logicalRulesPath: 'dist/inference-engine/rules/logical',
|
|
62
|
-
deploymentRulesPath: 'dist/inference-engine/rules/deployment'
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const engine = new LogicalInferenceEngine(config);
|
|
67
|
-
const models = ast.components.flatMap(c => c.models);
|
|
68
|
-
|
|
69
|
-
// Load rules
|
|
70
|
-
const rulesResult = await engine.loadRules();
|
|
71
|
-
if (!rulesResult.valid) {
|
|
72
|
-
throw new Error('Failed to load rules: ' + rulesResult.errors.map(e => e.message).join(', '));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Run inference
|
|
76
|
-
const inferenceResult = await engine.inferLogicalSpecification(models, 'TestComponent');
|
|
77
|
-
|
|
78
|
-
console.log('โ
Inference completed!');
|
|
79
|
-
console.log(' Generated Controllers:', inferenceResult.statistics.controllersGenerated || 0);
|
|
80
|
-
console.log(' Generated Services:', inferenceResult.statistics.servicesGenerated || 0);
|
|
81
|
-
console.log(' Generated Events:', inferenceResult.statistics.eventsGenerated || 0);
|
|
82
|
-
console.log(' Generated Views:', inferenceResult.statistics.viewsGenerated || 0);
|
|
83
|
-
|
|
84
|
-
if (inferenceResult.validation.valid) {
|
|
85
|
-
console.log('โ
Generated specification is valid!');
|
|
86
|
-
console.log('๐ FULL API WORKFLOW SUCCESS!');
|
|
87
|
-
return true;
|
|
88
|
-
} else {
|
|
89
|
-
console.log('โ ๏ธ Generated specification has warnings:', inferenceResult.validation.errors.length);
|
|
90
|
-
inferenceResult.validation.errors.forEach(error => {
|
|
91
|
-
console.log(' -', error.message);
|
|
92
|
-
});
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.error('โ Workflow failed:', error.message);
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Export for use in tests
|
|
103
|
-
export { testFullWorkflow };
|
|
104
|
-
|
|
105
|
-
// Run if executed directly
|
|
106
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
107
|
-
testFullWorkflow()
|
|
108
|
-
.then(success => process.exit(success ? 0 : 1))
|
|
109
|
-
.catch(error => {
|
|
110
|
-
console.error('Unexpected error:', error);
|
|
111
|
-
process.exit(1);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SpecVerse v3.1 Enhanced Examples Validation Harness with Expected Failures Support
|
|
5
|
-
*
|
|
6
|
-
* Validates and processes all .specly examples and test files
|
|
7
|
-
* Uses expected-failures.json to distinguish expected vs unexpected failures
|
|
8
|
-
*
|
|
9
|
-
* Usage: Run from project root directory
|
|
10
|
-
* node examples/validate-examples-with-expected-failures.cjs
|
|
11
|
-
*
|
|
12
|
-
* Features:
|
|
13
|
-
* - Comprehensive validation (examples + tests directories)
|
|
14
|
-
* - Expected failures management system
|
|
15
|
-
* - 3-phase validation with failure categorization
|
|
16
|
-
* - Integration with test suite expected failures
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
const { execSync } = require('child_process');
|
|
22
|
-
const ExpectedFailuresManager = require('../tests/expected-failures.cjs');
|
|
23
|
-
|
|
24
|
-
// ANSI Colors for better output
|
|
25
|
-
const colors = {
|
|
26
|
-
blue: '\x1b[1m\x1b[34m',
|
|
27
|
-
green: '\x1b[32m',
|
|
28
|
-
red: '\x1b[31m',
|
|
29
|
-
yellow: '\x1b[33m',
|
|
30
|
-
orange: '\x1b[38;5;208m',
|
|
31
|
-
reset: '\x1b[0m',
|
|
32
|
-
bold: '\x1b[1m'
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
class EnhancedExamplesValidator {
|
|
36
|
-
constructor() {
|
|
37
|
-
this.results = {
|
|
38
|
-
validation: { passed: 0, expectedFailures: 0, unexpectedFailures: 0, errors: [] },
|
|
39
|
-
processing: { passed: 0, expectedFailures: 0, unexpectedFailures: 0, errors: [] },
|
|
40
|
-
yamlValidation: { passed: 0, expectedFailures: 0, unexpectedFailures: 0, errors: [] }
|
|
41
|
-
};
|
|
42
|
-
this.cliPath = './dist/cli/specverse-cli.js';
|
|
43
|
-
this.expectedFailures = new ExpectedFailuresManager();
|
|
44
|
-
this.allTestedFiles = new Set();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
log(message, color = '') {
|
|
48
|
-
console.log(`${color}${message}${colors.reset}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
findSpeclyFiles() {
|
|
52
|
-
const speclyFiles = [];
|
|
53
|
-
|
|
54
|
-
function scanDirectory(dir) {
|
|
55
|
-
const items = fs.readdirSync(dir);
|
|
56
|
-
|
|
57
|
-
for (const item of items) {
|
|
58
|
-
const fullPath = path.join(dir, item);
|
|
59
|
-
const stat = fs.statSync(fullPath);
|
|
60
|
-
|
|
61
|
-
if (stat.isDirectory() && !item.startsWith('.') && item !== 'diagrams' && item !== 'docs' && item !== 'metadata' && item !== 'common' && item !== 'archive' && item !== 'templates') {
|
|
62
|
-
scanDirectory(fullPath);
|
|
63
|
-
} else if (item.endsWith('.specly') && !fullPath.includes('/archive/')) {
|
|
64
|
-
// Skip any .specly files that are in archive directories at any level
|
|
65
|
-
speclyFiles.push(fullPath);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Scan examples directory and test directories
|
|
71
|
-
// Note: Excluding templates as they contain {{variables}} that are invalid until processed
|
|
72
|
-
const searchPaths = [
|
|
73
|
-
'examples',
|
|
74
|
-
'tests'
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
searchPaths.forEach(searchPath => {
|
|
78
|
-
if (fs.existsSync(searchPath)) {
|
|
79
|
-
scanDirectory(searchPath);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return speclyFiles.sort();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
handleValidationResult(filePath, success, error = null) {
|
|
87
|
-
const relativePath = path.relative('.', filePath);
|
|
88
|
-
this.allTestedFiles.add(relativePath);
|
|
89
|
-
|
|
90
|
-
if (success) {
|
|
91
|
-
this.log(`โ
${path.basename(filePath)} validation passed`, colors.green);
|
|
92
|
-
this.results.validation.passed++;
|
|
93
|
-
} else {
|
|
94
|
-
const isExpected = this.expectedFailures.isExpectedFailure(relativePath);
|
|
95
|
-
|
|
96
|
-
if (isExpected) {
|
|
97
|
-
const reason = this.expectedFailures.getExpectedFailureReason(relativePath);
|
|
98
|
-
this.log(`โ ๏ธ ${path.basename(filePath)} validation failed (EXPECTED: ${reason.category})`, colors.orange);
|
|
99
|
-
this.results.validation.expectedFailures++;
|
|
100
|
-
} else {
|
|
101
|
-
this.log(`โ ${path.basename(filePath)} validation failed (UNEXPECTED!)`, colors.red);
|
|
102
|
-
this.results.validation.unexpectedFailures++;
|
|
103
|
-
if (error) {
|
|
104
|
-
this.log(` Error: ${error}`, colors.red);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.results.validation.errors.push({
|
|
109
|
-
file: relativePath,
|
|
110
|
-
error: error,
|
|
111
|
-
expected: isExpected
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
handleProcessingResult(filePath, success, error = null) {
|
|
117
|
-
const relativePath = path.relative('.', filePath);
|
|
118
|
-
|
|
119
|
-
if (success) {
|
|
120
|
-
this.log(`โ
${path.basename(filePath)} processing succeeded`, colors.green);
|
|
121
|
-
this.results.processing.passed++;
|
|
122
|
-
} else {
|
|
123
|
-
const isExpected = this.expectedFailures.isExpectedFailure(relativePath);
|
|
124
|
-
|
|
125
|
-
if (isExpected) {
|
|
126
|
-
const reason = this.expectedFailures.getExpectedFailureReason(relativePath);
|
|
127
|
-
this.log(`โ ๏ธ ${path.basename(filePath)} processing failed (EXPECTED: ${reason.category})`, colors.orange);
|
|
128
|
-
this.results.processing.expectedFailures++;
|
|
129
|
-
} else {
|
|
130
|
-
this.log(`โ ${path.basename(filePath)} processing failed (UNEXPECTED!)`, colors.red);
|
|
131
|
-
this.results.processing.unexpectedFailures++;
|
|
132
|
-
if (error && error.length > 200) {
|
|
133
|
-
// Truncate very long errors
|
|
134
|
-
error = error.substring(0, 200) + '...';
|
|
135
|
-
}
|
|
136
|
-
if (error) {
|
|
137
|
-
this.log(`โ Processing failed:\n ${error}`, colors.red);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
this.results.processing.errors.push({
|
|
142
|
-
file: relativePath,
|
|
143
|
-
error: error,
|
|
144
|
-
expected: isExpected
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
validateSpeclyFile(filePath) {
|
|
150
|
-
this.log(`๐งช Validating ${path.basename(filePath)}`, colors.blue);
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
execSync(`node ${this.cliPath} validate "${filePath}"`, {
|
|
154
|
-
stdio: 'pipe',
|
|
155
|
-
timeout: 10000
|
|
156
|
-
});
|
|
157
|
-
this.handleValidationResult(filePath, true);
|
|
158
|
-
} catch (error) {
|
|
159
|
-
this.handleValidationResult(filePath, false, error.message);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
processSpeclyFile(filePath) {
|
|
164
|
-
const fileName = path.basename(filePath, '.specly');
|
|
165
|
-
const outputPath = `/tmp/example-${fileName}.yaml`;
|
|
166
|
-
|
|
167
|
-
this.log(`๐งช Processing ${path.basename(filePath)} โ .yaml`, colors.blue);
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
const result = execSync(`node ${this.cliPath} gen yaml "${filePath}" -o "${outputPath}"`, {
|
|
171
|
-
stdio: 'pipe',
|
|
172
|
-
timeout: 15000,
|
|
173
|
-
encoding: 'utf8'
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
// Check if output file was created and has content
|
|
177
|
-
if (fs.existsSync(outputPath)) {
|
|
178
|
-
const content = fs.readFileSync(outputPath, 'utf8').trim();
|
|
179
|
-
if (content.length > 10) { // Minimal content check
|
|
180
|
-
this.handleProcessingResult(filePath, true);
|
|
181
|
-
|
|
182
|
-
// Validate the generated YAML
|
|
183
|
-
this.validateGeneratedYaml(outputPath, fileName);
|
|
184
|
-
} else {
|
|
185
|
-
this.handleProcessingResult(filePath, false, "Generated YAML is empty or minimal");
|
|
186
|
-
}
|
|
187
|
-
} else {
|
|
188
|
-
this.handleProcessingResult(filePath, false, "No output file generated");
|
|
189
|
-
}
|
|
190
|
-
} catch (error) {
|
|
191
|
-
this.handleProcessingResult(filePath, false, error.message);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
validateGeneratedYaml(yamlPath, baseName) {
|
|
196
|
-
this.log(`๐งช Validating generated ${path.basename(yamlPath)}`, colors.blue);
|
|
197
|
-
|
|
198
|
-
try {
|
|
199
|
-
execSync(`node ${this.cliPath} validate "${yamlPath}"`, {
|
|
200
|
-
stdio: 'pipe',
|
|
201
|
-
timeout: 10000
|
|
202
|
-
});
|
|
203
|
-
this.log(`โ
Generated ${path.basename(yamlPath)} validation passed`, colors.green);
|
|
204
|
-
this.results.yamlValidation.passed++;
|
|
205
|
-
} catch (error) {
|
|
206
|
-
this.log(`โ Generated ${path.basename(yamlPath)} validation failed`, colors.red);
|
|
207
|
-
this.results.yamlValidation.unexpectedFailures++;
|
|
208
|
-
this.results.yamlValidation.errors.push({
|
|
209
|
-
file: yamlPath,
|
|
210
|
-
error: error.message,
|
|
211
|
-
expected: false
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Clean up
|
|
216
|
-
try {
|
|
217
|
-
fs.unlinkSync(yamlPath);
|
|
218
|
-
} catch (e) {
|
|
219
|
-
// Ignore cleanup errors
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
printSummary() {
|
|
224
|
-
this.log('', '');
|
|
225
|
-
this.log('๐ Enhanced Test Results Summary', colors.bold + colors.blue);
|
|
226
|
-
|
|
227
|
-
const phases = [
|
|
228
|
-
{ name: 'Phase 1: .specly Validation', results: this.results.validation },
|
|
229
|
-
{ name: 'Phase 2: .specly โ .yaml Processing', results: this.results.processing },
|
|
230
|
-
{ name: 'Phase 3: Generated .yaml Validation', results: this.results.yamlValidation }
|
|
231
|
-
];
|
|
232
|
-
|
|
233
|
-
let totalPassed = 0;
|
|
234
|
-
let totalExpected = 0;
|
|
235
|
-
let totalUnexpected = 0;
|
|
236
|
-
|
|
237
|
-
phases.forEach(phase => {
|
|
238
|
-
const r = phase.results;
|
|
239
|
-
totalPassed += r.passed;
|
|
240
|
-
totalExpected += r.expectedFailures;
|
|
241
|
-
totalUnexpected += r.unexpectedFailures;
|
|
242
|
-
|
|
243
|
-
this.log(`\n${phase.name}:`, colors.bold);
|
|
244
|
-
this.log(` โ
Passed: ${r.passed}`, colors.green);
|
|
245
|
-
if (r.expectedFailures > 0) {
|
|
246
|
-
this.log(` โ ๏ธ Expected Failures: ${r.expectedFailures}`, colors.orange);
|
|
247
|
-
}
|
|
248
|
-
if (r.unexpectedFailures > 0) {
|
|
249
|
-
this.log(` โ Unexpected Failures: ${r.unexpectedFailures}`, colors.red);
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Overall summary
|
|
254
|
-
this.log('\n=== OVERALL SUMMARY ===', colors.bold);
|
|
255
|
-
this.log(`Total Tests: ${totalPassed + totalExpected + totalUnexpected}`);
|
|
256
|
-
this.log(`โ
Passed: ${totalPassed}`, colors.green);
|
|
257
|
-
this.log(`โ ๏ธ Expected Failures: ${totalExpected}`, colors.orange);
|
|
258
|
-
this.log(`โ Unexpected Failures: ${totalUnexpected}`, colors.red);
|
|
259
|
-
|
|
260
|
-
// Generate expected failures report
|
|
261
|
-
const allActualFailures = [
|
|
262
|
-
...this.results.validation.errors.filter(e => !e.expected).map(e => e.file),
|
|
263
|
-
...this.results.processing.errors.filter(e => !e.expected).map(e => e.file),
|
|
264
|
-
...this.results.yamlValidation.errors.filter(e => !e.expected).map(e => e.file)
|
|
265
|
-
];
|
|
266
|
-
|
|
267
|
-
const analysis = this.expectedFailures.generateReport(
|
|
268
|
-
allActualFailures,
|
|
269
|
-
totalPassed + totalExpected + totalUnexpected
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
this.log(analysis.report, '');
|
|
273
|
-
|
|
274
|
-
// Return success status
|
|
275
|
-
return {
|
|
276
|
-
success: analysis.isHealthy,
|
|
277
|
-
summary: analysis.summary,
|
|
278
|
-
hasUnexpectedFailures: totalUnexpected > 0
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
async run() {
|
|
283
|
-
this.log('๐ SpecVerse v3.1 Enhanced Examples Validation Harness', colors.bold + colors.blue);
|
|
284
|
-
this.log('Validating .specly examples with expected failures support\\n', '');
|
|
285
|
-
|
|
286
|
-
const speclyFiles = this.findSpeclyFiles();
|
|
287
|
-
this.log(`๐ Found ${speclyFiles.length} .specly example files\\n`, colors.blue);
|
|
288
|
-
|
|
289
|
-
// Phase 1: Validation
|
|
290
|
-
this.log('Phase 1: .specly File Validation', colors.bold + colors.blue);
|
|
291
|
-
for (const file of speclyFiles) {
|
|
292
|
-
this.validateSpeclyFile(file);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Phase 2: Processing (only for files that passed validation OR are expected to pass processing)
|
|
296
|
-
this.log('\\nPhase 2: .specly โ .yaml Processing', colors.bold + colors.blue);
|
|
297
|
-
const validFiles = speclyFiles.filter(file => {
|
|
298
|
-
const relativePath = path.relative('.', file);
|
|
299
|
-
const validationError = this.results.validation.errors.find(e => e.file === relativePath);
|
|
300
|
-
return !validationError || validationError.expected;
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
for (const file of validFiles) {
|
|
304
|
-
// Only process if validation passed OR it's an expected validation failure
|
|
305
|
-
const relativePath = path.relative('.', file);
|
|
306
|
-
const validationFailed = this.results.validation.errors.some(e => e.file === relativePath);
|
|
307
|
-
|
|
308
|
-
if (!validationFailed || this.expectedFailures.isExpectedFailure(relativePath)) {
|
|
309
|
-
this.processSpeclyFile(file);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return this.printSummary();
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Run if called directly
|
|
318
|
-
if (require.main === module) {
|
|
319
|
-
const validator = new EnhancedExamplesValidator();
|
|
320
|
-
validator.run().then(result => {
|
|
321
|
-
process.exit(result.hasUnexpectedFailures ? 1 : 0);
|
|
322
|
-
}).catch(error => {
|
|
323
|
-
console.error('Fatal error:', error);
|
|
324
|
-
process.exit(1);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
module.exports = EnhancedExamplesValidator;
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SpecVerse v3.1 Examples Validation Harness (Basic)
|
|
5
|
-
*
|
|
6
|
-
* Validates and processes all .specly examples in the examples directory
|
|
7
|
-
*
|
|
8
|
-
* Usage: Run from examples/ directory
|
|
9
|
-
* cd examples && node validate-examples.cjs
|
|
10
|
-
*
|
|
11
|
-
* Features:
|
|
12
|
-
* - Simple 3-phase validation (specly โ yaml โ validation)
|
|
13
|
-
* - No expected failures handling
|
|
14
|
-
* - Focused on examples directory only
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const fs = require('fs');
|
|
18
|
-
const path = require('path');
|
|
19
|
-
const { execSync } = require('child_process');
|
|
20
|
-
|
|
21
|
-
// ANSI Colors for better output
|
|
22
|
-
const colors = {
|
|
23
|
-
blue: '\x1b[1m\x1b[34m',
|
|
24
|
-
green: '\x1b[32m',
|
|
25
|
-
red: '\x1b[31m',
|
|
26
|
-
yellow: '\x1b[33m',
|
|
27
|
-
reset: '\x1b[0m',
|
|
28
|
-
bold: '\x1b[1m'
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
class ExamplesValidator {
|
|
32
|
-
constructor() {
|
|
33
|
-
this.results = {
|
|
34
|
-
validation: { passed: 0, failed: 0, errors: [] },
|
|
35
|
-
processing: { passed: 0, failed: 0, errors: [] },
|
|
36
|
-
yamlValidation: { passed: 0, failed: 0, errors: [] }
|
|
37
|
-
};
|
|
38
|
-
this.cliPath = '../dist/cli/specverse-cli.js';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
log(message, color = '') {
|
|
42
|
-
console.log(`${color}${message}${colors.reset}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
findSpeclyFiles() {
|
|
46
|
-
const speclyFiles = [];
|
|
47
|
-
|
|
48
|
-
function scanDirectory(dir) {
|
|
49
|
-
const items = fs.readdirSync(dir);
|
|
50
|
-
|
|
51
|
-
for (const item of items) {
|
|
52
|
-
const fullPath = path.join(dir, item);
|
|
53
|
-
const stat = fs.statSync(fullPath);
|
|
54
|
-
|
|
55
|
-
if (stat.isDirectory() && !item.startsWith('.') && item !== 'diagrams' && item !== 'docs' && item !== 'metadata' && item !== 'common') {
|
|
56
|
-
scanDirectory(fullPath);
|
|
57
|
-
} else if (item.endsWith('.specly')) {
|
|
58
|
-
speclyFiles.push(fullPath);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
scanDirectory('.');
|
|
64
|
-
return speclyFiles.sort();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async validateSpeclyFile(filePath) {
|
|
68
|
-
try {
|
|
69
|
-
const cmd = `node ${this.cliPath} validate "${filePath}"`;
|
|
70
|
-
execSync(cmd, { stdio: 'pipe' });
|
|
71
|
-
this.results.validation.passed++;
|
|
72
|
-
this.log(`โ
${path.basename(filePath)} validation passed`, colors.green);
|
|
73
|
-
return true;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
this.results.validation.failed++;
|
|
76
|
-
this.results.validation.errors.push({
|
|
77
|
-
file: filePath,
|
|
78
|
-
error: error.message,
|
|
79
|
-
type: '.specly validation'
|
|
80
|
-
});
|
|
81
|
-
this.log(`โ ${path.basename(filePath)} validation failed`, colors.red);
|
|
82
|
-
this.log(` Error: ${error.message.split('\\n')[0]}`, '');
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async processSpeclyFile(filePath) {
|
|
88
|
-
try {
|
|
89
|
-
const outputPath = `/tmp/example-${path.basename(filePath, '.specly')}.yaml`;
|
|
90
|
-
const cmd = `node ${this.cliPath} gen yaml "${filePath}" -o "${outputPath}"`;
|
|
91
|
-
execSync(cmd, { stdio: 'pipe' });
|
|
92
|
-
|
|
93
|
-
// Check if output file was created and has content
|
|
94
|
-
if (fs.existsSync(outputPath)) {
|
|
95
|
-
const content = fs.readFileSync(outputPath, 'utf8');
|
|
96
|
-
if (content.trim().length > 50) { // More than just empty structure
|
|
97
|
-
this.results.processing.passed++;
|
|
98
|
-
this.log(`โ
${path.basename(filePath)} processing succeeded`, colors.green);
|
|
99
|
-
return { success: true, outputPath };
|
|
100
|
-
} else {
|
|
101
|
-
throw new Error('Generated YAML is empty or minimal');
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
throw new Error('Output file was not created');
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
this.results.processing.failed++;
|
|
108
|
-
this.results.processing.errors.push({
|
|
109
|
-
file: filePath,
|
|
110
|
-
error: error.message,
|
|
111
|
-
type: '.specly โ .yaml processing'
|
|
112
|
-
});
|
|
113
|
-
this.log(`โ ${path.basename(filePath)} processing failed`, colors.red);
|
|
114
|
-
this.log(` Error: ${error.message.split('\\n')[0]}`, '');
|
|
115
|
-
return { success: false };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async validateYamlFile(filePath) {
|
|
120
|
-
try {
|
|
121
|
-
const cmd = `node ${this.cliPath} validate "${filePath}"`;
|
|
122
|
-
execSync(cmd, { stdio: 'pipe' });
|
|
123
|
-
this.results.yamlValidation.passed++;
|
|
124
|
-
this.log(`โ
Generated ${path.basename(filePath)} validation passed`, colors.green);
|
|
125
|
-
return true;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
this.results.yamlValidation.failed++;
|
|
128
|
-
this.results.yamlValidation.errors.push({
|
|
129
|
-
file: filePath,
|
|
130
|
-
error: error.message,
|
|
131
|
-
type: 'Generated .yaml validation'
|
|
132
|
-
});
|
|
133
|
-
this.log(`โ Generated ${path.basename(filePath)} validation failed`, colors.red);
|
|
134
|
-
this.log(` Error: ${error.message.split('\\n')[0]}`, '');
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
printSummary() {
|
|
140
|
-
const total = this.results.validation.passed + this.results.validation.failed;
|
|
141
|
-
const validationRate = total > 0 ? ((this.results.validation.passed / total) * 100).toFixed(1) : 0;
|
|
142
|
-
const processingRate = total > 0 ? ((this.results.processing.passed / total) * 100).toFixed(1) : 0;
|
|
143
|
-
const yamlRate = this.results.processing.passed > 0 ?
|
|
144
|
-
((this.results.yamlValidation.passed / this.results.processing.passed) * 100).toFixed(1) : 0;
|
|
145
|
-
|
|
146
|
-
this.log('\\n๐ Examples Validation Summary', colors.blue);
|
|
147
|
-
this.log(`Total Examples: ${total}`);
|
|
148
|
-
this.log(`โ
Specly Validation: ${this.results.validation.passed}/${total} (${validationRate}%)`, colors.green);
|
|
149
|
-
this.log(`โ
Processing: ${this.results.processing.passed}/${total} (${processingRate}%)`, colors.green);
|
|
150
|
-
this.log(`โ
Generated YAML Validation: ${this.results.yamlValidation.passed}/${this.results.processing.passed} (${yamlRate}%)`, colors.green);
|
|
151
|
-
|
|
152
|
-
const overallPassed = Math.min(this.results.validation.passed, this.results.processing.passed, this.results.yamlValidation.passed);
|
|
153
|
-
const overallRate = total > 0 ? ((overallPassed / total) * 100).toFixed(1) : 0;
|
|
154
|
-
|
|
155
|
-
this.log(`\\n๐ฏ Overall Success Rate: ${overallRate}%`, overallRate >= 90 ? colors.green : overallRate >= 70 ? colors.yellow : colors.red);
|
|
156
|
-
|
|
157
|
-
if (this.results.validation.errors.length > 0 ||
|
|
158
|
-
this.results.processing.errors.length > 0 ||
|
|
159
|
-
this.results.yamlValidation.errors.length > 0) {
|
|
160
|
-
this.log('\\nโ Failed Examples Details', colors.red);
|
|
161
|
-
let errorIndex = 1;
|
|
162
|
-
|
|
163
|
-
for (const error of [...this.results.validation.errors, ...this.results.processing.errors, ...this.results.yamlValidation.errors]) {
|
|
164
|
-
this.log(`${errorIndex}. ${error.type}`, colors.red);
|
|
165
|
-
this.log(` File: ${error.file}`, '');
|
|
166
|
-
this.log(` Error: ${error.error.split('\\n')[0]}`, '');
|
|
167
|
-
this.log('');
|
|
168
|
-
errorIndex++;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
this.log('\\n๐ง Recommended Actions', colors.blue);
|
|
173
|
-
if (overallRate < 50) {
|
|
174
|
-
this.log('1. Update examples to v3.1 container format (components: structure)');
|
|
175
|
-
this.log('2. Fix data types (Text โ String, etc.)');
|
|
176
|
-
this.log('3. Update import/export syntax to match v3.1 schema');
|
|
177
|
-
} else if (overallRate < 90) {
|
|
178
|
-
this.log('1. Fix specific validation errors shown above');
|
|
179
|
-
this.log('2. Ensure all examples use current v3.1 conventions');
|
|
180
|
-
} else {
|
|
181
|
-
this.log('1. Examples are in excellent shape!');
|
|
182
|
-
this.log('2. Consider adding more complex examples or edge cases');
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async run() {
|
|
187
|
-
this.log('๐ SpecVerse v3.1 Examples Validation Harness', colors.blue);
|
|
188
|
-
this.log('Validating .specly examples โ processing โ validating generated YAML\\n');
|
|
189
|
-
|
|
190
|
-
const speclyFiles = this.findSpeclyFiles();
|
|
191
|
-
|
|
192
|
-
if (speclyFiles.length === 0) {
|
|
193
|
-
this.log('โ No .specly files found in examples directory', colors.red);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
this.log(`๐ Found ${speclyFiles.length} .specly example files\\n`);
|
|
198
|
-
|
|
199
|
-
// Phase 1: Validate all .specly files
|
|
200
|
-
this.log('Phase 1: .specly File Validation', colors.blue);
|
|
201
|
-
for (const file of speclyFiles) {
|
|
202
|
-
this.log(`๐งช Validating ${path.basename(file)}`);
|
|
203
|
-
await this.validateSpeclyFile(file);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Phase 2: Process .specly โ .yaml
|
|
207
|
-
this.log('\\nPhase 2: .specly โ .yaml Processing', colors.blue);
|
|
208
|
-
for (const file of speclyFiles) {
|
|
209
|
-
this.log(`๐งช Processing ${path.basename(file)} โ .yaml`);
|
|
210
|
-
const result = await this.processSpeclyFile(file);
|
|
211
|
-
|
|
212
|
-
// Phase 3: Validate generated YAML (only if processing succeeded)
|
|
213
|
-
if (result.success) {
|
|
214
|
-
this.log(`๐งช Validating generated ${path.basename(result.outputPath)}`);
|
|
215
|
-
await this.validateYamlFile(result.outputPath);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
this.printSummary();
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Run the validator
|
|
224
|
-
const validator = new ExamplesValidator();
|
|
225
|
-
validator.run().catch(console.error);
|
package/assets/prompts/MOVED.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Prompts Directory Migration Notice
|
|
2
|
-
|
|
3
|
-
## Important: Directory Structure Changed
|
|
4
|
-
|
|
5
|
-
The prompts directory has been reorganized as part of the SpecVerse v3.1 AI Support architecture enhancement.
|
|
6
|
-
|
|
7
|
-
### New Structure
|
|
8
|
-
|
|
9
|
-
All prompts have been moved to the `ai-support/prompts/` directory:
|
|
10
|
-
|
|
11
|
-
- **Standard prompts**: `ai-support/prompts/core/standard/`
|
|
12
|
-
- **Specialized prompts**: `ai-support/prompts/specialized/`
|
|
13
|
-
- **Template prompts**: `ai-support/prompts/templates/`
|
|
14
|
-
- **Library-aware prompts**: `ai-support/prompts/library-aware/`
|
|
15
|
-
|
|
16
|
-
### Legacy Compatibility
|
|
17
|
-
|
|
18
|
-
This directory (`prompts/`) now serves as a symbolic link to `ai-support/prompts/` for backward compatibility.
|
|
19
|
-
|
|
20
|
-
### For Developers
|
|
21
|
-
|
|
22
|
-
Update your import paths and references:
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
OLD: prompts/standard/create.prompt.yaml
|
|
26
|
-
NEW: ai-support/prompts/core/standard/create.prompt.yaml
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Or use the symlink:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
COMPATIBLE: prompts/core/standard/create.prompt.yaml
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
For more information, see the AI Support Migration Guide in `ai-support/docs/migration-guide.md`.
|