@specsafe/cli 0.3.6 → 0.5.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/commands/apply.d.ts +3 -0
- package/dist/commands/apply.d.ts.map +1 -0
- package/dist/commands/apply.js +182 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/complete.d.ts.map +1 -1
- package/dist/commands/complete.js +4 -1
- package/dist/commands/complete.js.map +1 -1
- package/dist/commands/delta.d.ts +3 -0
- package/dist/commands/delta.d.ts.map +1 -0
- package/dist/commands/delta.js +82 -0
- package/dist/commands/delta.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +102 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/done.d.ts +3 -0
- package/dist/commands/done.d.ts.map +1 -0
- package/dist/commands/done.js +237 -0
- package/dist/commands/done.js.map +1 -0
- package/dist/commands/explore.d.ts +3 -0
- package/dist/commands/explore.d.ts.map +1 -0
- package/dist/commands/explore.js +236 -0
- package/dist/commands/explore.js.map +1 -0
- package/dist/commands/init-old.d.ts +3 -0
- package/dist/commands/init-old.d.ts.map +1 -0
- package/dist/commands/init-old.js +146 -0
- package/dist/commands/init-old.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +195 -43
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +332 -29
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/qa.d.ts.map +1 -1
- package/dist/commands/qa.js +37 -1
- package/dist/commands/qa.js.map +1 -1
- package/dist/commands/rules.d.ts.map +1 -1
- package/dist/commands/rules.js +182 -97
- package/dist/commands/rules.js.map +1 -1
- package/dist/commands/spec.d.ts.map +1 -1
- package/dist/commands/spec.js +257 -25
- package/dist/commands/spec.js.map +1 -1
- package/dist/commands/test-apply.d.ts +3 -0
- package/dist/commands/test-apply.d.ts.map +1 -0
- package/dist/commands/test-apply.js +228 -0
- package/dist/commands/test-apply.js.map +1 -0
- package/dist/commands/test-create.d.ts +3 -0
- package/dist/commands/test-create.d.ts.map +1 -0
- package/dist/commands/{test.js → test-create.js} +79 -30
- package/dist/commands/test-create.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +288 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -6
- package/dist/index.js.map +1 -1
- package/dist/utils/generateToolConfig.d.ts +1 -1
- package/dist/utils/generateToolConfig.d.ts.map +1 -1
- package/dist/utils/generateToolConfig.js +980 -209
- package/dist/utils/generateToolConfig.js.map +1 -1
- package/dist/utils/testRunner.d.ts +39 -0
- package/dist/utils/testRunner.d.ts.map +1 -0
- package/dist/utils/testRunner.js +325 -0
- package/dist/utils/testRunner.js.map +1 -0
- package/package.json +3 -3
- package/dist/commands/code.d.ts +0 -3
- package/dist/commands/code.d.ts.map +0 -1
- package/dist/commands/code.js +0 -53
- package/dist/commands/code.js.map +0 -1
- package/dist/commands/test.d.ts +0 -3
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js.map +0 -1
package/dist/commands/new.js
CHANGED
|
@@ -3,13 +3,16 @@ import chalk from 'chalk';
|
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import { writeFile, mkdir, readdir } from 'fs/promises';
|
|
5
5
|
import { join, basename } from 'path';
|
|
6
|
-
import { Workflow, ProjectTracker } from '@specsafe/core';
|
|
6
|
+
import { Workflow, ProjectTracker, generateEARSTemplate } from '@specsafe/core';
|
|
7
|
+
import { input, editor, select } from '@inquirer/prompts';
|
|
7
8
|
export const newCommand = new Command('new')
|
|
8
|
-
.description('Create a new spec')
|
|
9
|
-
.argument('
|
|
9
|
+
.description('Create a new spec with interactive PRD creation')
|
|
10
|
+
.argument('[name]', 'Spec name (kebab-case)')
|
|
10
11
|
.option('-d, --description <desc>', 'Spec description')
|
|
11
12
|
.option('-a, --author <author>', 'Author name', 'developer')
|
|
12
13
|
.option('-n, --dry-run', 'Preview changes without writing files')
|
|
14
|
+
.option('--skip-interactive', 'Skip interactive prompts and use defaults')
|
|
15
|
+
.option('--ears', 'Use EARS (Easy Approach to Requirements Syntax) template')
|
|
13
16
|
.action(async (name, options) => {
|
|
14
17
|
const spinner = ora('Creating new spec...').start();
|
|
15
18
|
try {
|
|
@@ -45,27 +48,176 @@ export const newCommand = new Command('new')
|
|
|
45
48
|
// Directory doesn't exist yet, that's fine
|
|
46
49
|
}
|
|
47
50
|
const id = `SPEC-${date}-${String(maxSuffix + 1).padStart(3, '0')}`;
|
|
51
|
+
// Interactive mode or defaults
|
|
52
|
+
spinner.stop();
|
|
53
|
+
// Get feature name if not provided
|
|
54
|
+
let featureName = name;
|
|
55
|
+
if (!featureName && !options.skipInteractive) {
|
|
56
|
+
featureName = await input({
|
|
57
|
+
message: 'Feature name (kebab-case):',
|
|
58
|
+
validate: (value) => value.length > 0 || 'Feature name is required'
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else if (!featureName) {
|
|
62
|
+
featureName = 'untitled-feature';
|
|
63
|
+
}
|
|
64
|
+
// Interactive PRD + BRD creation
|
|
65
|
+
let problemStatement = '';
|
|
66
|
+
let userStories = '';
|
|
67
|
+
let acceptanceCriteria = '';
|
|
68
|
+
let technicalConsiderations = '';
|
|
69
|
+
let businessJustification = '';
|
|
70
|
+
let successMetrics = '';
|
|
71
|
+
let stakeholders = '';
|
|
72
|
+
let timeline = '';
|
|
73
|
+
let priority = 'P1';
|
|
74
|
+
if (!options.skipInteractive && !options.dryRun && !options.ears) {
|
|
75
|
+
console.log(chalk.blue('\n📋 Let\'s create a Product Requirements Document (PRD)\n'));
|
|
76
|
+
problemStatement = await editor({
|
|
77
|
+
message: 'Problem Statement (what problem does this solve?):',
|
|
78
|
+
default: '<!-- Describe the problem this feature solves -->'
|
|
79
|
+
});
|
|
80
|
+
userStories = await editor({
|
|
81
|
+
message: 'User Stories (who benefits and how?):',
|
|
82
|
+
default: `As a [type of user]
|
|
83
|
+
I want [some goal]
|
|
84
|
+
So that [some reason]
|
|
85
|
+
|
|
86
|
+
<!-- Add more user stories as needed -->`
|
|
87
|
+
});
|
|
88
|
+
acceptanceCriteria = await editor({
|
|
89
|
+
message: 'Acceptance Criteria (how do we know it\'s done?):',
|
|
90
|
+
default: `- [ ] Criterion 1
|
|
91
|
+
- [ ] Criterion 2
|
|
92
|
+
- [ ] Criterion 3`
|
|
93
|
+
});
|
|
94
|
+
technicalConsiderations = await editor({
|
|
95
|
+
message: 'Technical Requirements (dependencies, constraints, stack):',
|
|
96
|
+
default: `<!-- Technical constraints, dependencies, integrations needed -->
|
|
97
|
+
- Required APIs:
|
|
98
|
+
- Data storage:
|
|
99
|
+
- Security requirements:`
|
|
100
|
+
});
|
|
101
|
+
console.log(chalk.blue('\n💼 Now let\'s create a Business Requirements Document (BRD)\n'));
|
|
102
|
+
businessJustification = await editor({
|
|
103
|
+
message: 'Business Justification (why invest in this?):',
|
|
104
|
+
default: `<!-- Why should we build this? Business value, market need, strategic alignment -->`
|
|
105
|
+
});
|
|
106
|
+
successMetrics = await editor({
|
|
107
|
+
message: 'Success Metrics (how do we measure success?):',
|
|
108
|
+
default: `- Metric 1: [e.g., "Reduce processing time by 50%"]
|
|
109
|
+
- Metric 2: [e.g., "Increase user engagement by 20%"]
|
|
110
|
+
- Metric 3: [e.g., "Zero critical bugs in production"]`
|
|
111
|
+
});
|
|
112
|
+
stakeholders = await editor({
|
|
113
|
+
message: 'Stakeholders (who cares about this?):',
|
|
114
|
+
default: `| Role | Name/Team | Responsibility |
|
|
115
|
+
|------|-----------|----------------|
|
|
116
|
+
| Product Owner | | Decision maker |
|
|
117
|
+
| Engineering Lead | | Technical oversight |
|
|
118
|
+
| QA Lead | | Quality assurance |`
|
|
119
|
+
});
|
|
120
|
+
timeline = await editor({
|
|
121
|
+
message: 'Timeline (key milestones):',
|
|
122
|
+
default: `| Phase | Milestone | Target Date |
|
|
123
|
+
|-------|-----------|-------------|
|
|
124
|
+
| 1 | Requirements final | |
|
|
125
|
+
| 2 | Development complete | |
|
|
126
|
+
| 3 | QA complete | |
|
|
127
|
+
| 4 | Release | |`
|
|
128
|
+
});
|
|
129
|
+
priority = await select({
|
|
130
|
+
message: 'Priority:',
|
|
131
|
+
choices: [
|
|
132
|
+
{ name: 'P0 - Critical (blocks release)', value: 'P0' },
|
|
133
|
+
{ name: 'P1 - High (should have)', value: 'P1' },
|
|
134
|
+
{ name: 'P2 - Medium (nice to have)', value: 'P2' },
|
|
135
|
+
],
|
|
136
|
+
default: 'P1'
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
spinner.start('Creating spec files...');
|
|
48
140
|
// Create spec
|
|
49
|
-
const spec = workflow.createSpec(id,
|
|
50
|
-
//
|
|
51
|
-
|
|
141
|
+
const spec = workflow.createSpec(id, featureName, options.description || `Spec for ${featureName}`, options.author, basename(process.cwd()));
|
|
142
|
+
// Use EARS template if requested
|
|
143
|
+
let specContent;
|
|
144
|
+
if (options.ears) {
|
|
145
|
+
specContent = generateEARSTemplate(id, featureName, options.author, priority);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// Create PRD + BRD-enhanced spec content
|
|
149
|
+
specContent = `# ${featureName} Specification
|
|
52
150
|
|
|
53
|
-
**ID:** ${id}
|
|
54
|
-
**Status:** SPEC
|
|
55
|
-
**Created:** ${new Date().toISOString().split('T')[0]}
|
|
151
|
+
**ID:** ${id}
|
|
152
|
+
**Status:** SPEC
|
|
153
|
+
**Created:** ${new Date().toISOString().split('T')[0]}
|
|
56
154
|
**Author:** ${options.author}
|
|
155
|
+
**Priority:** ${priority}
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## PRD (Product Requirements Document)
|
|
160
|
+
|
|
161
|
+
### Problem Statement
|
|
162
|
+
${problemStatement || '<!-- Describe the problem this feature solves -->'}
|
|
163
|
+
|
|
164
|
+
### User Stories
|
|
165
|
+
${userStories || `As a [type of user]
|
|
166
|
+
I want [some goal]
|
|
167
|
+
So that [some reason]
|
|
168
|
+
|
|
169
|
+
<!-- Add more user stories as needed -->`}
|
|
170
|
+
|
|
171
|
+
### Acceptance Criteria
|
|
172
|
+
${acceptanceCriteria || `- [ ] Criterion 1
|
|
173
|
+
- [ ] Criterion 2
|
|
174
|
+
- [ ] Criterion 3`}
|
|
175
|
+
|
|
176
|
+
### Technical Requirements
|
|
177
|
+
${technicalConsiderations || `<!-- Technical constraints, dependencies, integrations needed -->
|
|
178
|
+
- Required APIs:
|
|
179
|
+
- Data storage:
|
|
180
|
+
- Security requirements:`}
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## BRD (Business Requirements Document)
|
|
185
|
+
|
|
186
|
+
### Business Justification
|
|
187
|
+
${businessJustification || '<!-- Why should we build this? Business value, market need, strategic alignment -->'}
|
|
188
|
+
|
|
189
|
+
### Success Metrics
|
|
190
|
+
${successMetrics || `- Metric 1: [e.g., "Reduce processing time by 50%"]
|
|
191
|
+
- Metric 2: [e.g., "Increase user engagement by 20%"]
|
|
192
|
+
- Metric 3: [e.g., "Zero critical bugs in production"]`}
|
|
193
|
+
|
|
194
|
+
### Stakeholders
|
|
195
|
+
${stakeholders || `| Role | Name/Team | Responsibility |
|
|
196
|
+
|------|-----------|----------------|
|
|
197
|
+
| Product Owner | | Decision maker |
|
|
198
|
+
| Engineering Lead | | Technical oversight |
|
|
199
|
+
| QA Lead | | Quality assurance |`}
|
|
200
|
+
|
|
201
|
+
### Timeline
|
|
202
|
+
${timeline || `| Phase | Milestone | Target Date |
|
|
203
|
+
|-------|-----------|-------------|
|
|
204
|
+
| 1 | Requirements final | |
|
|
205
|
+
| 2 | Development complete | |
|
|
206
|
+
| 3 | QA complete | |
|
|
207
|
+
| 4 | Release | |`}
|
|
57
208
|
|
|
58
|
-
|
|
59
|
-
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Scope (WHAT)
|
|
60
212
|
|
|
61
|
-
## 2. Scope (WHAT)
|
|
62
213
|
### In Scope
|
|
63
|
-
-
|
|
214
|
+
-
|
|
64
215
|
|
|
65
216
|
### Out of Scope
|
|
66
|
-
-
|
|
217
|
+
-
|
|
218
|
+
|
|
219
|
+
## Requirements
|
|
67
220
|
|
|
68
|
-
## 3. Requirements
|
|
69
221
|
### Functional Requirements
|
|
70
222
|
| ID | Requirement | Priority | Acceptance Criteria |
|
|
71
223
|
|----|-------------|----------|---------------------|
|
|
@@ -76,56 +228,203 @@ export const newCommand = new Command('new')
|
|
|
76
228
|
|----|-------------|--------|
|
|
77
229
|
| NFR-1 | | |
|
|
78
230
|
|
|
79
|
-
##
|
|
231
|
+
## Scenarios (Given/When/Then)
|
|
232
|
+
|
|
233
|
+
### Scenario 1: [Name]
|
|
234
|
+
- **Given** [initial context]
|
|
235
|
+
- **When** [action/event occurs]
|
|
236
|
+
- **Then** [expected outcome]
|
|
237
|
+
|
|
238
|
+
## Technical Approach (HOW)
|
|
239
|
+
|
|
240
|
+
### Tech Stack
|
|
241
|
+
<!-- Refer to .specsafe/tech-stack.md -->
|
|
242
|
+
|
|
243
|
+
### Architecture
|
|
244
|
+
|
|
245
|
+
### Dependencies
|
|
246
|
+
|
|
247
|
+
## Test Strategy (TDD)
|
|
80
248
|
|
|
81
|
-
## 5. Test Strategy (TDD)
|
|
82
249
|
### Unit Tests
|
|
83
|
-
-
|
|
250
|
+
-
|
|
84
251
|
|
|
85
252
|
### Integration Tests
|
|
86
|
-
-
|
|
253
|
+
-
|
|
254
|
+
|
|
255
|
+
## Implementation Plan
|
|
87
256
|
|
|
88
|
-
## 6. Implementation Plan
|
|
89
257
|
| Phase | Task | Est. Time | Dependencies |
|
|
90
258
|
|-------|------|-----------|--------------|
|
|
91
259
|
| 1 | | | |
|
|
92
260
|
|
|
93
|
-
##
|
|
261
|
+
## Success Criteria
|
|
94
262
|
- [ ] All P0 requirements met
|
|
95
263
|
- [ ] All tests passing
|
|
96
264
|
- [ ] Documentation complete
|
|
97
265
|
|
|
98
|
-
##
|
|
266
|
+
## Risks & Mitigations
|
|
267
|
+
|
|
99
268
|
| Risk | Probability | Impact | Mitigation |
|
|
100
269
|
|------|-------------|--------|------------|
|
|
101
270
|
| | | | |
|
|
102
271
|
|
|
103
|
-
##
|
|
104
|
-
-
|
|
272
|
+
## Notes & References
|
|
273
|
+
-
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
*Generated by SpecSafe v0.4.0 - OpenSpec Workflow*
|
|
105
278
|
`;
|
|
279
|
+
}
|
|
106
280
|
const specPath = join('specs/active', `${id}.md`);
|
|
107
281
|
// Handle dry-run mode
|
|
108
282
|
if (options.dryRun) {
|
|
109
283
|
spinner.stop();
|
|
110
284
|
console.log(chalk.cyan('[DRY RUN] Would create the following files:\n'));
|
|
111
285
|
console.log(chalk.cyan(` ${specPath}`));
|
|
112
|
-
console.log(chalk.cyan(`\nContent preview (first
|
|
113
|
-
const previewLines = specContent.split('\n').slice(0,
|
|
286
|
+
console.log(chalk.cyan(`\nContent preview (first 30 lines):\n`));
|
|
287
|
+
const previewLines = specContent.split('\n').slice(0, 30).join('\n');
|
|
114
288
|
console.log(chalk.gray(previewLines));
|
|
115
|
-
if (specContent.split('\n').length >
|
|
289
|
+
if (specContent.split('\n').length > 30) {
|
|
116
290
|
console.log(chalk.gray(' ... (truncated)'));
|
|
117
291
|
}
|
|
118
292
|
console.log(chalk.cyan(`\nWould update PROJECT_STATE.md with spec: ${id}`));
|
|
119
293
|
process.exit(0);
|
|
120
294
|
}
|
|
295
|
+
// Create .specsafe directory and supporting files
|
|
296
|
+
await mkdir('.specsafe', { recursive: true });
|
|
297
|
+
// Create tech-stack.md if it doesn't exist
|
|
298
|
+
const techStackPath = join('.specsafe', 'tech-stack.md');
|
|
299
|
+
const techStackContent = `# Tech Stack
|
|
300
|
+
|
|
301
|
+
**Project:** ${basename(process.cwd())}
|
|
302
|
+
**Last Updated:** ${new Date().toISOString().split('T')[0]}
|
|
303
|
+
|
|
304
|
+
## Core Technologies
|
|
305
|
+
|
|
306
|
+
| Category | Technology | Version | Purpose |
|
|
307
|
+
|----------|------------|---------|---------|
|
|
308
|
+
| Language | TypeScript | ^5.0 | Primary language |
|
|
309
|
+
| Testing | Vitest | ^1.0 | Unit testing |
|
|
310
|
+
| Linting | ESLint | ^8.0 | Code quality |
|
|
311
|
+
|
|
312
|
+
## Project Structure
|
|
313
|
+
|
|
314
|
+
\`\`\`
|
|
315
|
+
src/
|
|
316
|
+
├── components/ # UI components
|
|
317
|
+
├── utils/ # Utility functions
|
|
318
|
+
└── index.ts # Entry point
|
|
319
|
+
|
|
320
|
+
tests/
|
|
321
|
+
└── *.test.ts # Test files
|
|
322
|
+
|
|
323
|
+
specs/
|
|
324
|
+
├── active/ # Active specs
|
|
325
|
+
├── completed/ # Completed specs
|
|
326
|
+
└── archive/ # Archived specs
|
|
327
|
+
\`\`\`
|
|
328
|
+
|
|
329
|
+
## Dependencies
|
|
330
|
+
|
|
331
|
+
### Production
|
|
332
|
+
- None yet
|
|
333
|
+
|
|
334
|
+
### Development
|
|
335
|
+
- @specsafe/core
|
|
336
|
+
- @specsafe/cli
|
|
337
|
+
- @specsafe/test-gen
|
|
338
|
+
|
|
339
|
+
## Guidelines
|
|
340
|
+
|
|
341
|
+
1. Follow existing code patterns
|
|
342
|
+
2. Write tests before implementation
|
|
343
|
+
3. Update specs as requirements change
|
|
344
|
+
4. Use TypeScript strict mode
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
*Auto-generated by specsafe new*
|
|
349
|
+
`;
|
|
350
|
+
// Create rules.md if it doesn't exist
|
|
351
|
+
const rulesContent = `# Project Rules
|
|
352
|
+
|
|
353
|
+
**Project:** ${basename(process.cwd())}
|
|
354
|
+
**Last Updated:** ${new Date().toISOString().split('T')[0]}
|
|
355
|
+
|
|
356
|
+
## Coding Standards
|
|
357
|
+
|
|
358
|
+
1. **TypeScript First**: All code must be TypeScript with strict mode enabled
|
|
359
|
+
2. **Test-Driven**: Write tests before implementation
|
|
360
|
+
3. **Documentation**: Document all public APIs
|
|
361
|
+
4. **Error Handling**: Always handle errors gracefully
|
|
362
|
+
|
|
363
|
+
## SpecSafe Workflow Rules
|
|
364
|
+
|
|
365
|
+
1. **SPEC Stage**: Requirements must be clear and testable
|
|
366
|
+
2. **TEST Stage**: All tests must be written before code
|
|
367
|
+
3. **CODE Stage**: Implementation follows tests exactly
|
|
368
|
+
4. **QA Stage**: All tests must pass before completion
|
|
369
|
+
5. **COMPLETE Stage**: Archive spec after completion
|
|
370
|
+
|
|
371
|
+
## AI Assistant Guidelines
|
|
372
|
+
|
|
373
|
+
When assisting with this project:
|
|
374
|
+
|
|
375
|
+
1. Always read the relevant spec before making changes
|
|
376
|
+
2. Follow the acceptance criteria in the PRD
|
|
377
|
+
3. Update spec status as work progresses
|
|
378
|
+
4. Suggest running \`specsafe verify\` after changes
|
|
379
|
+
5. Respect the out-of-scope section
|
|
380
|
+
|
|
381
|
+
## Communication Style
|
|
382
|
+
|
|
383
|
+
- Be concise but thorough
|
|
384
|
+
- Provide code examples when helpful
|
|
385
|
+
- Explain the "why" behind suggestions
|
|
386
|
+
- Flag any spec violations immediately
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
*Auto-generated by specsafe new*
|
|
391
|
+
`;
|
|
121
392
|
// Create spec file
|
|
122
393
|
await mkdir('specs/active', { recursive: true });
|
|
123
394
|
await writeFile(specPath, specContent);
|
|
395
|
+
// Create supporting files (only if they don't exist)
|
|
396
|
+
try {
|
|
397
|
+
await writeFile(techStackPath, techStackContent, { flag: 'wx' });
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
// File already exists, skip
|
|
401
|
+
}
|
|
402
|
+
try {
|
|
403
|
+
await writeFile(join('.specsafe', 'rules.md'), rulesContent, { flag: 'wx' });
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
// File already exists, skip
|
|
407
|
+
}
|
|
124
408
|
// Update project state
|
|
125
409
|
await tracker.addSpec(spec);
|
|
126
|
-
spinner.succeed(chalk.green(`Created spec: ${id}`));
|
|
410
|
+
spinner.succeed(chalk.green(`Created spec: ${id}${options.ears ? ' (EARS format)' : ''}`));
|
|
127
411
|
console.log(chalk.blue(` Location: ${specPath}`));
|
|
128
|
-
console.log(chalk.
|
|
412
|
+
console.log(chalk.blue(` Tech Stack: .specsafe/tech-stack.md`));
|
|
413
|
+
console.log(chalk.blue(` Rules: .specsafe/rules.md`));
|
|
414
|
+
if (options.ears) {
|
|
415
|
+
console.log(chalk.green('\n ✨ Using EARS (Easy Approach to Requirements Syntax)'));
|
|
416
|
+
console.log(chalk.gray(' EARS patterns make requirements testable by construction'));
|
|
417
|
+
}
|
|
418
|
+
console.log(chalk.gray('\n Next steps:'));
|
|
419
|
+
console.log(chalk.gray(` 1. Edit ${specPath} to refine requirements`));
|
|
420
|
+
if (options.ears) {
|
|
421
|
+
console.log(chalk.gray(` 2. Follow EARS patterns in the template`));
|
|
422
|
+
console.log(chalk.gray(` 3. Run: specsafe qa ${id} --ears (to validate EARS compliance)`));
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
console.log(chalk.gray(` 2. Run: specsafe spec ${id}`));
|
|
426
|
+
console.log(chalk.gray(` 3. Or explore: specsafe explore`));
|
|
427
|
+
}
|
|
129
428
|
}
|
|
130
429
|
catch (error) {
|
|
131
430
|
spinner.fail(chalk.red(`Failed to create spec: ${error.message}`));
|
|
@@ -135,6 +434,10 @@ export const newCommand = new Command('new')
|
|
|
135
434
|
else if (error.message.includes('already exists')) {
|
|
136
435
|
console.log(chalk.gray('💡 Tip: Use a different spec name or delete the existing spec first.'));
|
|
137
436
|
}
|
|
437
|
+
else if (error.message.includes('User force closed')) {
|
|
438
|
+
console.log(chalk.gray('💡 Tip: Creation was cancelled.'));
|
|
439
|
+
process.exit(0);
|
|
440
|
+
}
|
|
138
441
|
process.exit(1);
|
|
139
442
|
}
|
|
140
443
|
});
|
package/dist/commands/new.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAW,MAAM,mBAAmB,CAAC;AAEnE,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC;KACzC,WAAW,CAAC,iDAAiD,CAAC;KAC9D,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC5C,MAAM,CAAC,0BAA0B,EAAE,kBAAkB,CAAC;KACtD,MAAM,CAAC,uBAAuB,EAAE,aAAa,EAAE,WAAW,CAAC;KAC3D,MAAM,CAAC,eAAe,EAAE,uCAAuC,CAAC;KAChE,MAAM,CAAC,oBAAoB,EAAE,2CAA2C,CAAC;KACzE,MAAM,CAAC,QAAQ,EAAE,0DAA0D,CAAC;KAC5E,MAAM,CAAC,KAAK,EAAE,IAAwB,EAAE,OAA8G,EAAE,EAAE;IACzJ,MAAM,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAElD,2DAA2D;QAC3D,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAEtE,yCAAyC;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;YAC7G,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,oDAAoD;QACpD,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,QAAQ,IAAI,GAAG,CAAC;YACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC9E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;wBACzC,SAAS,GAAG,MAAM,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QAED,MAAM,EAAE,GAAG,QAAQ,IAAI,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QAEpE,+BAA+B;QAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,mCAAmC;QACnC,IAAI,WAAW,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;YAC7C,WAAW,GAAG,MAAM,KAAK,CAAC;gBACxB,OAAO,EAAE,4BAA4B;gBACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,0BAA0B;aACpE,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACxB,WAAW,GAAG,kBAAkB,CAAC;QACnC,CAAC;QAED,iCAAiC;QACjC,IAAI,gBAAgB,GAAG,EAAE,CAAC;QAC1B,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,IAAI,kBAAkB,GAAG,EAAE,CAAC;QAC5B,IAAI,uBAAuB,GAAG,EAAE,CAAC;QACjC,IAAI,qBAAqB,GAAG,EAAE,CAAC;QAC/B,IAAI,cAAc,GAAG,EAAE,CAAC;QACxB,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,QAAQ,GAAuB,IAAI,CAAC;QAExC,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC,CAAC;YAEtF,gBAAgB,GAAG,MAAM,MAAM,CAAC;gBAC9B,OAAO,EAAE,oDAAoD;gBAC7D,OAAO,EAAE,mDAAmD;aAC7D,CAAC,CAAC;YAEH,WAAW,GAAG,MAAM,MAAM,CAAC;gBACzB,OAAO,EAAE,uCAAuC;gBAChD,OAAO,EAAE;;;;yCAIsB;aAChC,CAAC,CAAC;YAEH,kBAAkB,GAAG,MAAM,MAAM,CAAC;gBAChC,OAAO,EAAE,mDAAmD;gBAC5D,OAAO,EAAE;;kBAED;aACT,CAAC,CAAC;YAEH,uBAAuB,GAAG,MAAM,MAAM,CAAC;gBACrC,OAAO,EAAE,4DAA4D;gBACrE,OAAO,EAAE;;;yBAGM;aAChB,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC,CAAC;YAE3F,qBAAqB,GAAG,MAAM,MAAM,CAAC;gBACnC,OAAO,EAAE,+CAA+C;gBACxD,OAAO,EAAE,qFAAqF;aAC/F,CAAC,CAAC;YAEH,cAAc,GAAG,MAAM,MAAM,CAAC;gBAC5B,OAAO,EAAE,+CAA+C;gBACxD,OAAO,EAAE;;uDAEoC;aAC9C,CAAC,CAAC;YAEH,YAAY,GAAG,MAAM,MAAM,CAAC;gBAC1B,OAAO,EAAE,uCAAuC;gBAChD,OAAO,EAAE;;;;kCAIe;aACzB,CAAC,CAAC;YAEH,QAAQ,GAAG,MAAM,MAAM,CAAC;gBACtB,OAAO,EAAE,4BAA4B;gBACrC,OAAO,EAAE;;;;;kBAKD;aACT,CAAC,CAAC;YAEH,QAAQ,GAAG,MAAM,MAAM,CAAC;gBACtB,OAAO,EAAE,WAAW;gBACpB,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,gCAAgC,EAAE,KAAK,EAAE,IAAI,EAAE;oBACvD,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,IAAI,EAAE;oBAChD,EAAE,IAAI,EAAE,4BAA4B,EAAE,KAAK,EAAE,IAAI,EAAE;iBACpD;gBACD,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAExC,cAAc;QACd,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAC9B,EAAE,EACF,WAAW,EACX,OAAO,CAAC,WAAW,IAAI,YAAY,WAAW,EAAE,EAChD,OAAO,CAAC,MAAM,EACd,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CACxB,CAAC;QAEF,iCAAiC;QACjC,IAAI,WAAmB,CAAC;QACxB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,WAAW,GAAG,oBAAoB,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAChF,CAAC;aAAM,CAAC;YACN,yCAAyC;YACzC,WAAW,GAAG,KAAK,WAAW;;UAE5B,EAAE;;eAEG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;cACvC,OAAO,CAAC,MAAM;gBACZ,QAAQ;;;;;;;EAOtB,gBAAgB,IAAI,mDAAmD;;;EAGvE,WAAW,IAAI;;;;yCAIwB;;;EAGvC,kBAAkB,IAAI;;kBAEN;;;EAGhB,uBAAuB,IAAI;;;yBAGJ;;;;;;;EAOvB,qBAAqB,IAAI,qFAAqF;;;EAG9G,cAAc,IAAI;;uDAEmC;;;EAGrD,YAAY,IAAI;;;;kCAIgB;;;EAGhC,QAAQ,IAAI;;;;;kBAKI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuEjB,CAAC;QACI,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAElD,sBAAsB;QACtB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;YACjE,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACtC,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8CAA8C,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,kDAAkD;QAClD,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,2CAA2C;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAEzD,MAAM,gBAAgB,GAAG;;eAEhB,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;oBAClB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CzD,CAAC;QAEI,sCAAsC;QACtC,MAAM,YAAY,GAAG;;eAEZ,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;oBAClB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCzD,CAAC;QAEI,mBAAmB;QACnB,MAAM,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAEvC,qDAAqD;QACrD,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,aAAa,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,4BAA4B;QAC9B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,4BAA4B;QAC9B,CAAC;QAED,uBAAuB;QACvB,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE5B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACvD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC,CAAC;YACpF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,QAAQ,yBAAyB,CAAC,CAAC,CAAC;QAC1E,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,EAAE,uCAAuC,CAAC,CAAC,CAAC;QAChG,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACnE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC,CAAC;QAC1F,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC,CAAC;QAClG,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qa.d.ts","sourceRoot":"","sources":["../../src/commands/qa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"qa.d.ts","sourceRoot":"","sources":["../../src/commands/qa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,SAAS,SA4KlB,CAAC"}
|
package/dist/commands/qa.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { Workflow, ProjectTracker, validateSpecId } from '@specsafe/core';
|
|
4
|
+
import { Workflow, ProjectTracker, validateSpecId, generateEARSReport, getEARSScore } from '@specsafe/core';
|
|
5
5
|
import { exec } from 'child_process';
|
|
6
6
|
import { promisify } from 'util';
|
|
7
7
|
import { writeFile, mkdir } from 'fs/promises';
|
|
@@ -11,6 +11,7 @@ export const qaCommand = new Command('qa')
|
|
|
11
11
|
.description('Run QA validation (CODE → QA)')
|
|
12
12
|
.argument('<id>', 'Spec ID')
|
|
13
13
|
.option('-o, --output <path>', 'Output path for QA report')
|
|
14
|
+
.option('--ears', 'Validate EARS compliance and generate EARS report')
|
|
14
15
|
.action(async (id, options) => {
|
|
15
16
|
const spinner = ora(`Running QA for ${id}...`).start();
|
|
16
17
|
try {
|
|
@@ -108,11 +109,34 @@ export const qaCommand = new Command('qa')
|
|
|
108
109
|
await mkdir('qa-reports', { recursive: true });
|
|
109
110
|
const reportPath = options.output || join('qa-reports', `qa-${id}.json`);
|
|
110
111
|
await writeFile(reportPath, JSON.stringify(qaReport, null, 2));
|
|
112
|
+
// EARS validation if requested
|
|
113
|
+
let earsScore;
|
|
114
|
+
let earsReportPath;
|
|
115
|
+
if (options.ears) {
|
|
116
|
+
spinner.text = `Validating EARS compliance for ${id}...`;
|
|
117
|
+
const spec = workflow.getSpec(id);
|
|
118
|
+
earsScore = getEARSScore(spec);
|
|
119
|
+
const earsReport = generateEARSReport(spec);
|
|
120
|
+
earsReportPath = join('qa-reports', `ears-${id}.md`);
|
|
121
|
+
await writeFile(earsReportPath, earsReport);
|
|
122
|
+
}
|
|
111
123
|
// Persist state
|
|
112
124
|
await tracker.addSpec(workflow.getSpec(id));
|
|
113
125
|
if (qaReport.recommendation === 'GO') {
|
|
114
126
|
spinner.succeed(chalk.green(`✅ QA passed for ${id}`));
|
|
115
127
|
console.log(chalk.blue(` Report: ${reportPath}`));
|
|
128
|
+
if (options.ears && earsScore !== undefined) {
|
|
129
|
+
console.log(chalk.blue(` EARS Report: ${earsReportPath}`));
|
|
130
|
+
if (earsScore >= 90) {
|
|
131
|
+
console.log(chalk.green(` EARS Score: ${earsScore}/100 ✅`));
|
|
132
|
+
}
|
|
133
|
+
else if (earsScore >= 70) {
|
|
134
|
+
console.log(chalk.yellow(` EARS Score: ${earsScore}/100 ⚠️`));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log(chalk.red(` EARS Score: ${earsScore}/100 ❌`));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
116
140
|
console.log(chalk.green('Ready for completion!'));
|
|
117
141
|
console.log(chalk.blue(` Run: specsafe complete ${id} --report ${reportPath}`));
|
|
118
142
|
}
|
|
@@ -120,6 +144,18 @@ export const qaCommand = new Command('qa')
|
|
|
120
144
|
spinner.warn(chalk.yellow(`⚠️ QA issues found for ${id}`));
|
|
121
145
|
const issueDescs = qaReport.issues.map(i => i.description);
|
|
122
146
|
console.log(chalk.red(` Issues: ${issueDescs.join(', ')}`));
|
|
147
|
+
if (options.ears && earsScore !== undefined) {
|
|
148
|
+
console.log(chalk.blue(` EARS Report: ${earsReportPath}`));
|
|
149
|
+
if (earsScore >= 90) {
|
|
150
|
+
console.log(chalk.green(` EARS Score: ${earsScore}/100 ✅`));
|
|
151
|
+
}
|
|
152
|
+
else if (earsScore >= 70) {
|
|
153
|
+
console.log(chalk.yellow(` EARS Score: ${earsScore}/100 ⚠️`));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.log(chalk.red(` EARS Score: ${earsScore}/100 ❌`));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
123
159
|
console.log(chalk.blue('Fix issues and re-run: specsafe qa <id>'));
|
|
124
160
|
}
|
|
125
161
|
}
|
package/dist/commands/qa.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qa.js","sourceRoot":"","sources":["../../src/commands/qa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"qa.js","sourceRoot":"","sources":["../../src/commands/qa.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/commands/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/commands/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkFpC;;GAEG;AACH,eAAO,MAAM,YAAY,SA8MtB,CAAC"}
|