speckeeper 0.10.0 → 0.10.1
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/cli-contract.yaml +1 -1
- package/docs/design/cli-commands.md +181 -0
- package/docs/model-guide.md +102 -98
- package/package.json +1 -1
package/cli-contract.yaml
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
| init | Initialize a new speckeeper project with starter templates |
|
|
10
10
|
| new | Create a new element with auto-generated ID |
|
|
11
11
|
| scaffold | Generate _models/ from a mermaid flowchart definition |
|
|
12
|
+
| audit-requirements | Semantic requirement quality audit via LLM (verifiability, ambiguity, granularity, terminology, design-mixing) |
|
|
13
|
+
| propose-trace-links | Propose candidate traceability links between specs with confidence scores and rationale |
|
|
14
|
+
| explain-impact | Translate impact analysis JSON (from stdin) into human-readable explanation for PM/executive audiences |
|
|
15
|
+
| propose-acceptance-criteria | Propose testable acceptance criteria in Given/When/Then format for specified specs |
|
|
12
16
|
| impact | Analyze the change impact scope of a specified ID |
|
|
13
17
|
|
|
14
18
|
---
|
|
@@ -293,6 +297,183 @@ speckeeper scaffold -s spec.md --dry-run
|
|
|
293
297
|
|
|
294
298
|
---
|
|
295
299
|
|
|
300
|
+
## CMD-AUDIT-REQ: audit-requirements
|
|
301
|
+
|
|
302
|
+
Semantic requirement quality audit via LLM (verifiability, ambiguity, granularity, terminology, design-mixing)
|
|
303
|
+
|
|
304
|
+
### Usage
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
speckeeper audit-requirements [options]
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Parameters
|
|
311
|
+
|
|
312
|
+
| Name | Kind | Type | Required | Default | Description |
|
|
313
|
+
|------|------|------|----------|---------|-------------|
|
|
314
|
+
| -c, --config | option | path | | - | Path to config file |
|
|
315
|
+
| -a, --adapter | option | enum | | - | SDK adapter for LLM execution |
|
|
316
|
+
| --model | option | string | | - | LLM model override |
|
|
317
|
+
| -n, --dry-run | option | boolean | | false | Output constructed prompt without calling LLM |
|
|
318
|
+
| --fail-on | option | enum | | error | Minimum severity for non-zero exit |
|
|
319
|
+
| -o, --output | option | path | | - | Write result to file instead of stdout |
|
|
320
|
+
| --report-format | option | enum | | json | Output format for audit report |
|
|
321
|
+
| --show-prompt | option | boolean | | false | Display constructed LLM prompt on stderr |
|
|
322
|
+
|
|
323
|
+
### Examples
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
speckeeper audit-requirements
|
|
327
|
+
speckeeper audit-requirements --adapter openai --dry-run
|
|
328
|
+
speckeeper audit-requirements --report-format json --output audit.json
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Exit Codes
|
|
332
|
+
|
|
333
|
+
| Code | Description |
|
|
334
|
+
|------|-------------|
|
|
335
|
+
| 0 | No blocking findings |
|
|
336
|
+
| 1 | Unexpected error |
|
|
337
|
+
| 2 | Configuration or input error |
|
|
338
|
+
| 10 | Completed with blocking findings |
|
|
339
|
+
| 11 | Runtime dependency missing |
|
|
340
|
+
| 12 | LLM provider or adapter error |
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## CMD-PROPOSE-TRACE: propose-trace-links
|
|
345
|
+
|
|
346
|
+
Propose candidate traceability links between specs with confidence scores and rationale
|
|
347
|
+
|
|
348
|
+
### Usage
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
speckeeper propose-trace-links [options]
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Parameters
|
|
355
|
+
|
|
356
|
+
| Name | Kind | Type | Required | Default | Description |
|
|
357
|
+
|------|------|------|----------|---------|-------------|
|
|
358
|
+
| -c, --config | option | path | | - | Path to config file |
|
|
359
|
+
| -a, --adapter | option | enum | | - | SDK adapter for LLM execution |
|
|
360
|
+
| --model | option | string | | - | LLM model override |
|
|
361
|
+
| -n, --dry-run | option | boolean | | false | Output constructed prompt without calling LLM |
|
|
362
|
+
| --fail-on | option | enum | | error | Minimum severity for non-zero exit |
|
|
363
|
+
| -o, --output | option | path | | - | Write result to file instead of stdout |
|
|
364
|
+
| --report-format | option | enum | | json | Output format for report |
|
|
365
|
+
| --show-prompt | option | boolean | | false | Display constructed LLM prompt on stderr |
|
|
366
|
+
|
|
367
|
+
### Examples
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
speckeeper propose-trace-links
|
|
371
|
+
speckeeper propose-trace-links --adapter claude --report-format json
|
|
372
|
+
speckeeper propose-trace-links --dry-run
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Exit Codes
|
|
376
|
+
|
|
377
|
+
| Code | Description |
|
|
378
|
+
|------|-------------|
|
|
379
|
+
| 0 | No blocking findings |
|
|
380
|
+
| 1 | Unexpected error |
|
|
381
|
+
| 2 | Configuration or input error |
|
|
382
|
+
| 10 | Completed with blocking findings |
|
|
383
|
+
| 11 | Runtime dependency missing |
|
|
384
|
+
| 12 | LLM provider or adapter error |
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## CMD-EXPLAIN-IMPACT: explain-impact
|
|
389
|
+
|
|
390
|
+
Translate impact analysis JSON (from stdin) into human-readable explanation for PM/executive audiences
|
|
391
|
+
|
|
392
|
+
### Usage
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
speckeeper explain-impact [options]
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Parameters
|
|
399
|
+
|
|
400
|
+
| Name | Kind | Type | Required | Default | Description |
|
|
401
|
+
|------|------|------|----------|---------|-------------|
|
|
402
|
+
| -c, --config | option | path | | - | Path to config file |
|
|
403
|
+
| -a, --adapter | option | enum | | - | SDK adapter for LLM execution |
|
|
404
|
+
| --model | option | string | | - | LLM model override |
|
|
405
|
+
| -n, --dry-run | option | boolean | | false | Output constructed prompt without calling LLM |
|
|
406
|
+
| --fail-on | option | enum | | error | Minimum severity for non-zero exit |
|
|
407
|
+
| -o, --output | option | path | | - | Write result to file instead of stdout |
|
|
408
|
+
| --report-format | option | enum | | json | Output format for report |
|
|
409
|
+
| --show-prompt | option | boolean | | false | Display constructed LLM prompt on stderr |
|
|
410
|
+
|
|
411
|
+
### Examples
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
speckeeper impact FR-001 --format json | speckeeper explain-impact
|
|
415
|
+
speckeeper impact ENT-ORDER --format json | speckeeper explain-impact --adapter claude
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Exit Codes
|
|
419
|
+
|
|
420
|
+
| Code | Description |
|
|
421
|
+
|------|-------------|
|
|
422
|
+
| 0 | Explanation completed |
|
|
423
|
+
| 1 | Unexpected error |
|
|
424
|
+
| 2 | Configuration or input error |
|
|
425
|
+
| 3 | No input on stdin |
|
|
426
|
+
| 10 | Completed with blocking findings |
|
|
427
|
+
| 11 | Runtime dependency missing |
|
|
428
|
+
| 12 | LLM provider or adapter error |
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## CMD-PROPOSE-AC: propose-acceptance-criteria
|
|
433
|
+
|
|
434
|
+
Propose testable acceptance criteria in Given/When/Then format for specified specs
|
|
435
|
+
|
|
436
|
+
### Usage
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
speckeeper propose-acceptance-criteria [options]
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Parameters
|
|
443
|
+
|
|
444
|
+
| Name | Kind | Type | Required | Default | Description |
|
|
445
|
+
|------|------|------|----------|---------|-------------|
|
|
446
|
+
| <specIds> | argument | string | | - | Spec IDs to propose criteria for (defaults to all) |
|
|
447
|
+
| -c, --config | option | path | | - | Path to config file |
|
|
448
|
+
| -a, --adapter | option | enum | | - | SDK adapter for LLM execution |
|
|
449
|
+
| --model | option | string | | - | LLM model override |
|
|
450
|
+
| -n, --dry-run | option | boolean | | false | Output constructed prompt without calling LLM |
|
|
451
|
+
| --fail-on | option | enum | | error | Minimum severity for non-zero exit |
|
|
452
|
+
| -o, --output | option | path | | - | Write result to file instead of stdout |
|
|
453
|
+
| --report-format | option | enum | | json | Output format for report |
|
|
454
|
+
| --show-prompt | option | boolean | | false | Display constructed LLM prompt on stderr |
|
|
455
|
+
|
|
456
|
+
### Examples
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
speckeeper propose-acceptance-criteria
|
|
460
|
+
speckeeper propose-acceptance-criteria FR-001 FR-002
|
|
461
|
+
speckeeper propose-acceptance-criteria --adapter gemini --dry-run
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Exit Codes
|
|
465
|
+
|
|
466
|
+
| Code | Description |
|
|
467
|
+
|------|-------------|
|
|
468
|
+
| 0 | No blocking findings |
|
|
469
|
+
| 1 | Unexpected error |
|
|
470
|
+
| 2 | Configuration or input error |
|
|
471
|
+
| 10 | Completed with blocking findings |
|
|
472
|
+
| 11 | Runtime dependency missing |
|
|
473
|
+
| 12 | LLM provider or adapter error |
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
296
477
|
## CMD-IMPACT: impact
|
|
297
478
|
|
|
298
479
|
Analyze the change impact scope of a specified ID
|
package/docs/model-guide.md
CHANGED
|
@@ -109,7 +109,10 @@ export interface Exporter<T> {
|
|
|
109
109
|
format: 'markdown' | 'json' | 'mermaid';
|
|
110
110
|
single?: (spec: T) => string;
|
|
111
111
|
index?: (specs: T[]) => string;
|
|
112
|
+
/** Subdirectory under docsDir (used with single + index/index.md) */
|
|
112
113
|
outputDir?: string;
|
|
114
|
+
/** Direct output file path relative to docsDir (used with index-only exporters) */
|
|
115
|
+
outputFile?: string;
|
|
113
116
|
filename?: (spec: T) => string;
|
|
114
117
|
}
|
|
115
118
|
|
|
@@ -138,34 +141,31 @@ export interface CheckResult {
|
|
|
138
141
|
}>;
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Deep Validation (replaces per-model externalChecker)
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
/** OpenAPI deep validation mapping */
|
|
149
|
+
export interface OpenAPIValidationMapping {
|
|
150
|
+
path: string;
|
|
151
|
+
method?: string;
|
|
152
|
+
parameters?: Array<{ name: string; in?: string; type?: string }>;
|
|
153
|
+
responseProperties?: Array<{ name: string; type?: string }>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** DDL deep validation mapping */
|
|
157
|
+
export interface DDLValidationMapping {
|
|
158
|
+
tableName: string;
|
|
159
|
+
columns?: Array<{ name: string; type?: string }>;
|
|
160
|
+
checkTypes?: boolean;
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* Example: Whether TestRef covers acceptanceCriteria of Requirement
|
|
164
|
+
* Deep validation rule for a specific source type.
|
|
165
|
+
* The mapper extracts expected structure from a spec for detailed comparison
|
|
166
|
+
* against the matched source object.
|
|
164
167
|
*/
|
|
165
|
-
export interface
|
|
166
|
-
/** Target model ID for coverage (e.g. 'requirement') */
|
|
167
|
-
targetModel: string;
|
|
168
|
-
/** Description of coverage check */
|
|
168
|
+
export interface DeepValidationRule<T, TMapping = unknown> {
|
|
169
169
|
```
|
|
170
170
|
<!--@embedoc:end-->
|
|
171
171
|
|
|
@@ -175,54 +175,54 @@ export interface CoverageChecker<T> {
|
|
|
175
175
|
**src/core/model.ts (Model Class Properties)**
|
|
176
176
|
|
|
177
177
|
```typescript
|
|
178
|
-
/** Execute coverage check */
|
|
179
|
-
check: (
|
|
180
|
-
specs: T[],
|
|
181
|
-
registry: Record<string, Map<string, unknown>>
|
|
182
|
-
) => CoverageResult;
|
|
183
178
|
}
|
|
184
179
|
|
|
185
|
-
// ============================================================================
|
|
186
|
-
// Renderer (for embeds)
|
|
187
|
-
// ============================================================================
|
|
188
|
-
|
|
189
180
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
181
|
+
* Deep validation configuration keyed by source type.
|
|
182
|
+
* Models define this to enable Level 2/3 checks beyond existence.
|
|
192
183
|
*/
|
|
193
|
-
export interface
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
markdown: {
|
|
198
|
-
/** Generate table */
|
|
199
|
-
table: (headers: string[], rows: (string | unknown)[][]) => string;
|
|
200
|
-
};
|
|
184
|
+
export interface DeepValidationConfig<T> {
|
|
185
|
+
openapi?: DeepValidationRule<T, OpenAPIValidationMapping>;
|
|
186
|
+
ddl?: DeepValidationRule<T, DDLValidationMapping>;
|
|
187
|
+
[sourceType: string]: DeepValidationRule<T, unknown> | undefined;
|
|
201
188
|
}
|
|
202
189
|
|
|
203
190
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
191
|
+
* Lookup key configuration keyed by source type.
|
|
192
|
+
* When a model's spec ID differs from the external identifier
|
|
193
|
+
* (e.g. entity ID "user" vs DDL table name "users"),
|
|
194
|
+
* define a mapper per source type to derive the external key.
|
|
195
|
+
* If not defined for a source type, spec.id is used as-is.
|
|
207
196
|
*/
|
|
208
|
-
export interface
|
|
209
|
-
|
|
210
|
-
format: string;
|
|
211
|
-
/** Rendering process */
|
|
212
|
-
render: (specs: T[], ctx: RenderContext) => string;
|
|
197
|
+
export interface LookupKeyConfig<T> {
|
|
198
|
+
[sourceType: string]: ((spec: T) => string) | undefined;
|
|
213
199
|
}
|
|
214
200
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Coverage result
|
|
203
|
+
*/
|
|
204
|
+
export interface CoverageResult {
|
|
205
|
+
/** Total target count */
|
|
206
|
+
total: number;
|
|
207
|
+
/** Covered count */
|
|
208
|
+
covered: number;
|
|
209
|
+
/** Uncovered count */
|
|
210
|
+
uncovered: number;
|
|
211
|
+
/** Coverage rate (%) */
|
|
212
|
+
coveragePercent: number;
|
|
213
|
+
/** Details of covered items */
|
|
214
|
+
coveredItems: { id: string; description?: string }[];
|
|
215
|
+
/** Details of uncovered items */
|
|
216
|
+
uncoveredItems: { id: string; description?: string; sourceId?: string }[];
|
|
217
|
+
}
|
|
218
218
|
|
|
219
219
|
/**
|
|
220
|
-
*
|
|
220
|
+
* Coverage checker definition
|
|
221
221
|
*
|
|
222
|
-
*
|
|
222
|
+
* Verify cross-model consistency (coverage).
|
|
223
|
+
* Example: Whether TestRef covers acceptanceCriteria of Requirement
|
|
223
224
|
*/
|
|
224
|
-
export
|
|
225
|
-
/** Singleton instance storage (per subclass) */
|
|
225
|
+
export interface CoverageChecker<T> {
|
|
226
226
|
```
|
|
227
227
|
<!--@embedoc:end-->
|
|
228
228
|
|
|
@@ -493,61 +493,65 @@ class TestRefModel extends Model<typeof TestRefSchema> {
|
|
|
493
493
|
protected exporters: Exporter<TestRef>[] = [
|
|
494
494
|
{
|
|
495
495
|
format: 'markdown',
|
|
496
|
-
|
|
496
|
+
index: (specs) => {
|
|
497
497
|
const lines: string[] = [];
|
|
498
|
-
lines.push(
|
|
499
|
-
lines.push('');
|
|
500
|
-
lines.push('## Test Source');
|
|
498
|
+
lines.push('# Test Reference List');
|
|
501
499
|
lines.push('');
|
|
502
|
-
lines.push(
|
|
503
|
-
lines.push(
|
|
504
|
-
|
|
505
|
-
lines.push(
|
|
500
|
+
lines.push('| ID | Description | Framework | Requirements Count |');
|
|
501
|
+
lines.push('|----|-------------|-----------|-------------------|');
|
|
502
|
+
for (const spec of specs) {
|
|
503
|
+
lines.push(
|
|
504
|
+
`| ${spec.id} | ${spec.description} | ${spec.source.framework} | ${spec.verifiesRequirements.length} |`,
|
|
505
|
+
);
|
|
506
506
|
}
|
|
507
507
|
lines.push('');
|
|
508
|
-
|
|
509
|
-
lines.push('## Verified Requirements');
|
|
510
|
-
lines.push('');
|
|
511
|
-
for (const reqId of spec.verifiesRequirements) {
|
|
512
|
-
lines.push(`- ${reqId}`);
|
|
513
|
-
}
|
|
508
|
+
lines.push('---');
|
|
514
509
|
lines.push('');
|
|
515
510
|
|
|
516
|
-
|
|
517
|
-
lines.push(
|
|
511
|
+
for (const spec of specs) {
|
|
512
|
+
lines.push(`## ${spec.id}: ${spec.description}`);
|
|
518
513
|
lines.push('');
|
|
519
|
-
lines.push(
|
|
514
|
+
lines.push('### Test Source');
|
|
515
|
+
lines.push('');
|
|
516
|
+
lines.push(`- **Path**: \`${spec.source.path}\``);
|
|
517
|
+
lines.push(`- **Framework**: ${spec.source.framework}`);
|
|
518
|
+
if (spec.source.resultPath) {
|
|
519
|
+
lines.push(`- **Result JSON**: \`${spec.source.resultPath}\``);
|
|
520
|
+
}
|
|
520
521
|
lines.push('');
|
|
521
|
-
}
|
|
522
522
|
|
|
523
|
-
|
|
524
|
-
lines.push('## Test Case Patterns');
|
|
523
|
+
lines.push('### Verified Requirements');
|
|
525
524
|
lines.push('');
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
for (const p of spec.testCasePatterns) {
|
|
529
|
-
lines.push(`| ${p.acceptanceCriteriaId} | \`${p.pattern}\` | ${p.description || '-'} |`);
|
|
525
|
+
for (const reqId of spec.verifiesRequirements) {
|
|
526
|
+
lines.push(`- ${reqId}`);
|
|
530
527
|
}
|
|
531
528
|
lines.push('');
|
|
532
|
-
}
|
|
533
529
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
530
|
+
if (spec.implementsCommand) {
|
|
531
|
+
lines.push('### Implemented Command');
|
|
532
|
+
lines.push('');
|
|
533
|
+
lines.push(`- ${spec.implementsCommand}`);
|
|
534
|
+
lines.push('');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (spec.testCasePatterns && spec.testCasePatterns.length > 0) {
|
|
538
|
+
lines.push('### Test Case Patterns');
|
|
539
|
+
lines.push('');
|
|
540
|
+
lines.push('| Acceptance Criteria ID | Pattern | Description |');
|
|
541
|
+
lines.push('|------------------------|---------|-------------|');
|
|
542
|
+
for (const p of spec.testCasePatterns) {
|
|
543
|
+
lines.push(`| ${p.acceptanceCriteriaId} | \`${p.pattern}\` | ${p.description || '-'} |`);
|
|
544
|
+
}
|
|
545
|
+
lines.push('');
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
lines.push('---');
|
|
549
|
+
lines.push('');
|
|
546
550
|
}
|
|
547
|
-
|
|
551
|
+
|
|
552
|
+
return lines.join('\n').replace(/\n---\n\n$/s, '\n');
|
|
548
553
|
},
|
|
549
|
-
|
|
550
|
-
filename: (spec) => spec.id,
|
|
554
|
+
outputFile: 'design/test-refs.md',
|
|
551
555
|
},
|
|
552
556
|
];
|
|
553
557
|
|