@specsafe/cli 0.5.0 → 0.7.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.
Files changed (42) hide show
  1. package/dist/commands/capsule.d.ts +8 -0
  2. package/dist/commands/capsule.d.ts.map +1 -0
  3. package/dist/commands/capsule.js +466 -0
  4. package/dist/commands/capsule.js.map +1 -0
  5. package/dist/commands/constitution.d.ts +3 -0
  6. package/dist/commands/constitution.d.ts.map +1 -0
  7. package/dist/commands/constitution.js +192 -0
  8. package/dist/commands/constitution.js.map +1 -0
  9. package/dist/commands/export.d.ts +7 -0
  10. package/dist/commands/export.d.ts.map +1 -0
  11. package/dist/commands/export.js +179 -0
  12. package/dist/commands/export.js.map +1 -0
  13. package/dist/commands/extend.d.ts +6 -0
  14. package/dist/commands/extend.d.ts.map +1 -0
  15. package/dist/commands/extend.js +167 -0
  16. package/dist/commands/extend.js.map +1 -0
  17. package/dist/commands/memory.d.ts +3 -0
  18. package/dist/commands/memory.d.ts.map +1 -0
  19. package/dist/commands/memory.js +166 -0
  20. package/dist/commands/memory.js.map +1 -0
  21. package/dist/commands/new.d.ts.map +1 -1
  22. package/dist/commands/new.js +66 -1
  23. package/dist/commands/new.js.map +1 -1
  24. package/dist/commands/shard.d.ts +6 -0
  25. package/dist/commands/shard.d.ts.map +1 -0
  26. package/dist/commands/shard.js +199 -0
  27. package/dist/commands/shard.js.map +1 -0
  28. package/dist/commands/test-guide.d.ts +3 -0
  29. package/dist/commands/test-guide.d.ts.map +1 -0
  30. package/dist/commands/test-guide.js +190 -0
  31. package/dist/commands/test-guide.js.map +1 -0
  32. package/dist/commands/test-report.d.ts +3 -0
  33. package/dist/commands/test-report.d.ts.map +1 -0
  34. package/dist/commands/test-report.js +196 -0
  35. package/dist/commands/test-report.js.map +1 -0
  36. package/dist/commands/test-submit.d.ts +6 -0
  37. package/dist/commands/test-submit.d.ts.map +1 -0
  38. package/dist/commands/test-submit.js +236 -0
  39. package/dist/commands/test-submit.js.map +1 -0
  40. package/dist/index.js +21 -0
  41. package/dist/index.js.map +1 -1
  42. package/package.json +3 -3
@@ -0,0 +1,190 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { Workflow, ProjectTracker, generateGuide, generateGuideContent, convertToPlaywrightScenarios, generatePlaywrightScript, } from '@specsafe/core';
5
+ import { readFile, writeFile, mkdir } from 'fs/promises';
6
+ import { join, dirname, normalize, isAbsolute } from 'path';
7
+ function validateSpecInput(specInput) {
8
+ if (specInput.endsWith('.md'))
9
+ return specInput;
10
+ if (!/^[A-Za-z0-9_-]+$/.test(specInput)) {
11
+ throw new Error('Invalid spec identifier. Use only letters, numbers, dash, and underscore.');
12
+ }
13
+ return specInput;
14
+ }
15
+ function sanitizeOutputPath(outputPath) {
16
+ const normalized = normalize(outputPath);
17
+ if (isAbsolute(normalized) || normalized.includes('..')) {
18
+ throw new Error('Output path must be a safe relative path');
19
+ }
20
+ return normalized;
21
+ }
22
+ export const testGuideCommand = new Command('test-guide')
23
+ .description('Generate E2E test guide from spec')
24
+ .argument('<spec>', 'Spec ID or path to spec file')
25
+ .option('-o, --output <file>', 'Output file path')
26
+ .option('--format <format>', 'Output format (markdown|json)', 'markdown')
27
+ .option('--mode <mode>', 'Automation mode (manual|playwright)', 'manual')
28
+ .option('--auto', 'Generate Playwright script output')
29
+ .option('--priority <priorities...>', 'Filter by priority (P0 P1 P2)', ['P0', 'P1', 'P2'])
30
+ .action(async (specInput, options) => {
31
+ const spinner = ora('Generating test guide...').start();
32
+ try {
33
+ specInput = validateSpecInput(specInput);
34
+ const workflow = new Workflow();
35
+ const tracker = new ProjectTracker(process.cwd());
36
+ await tracker.loadSpecsIntoWorkflow(workflow);
37
+ let specId;
38
+ let specContent;
39
+ let specPath;
40
+ if (specInput.endsWith('.md')) {
41
+ specPath = specInput;
42
+ try {
43
+ specContent = await readFile(specPath, 'utf-8');
44
+ specId = specInput.split('/').pop().replace('.md', '');
45
+ }
46
+ catch {
47
+ throw new Error(`Spec file not found: ${specPath}`);
48
+ }
49
+ }
50
+ else {
51
+ specId = specInput;
52
+ specPath = join('specs/active', `${specId}.md`);
53
+ try {
54
+ specContent = await readFile(specPath, 'utf-8');
55
+ }
56
+ catch {
57
+ throw new Error(`Spec file not found: ${specPath}`);
58
+ }
59
+ }
60
+ let spec = workflow.getSpec(specId);
61
+ if (!spec)
62
+ spec = parseSpecFromContent(specId, specContent);
63
+ spinner.text = 'Generating test content...';
64
+ const priorityFilter = options.priority;
65
+ const mode = options.auto ? 'playwright' : (options.mode ?? 'manual');
66
+ const guide = generateGuide(spec, {
67
+ priorityFilter,
68
+ format: options.format,
69
+ mode,
70
+ });
71
+ let output;
72
+ let outputFormat;
73
+ if (options.auto) {
74
+ const scenarios = convertToPlaywrightScenarios(guide);
75
+ output = generatePlaywrightScript(spec.id, scenarios);
76
+ outputFormat = 'js';
77
+ }
78
+ else {
79
+ const result = generateGuideContent(spec, {
80
+ priorityFilter,
81
+ format: options.format,
82
+ mode,
83
+ });
84
+ output = result.content;
85
+ outputFormat = result.format === 'markdown' ? 'md' : result.format;
86
+ }
87
+ spinner.stop();
88
+ let outputPath;
89
+ if (options.output) {
90
+ outputPath = sanitizeOutputPath(options.output);
91
+ }
92
+ else {
93
+ const guidesDir = join('.specsafe', 'e2e', 'guides');
94
+ await mkdir(guidesDir, { recursive: true });
95
+ const extension = outputFormat;
96
+ outputPath = join(guidesDir, `test-guide-${specId}.${extension}`);
97
+ }
98
+ await mkdir(dirname(outputPath), { recursive: true });
99
+ await writeFile(outputPath, output, 'utf-8');
100
+ console.log(chalk.green(`\n✅ Test guide generated: ${outputPath}`));
101
+ console.log(chalk.blue('\nGuide Summary:'));
102
+ console.log(` Mode: ${mode}`);
103
+ console.log(` Scenarios: ${guide.scenarios.length}`);
104
+ console.log(` Steps: ${guide.scenarios.reduce((sum, s) => sum + s.steps.length, 0)}`);
105
+ console.log(` P0 (Critical): ${guide.scenarios.filter(s => s.priority === 'P0').length}`);
106
+ console.log(` P1 (High): ${guide.scenarios.filter(s => s.priority === 'P1').length}`);
107
+ console.log(` P2 (Normal): ${guide.scenarios.filter(s => s.priority === 'P2').length}`);
108
+ console.log(chalk.blue('\nNext steps:'));
109
+ if (mode === 'playwright') {
110
+ console.log(chalk.gray(` 1. Run generated script with: npx playwright test ${outputPath}`));
111
+ console.log(chalk.gray(' 2. Review screenshots captured at configured intervals'));
112
+ console.log(chalk.gray(' 3. Validate assertions and adjust selectors as needed'));
113
+ }
114
+ else {
115
+ console.log(chalk.gray(` 1. Review the test guide: ${outputPath}`));
116
+ console.log(chalk.gray(' 2. Execute test scenarios manually'));
117
+ console.log(chalk.gray(' 3. Take screenshots at key steps'));
118
+ console.log(chalk.gray(` 4. Submit for analysis: specsafe test-submit ${specId} --screenshots ./my-screenshots/`));
119
+ }
120
+ }
121
+ catch (error) {
122
+ spinner.fail(chalk.red(error.message));
123
+ if (error.message.includes('not found')) {
124
+ console.log(chalk.gray(`\n💡 Tip: Create a spec first with 'specsafe new <name>'`));
125
+ }
126
+ process.exit(1);
127
+ }
128
+ });
129
+ function parseSpecFromContent(specId, content) {
130
+ const safeContent = content.slice(0, 500_000);
131
+ const nameMatch = safeContent.match(/^#\s+(.+?)(?:\s+Specification)?$/m);
132
+ const name = nameMatch ? nameMatch[1] : specId;
133
+ const descMatch = safeContent.match(/## Overview\n+([\s\S]*?)(?=##|$)/);
134
+ const description = descMatch ? descMatch[1].trim() : '';
135
+ const requirements = [];
136
+ const tableMatch = safeContent.match(/\| ID \| Requirement \| Priority \|[^|]+\|\n\|[-\s|]+\|\n([\s\S]*?)(?=\n## |\n### |$)/);
137
+ if (tableMatch) {
138
+ const rows = tableMatch[1].trim().split('\n');
139
+ for (const row of rows) {
140
+ const cells = row.split('|').map(c => c.trim()).filter(Boolean);
141
+ if (cells.length >= 3) {
142
+ const [id, text, priority] = cells;
143
+ requirements.push({ id, text, priority: priority || 'P1', scenarios: [] });
144
+ }
145
+ }
146
+ }
147
+ const scenariosMatch = safeContent.match(/## \d+\.\s*Scenarios\n+([\s\S]*?)(?=## \d+\.|$)/);
148
+ if (scenariosMatch) {
149
+ const scenarioBlocks = scenariosMatch[1].split(/### Scenario \d+:/);
150
+ for (let i = 0; i < scenarioBlocks.length; i++) {
151
+ const block = scenarioBlocks[i];
152
+ const givenMatch = block.match(/[-*]\s*\*\*Given\*\*\s*(.+)/i);
153
+ const whenMatch = block.match(/[-*]\s*\*\*When\*\*\s*(.+)/i);
154
+ const thenMatch = block.match(/[-*]\s*\*\*Then\*\*\s*(.+)/i);
155
+ if (givenMatch && whenMatch && thenMatch) {
156
+ const scenario = {
157
+ id: `SC-${i + 1}`,
158
+ given: givenMatch[1].trim(),
159
+ when: whenMatch[1].trim(),
160
+ thenOutcome: thenMatch[1].trim(),
161
+ };
162
+ if (requirements.length > 0)
163
+ requirements[0].scenarios.push(scenario);
164
+ else
165
+ requirements.push({ id: 'FR-1', text: 'Generated from scenarios', priority: 'P1', scenarios: [scenario] });
166
+ }
167
+ }
168
+ }
169
+ if (requirements.length === 0) {
170
+ requirements.push({
171
+ id: 'FR-1',
172
+ text: 'Feature implementation matches spec',
173
+ priority: 'P0',
174
+ scenarios: [{ id: 'SC-1', given: 'user accesses the feature', when: 'user interacts with the feature', thenOutcome: 'feature behaves as specified' }],
175
+ });
176
+ }
177
+ return {
178
+ id: specId,
179
+ name,
180
+ description,
181
+ stage: 'spec',
182
+ createdAt: new Date(),
183
+ updatedAt: new Date(),
184
+ requirements,
185
+ testFiles: [],
186
+ implementationFiles: [],
187
+ metadata: { author: 'unknown', project: 'unknown', tags: [] },
188
+ };
189
+ }
190
+ //# sourceMappingURL=test-guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-guide.js","sourceRoot":"","sources":["../../src/commands/test-guide.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const testReportCommand: Command;
3
+ //# sourceMappingURL=test-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-report.d.ts","sourceRoot":"","sources":["../../src/commands/test-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,eAAO,MAAM,iBAAiB,SA0F1B,CAAC"}
@@ -0,0 +1,196 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { readFile, readdir } from 'fs/promises';
4
+ import { join } from 'path';
5
+ import { existsSync } from 'fs';
6
+ function validateSpecId(specId) {
7
+ if (!/^[A-Za-z0-9_-]+$/.test(specId)) {
8
+ throw new Error('Invalid spec ID. Use only letters, numbers, dash, and underscore.');
9
+ }
10
+ return specId;
11
+ }
12
+ export const testReportCommand = new Command('test-report')
13
+ .description('View E2E test report for a spec')
14
+ .argument('<spec>', 'Spec ID')
15
+ .option('-l, --latest', 'Show only the latest report', true)
16
+ .option('--json', 'Output as JSON')
17
+ .option('--all', 'Show all reports for this spec')
18
+ .action(async (specId, options) => {
19
+ try {
20
+ specId = validateSpecId(specId);
21
+ const reportsDir = join('.specsafe', 'e2e', 'reports');
22
+ if (!existsSync(reportsDir)) {
23
+ console.log(chalk.yellow('\n⚠️ No reports directory found.'));
24
+ console.log(chalk.gray(' Run tests first: specsafe test-submit ' + specId + ' --screenshots ./screenshots/'));
25
+ return;
26
+ }
27
+ // Find reports for this spec
28
+ const files = await readdir(reportsDir);
29
+ const reportFiles = files.filter(f => f.startsWith(specId) && f.endsWith('.json'));
30
+ if (reportFiles.length === 0) {
31
+ console.log(chalk.yellow(`\n⚠️ No reports found for spec: ${specId}`));
32
+ console.log(chalk.gray(' Run tests first: specsafe test-submit ' + specId + ' --screenshots ./screenshots/'));
33
+ return;
34
+ }
35
+ // Sort by modification time (latest first)
36
+ const reportsWithStats = await Promise.all(reportFiles.map(async (filename) => {
37
+ const path = join(reportsDir, filename);
38
+ const content = await readFile(path, 'utf-8');
39
+ const report = JSON.parse(content);
40
+ return { filename, report, path };
41
+ }));
42
+ reportsWithStats.sort((a, b) => new Date(b.report.createdAt).getTime() - new Date(a.report.createdAt).getTime());
43
+ if (options.all) {
44
+ // Show list of all reports
45
+ console.log(chalk.blue(`\n📊 Test Reports for ${specId}\n`));
46
+ console.log(`Found ${reportsWithStats.length} report(s):\n`);
47
+ for (let i = 0; i < reportsWithStats.length; i++) {
48
+ const { report, filename } = reportsWithStats[i];
49
+ const date = new Date(report.createdAt).toLocaleString();
50
+ const passRate = (report.summary.passRate * 100).toFixed(1);
51
+ const statusColor = report.summary.passRate === 1 ? chalk.green :
52
+ report.summary.passRate >= 0.8 ? chalk.yellow :
53
+ chalk.red;
54
+ console.log(`${i + 1}. ${filename}`);
55
+ console.log(` Date: ${date}`);
56
+ console.log(` Pass Rate: ${statusColor(passRate + '%')}`);
57
+ console.log(` Steps: ${report.summary.passed}/${report.summary.totalSteps} passed`);
58
+ if (report.summary.failed > 0) {
59
+ console.log(chalk.red(` Failed: ${report.summary.failed}`));
60
+ }
61
+ console.log();
62
+ }
63
+ console.log(chalk.gray('Use --latest to see the most recent report in detail.'));
64
+ return;
65
+ }
66
+ // Show latest report
67
+ const { report } = reportsWithStats[0];
68
+ if (options.json) {
69
+ console.log(JSON.stringify(report, null, 2));
70
+ return;
71
+ }
72
+ // Display formatted report
73
+ displayReport(report);
74
+ }
75
+ catch (error) {
76
+ console.error(chalk.red('Error:'), error.message);
77
+ process.exit(1);
78
+ }
79
+ });
80
+ /**
81
+ * Display a formatted test report
82
+ */
83
+ function displayReport(report) {
84
+ const { summary } = report;
85
+ // Header
86
+ console.log(chalk.blue('\n┌─────────────────────────────────────────────────────────────┐'));
87
+ console.log(chalk.blue('│ E2E Test Report │'));
88
+ console.log(chalk.blue('└─────────────────────────────────────────────────────────────┘\n'));
89
+ console.log(chalk.bold(`Spec ID: ${report.specId}`));
90
+ console.log(chalk.gray(`Report ID: ${report.reportId}`));
91
+ console.log(chalk.gray(`Submitted By: ${report.submittedBy}`));
92
+ console.log(chalk.gray(`Generated: ${new Date(report.createdAt).toLocaleString()}`));
93
+ console.log();
94
+ // Summary Box
95
+ const passRatePercent = (summary.passRate * 100).toFixed(1);
96
+ const passRateColor = summary.passRate === 1 ? chalk.green :
97
+ summary.passRate >= 0.8 ? chalk.yellow :
98
+ chalk.red;
99
+ console.log(chalk.bold('📊 Summary\n'));
100
+ console.log(` Total Scenarios: ${summary.totalScenarios}`);
101
+ console.log(` Total Steps: ${summary.totalSteps}`);
102
+ console.log();
103
+ console.log(` ${chalk.green('✅ Passed:')} ${summary.passed.toString().padStart(3)}`);
104
+ console.log(` ${chalk.red('❌ Failed:')} ${summary.failed.toString().padStart(3)}`);
105
+ console.log(` ${chalk.yellow('⚠️ Partial:')} ${summary.partial.toString().padStart(3)}`);
106
+ console.log(` ${chalk.gray('⏭️ Skipped:')} ${summary.skipped.toString().padStart(3)}`);
107
+ console.log();
108
+ console.log(` Pass Rate: ${passRateColor(passRatePercent + '%')}`);
109
+ console.log();
110
+ // Issues
111
+ if (summary.criticalIssues > 0 || summary.highIssues > 0 ||
112
+ summary.mediumIssues > 0 || summary.lowIssues > 0) {
113
+ console.log(chalk.bold('🚨 Issues Found\n'));
114
+ if (summary.criticalIssues > 0) {
115
+ console.log(chalk.red(` 🔴 Critical: ${summary.criticalIssues}`));
116
+ }
117
+ if (summary.highIssues > 0) {
118
+ console.log(chalk.red(` 🟠 High: ${summary.highIssues}`));
119
+ }
120
+ if (summary.mediumIssues > 0) {
121
+ console.log(chalk.yellow(` 🟡 Medium: ${summary.mediumIssues}`));
122
+ }
123
+ if (summary.lowIssues > 0) {
124
+ console.log(chalk.gray(` 🟢 Low: ${summary.lowIssues}`));
125
+ }
126
+ console.log();
127
+ }
128
+ // Recommendations
129
+ if (report.recommendations && report.recommendations.length > 0) {
130
+ console.log(chalk.bold('💡 Recommendations\n'));
131
+ for (const rec of report.recommendations) {
132
+ console.log(` ${rec}`);
133
+ }
134
+ console.log();
135
+ }
136
+ // Detailed Results
137
+ console.log(chalk.bold('📝 Detailed Results\n'));
138
+ // Group results by scenario
139
+ const resultsByScenario = new Map();
140
+ for (const result of report.results) {
141
+ if (!resultsByScenario.has(result.scenarioId)) {
142
+ resultsByScenario.set(result.scenarioId, []);
143
+ }
144
+ resultsByScenario.get(result.scenarioId).push(result);
145
+ }
146
+ for (const [scenarioId, results] of resultsByScenario) {
147
+ console.log(chalk.cyan(` Scenario: ${scenarioId}`));
148
+ for (const result of results) {
149
+ const icon = result.status === 'pass' ? chalk.green('✅') :
150
+ result.status === 'fail' ? chalk.red('❌') :
151
+ result.status === 'partial' ? chalk.yellow('⚠️') : chalk.gray('⏭️');
152
+ console.log(` ${icon} Step ${result.stepId}: ${result.analysis.substring(0, 60)}${result.analysis.length > 60 ? '...' : ''}`);
153
+ if (result.issues.length > 0) {
154
+ for (const issue of result.issues) {
155
+ const severityColor = issue.severity === 'critical' ? chalk.red :
156
+ issue.severity === 'high' ? chalk.red :
157
+ issue.severity === 'medium' ? chalk.yellow : chalk.gray;
158
+ console.log(severityColor(` • ${issue.severity.toUpperCase()}: ${issue.description}`));
159
+ }
160
+ }
161
+ }
162
+ console.log();
163
+ }
164
+ // Fix Suggestions
165
+ if (report.fixSuggestions && report.fixSuggestions.length > 0) {
166
+ console.log(chalk.bold('🔧 Suggested Fixes\n'));
167
+ for (const fix of report.fixSuggestions.slice(0, 5)) { // Show first 5
168
+ const priorityColor = fix.priority === 'P0' ? chalk.red :
169
+ fix.priority === 'P1' ? chalk.yellow : chalk.gray;
170
+ console.log(` ${priorityColor(`[${fix.priority}]`)} ${fix.scenarioId} - ${fix.stepId}`);
171
+ console.log(` Issue: ${fix.issue}`);
172
+ console.log(` Fix: ${fix.suggestion}`);
173
+ console.log();
174
+ }
175
+ if (report.fixSuggestions.length > 5) {
176
+ console.log(chalk.gray(` ... and ${report.fixSuggestions.length - 5} more suggestions`));
177
+ console.log();
178
+ }
179
+ }
180
+ // Footer
181
+ console.log(chalk.gray('─'.repeat(60)));
182
+ if (summary.passRate === 1) {
183
+ console.log(chalk.green('\n 🎉 All tests passed!'));
184
+ }
185
+ else if (summary.passRate >= 0.8) {
186
+ console.log(chalk.yellow('\n ⚠️ Most tests passed. Review the failures above.'));
187
+ }
188
+ else {
189
+ console.log(chalk.red('\n ❌ Significant issues found. Please fix and re-test.'));
190
+ }
191
+ // Location of full report
192
+ const markdownPath = join('.specsafe', 'e2e', 'reports', `${report.specId}-report.md`);
193
+ console.log(chalk.gray(`\n Full report: ${markdownPath}`));
194
+ console.log();
195
+ }
196
+ //# sourceMappingURL=test-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-report.js","sourceRoot":"","sources":["../../src/commands/test-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ export declare function validateSpecId(specId: string): string;
3
+ export declare function sanitizeRelativePath(input: string, label: string): string;
4
+ export declare function sanitizeFilename(filename: string): string;
5
+ export declare const testSubmitCommand: Command;
6
+ //# sourceMappingURL=test-submit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-submit.d.ts","sourceRoot":"","sources":["../../src/commands/test-submit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzD;AAYD,eAAO,MAAM,iBAAiB,SA6L1B,CAAC"}