speckeeper 0.8.0 → 0.9.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/README.md +137 -33
- package/dist/cli.js +622 -106
- package/dist/cli.js.map +1 -1
- package/dist/{config-api-Bh0zX8W7.d.ts → config-api-BDl4otlv.d.ts} +92 -2
- package/dist/dsl/index.d.ts +38 -82
- package/dist/dsl/index.js +431 -454
- package/dist/dsl/index.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,20 +11,28 @@
|
|
|
11
11
|
Requirements and design documents often drift from implementation. **speckeeper** treats specifications as **code** — type-safe, version-controlled, and continuously validated against your actual artifacts (tests, OpenAPI, DDL, IaC).
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
|
|
15
|
-
│
|
|
16
|
-
design/*.ts ─────────────────────────────► Validation & Consistency Checks
|
|
14
|
+
speckeeper.config.ts (sources)
|
|
17
15
|
│
|
|
18
|
-
├─►
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
├─► Global Source Scan → Find spec IDs in OpenAPI / DDL / annotations
|
|
17
|
+
│ │
|
|
18
|
+
│ ▼
|
|
19
|
+
│ MatchMap (specId → matches)
|
|
20
|
+
│ │
|
|
21
|
+
│ ▼
|
|
22
|
+
├─► Deep Validation → Model-level structural checks (optional)
|
|
23
|
+
│
|
|
24
|
+
design/*.ts
|
|
25
|
+
│
|
|
26
|
+
├─► speckeeper lint → Design integrity (IDs, references, phase gates)
|
|
27
|
+
├─► speckeeper check → External SSOT validation (global scan + deep validation)
|
|
28
|
+
└─► speckeeper impact → Change impact analysis with traceability
|
|
21
29
|
```
|
|
22
30
|
|
|
23
31
|
## Features
|
|
24
32
|
|
|
25
33
|
- **TypeScript as SSOT** — Define requirements, architecture, and design in type-safe TypeScript
|
|
26
34
|
- **Design validation** — Lint rules for ID uniqueness, reference integrity, circular dependencies, and phase gates
|
|
27
|
-
- **External SSOT validation** —
|
|
35
|
+
- **External SSOT validation** — Global scan across OpenAPI, DDL, annotations; optional deep validation per model
|
|
28
36
|
- **Traceability** — Track relationships across model levels (L0-L3) with impact analysis
|
|
29
37
|
- **Scaffold from Mermaid** — Generate `_models/` skeletons from a mermaid flowchart with class-based artifact resolution
|
|
30
38
|
- **Custom models** — Extend with domain-specific models (Runbooks, Policies, etc.)
|
|
@@ -78,10 +86,9 @@ flowchart TB
|
|
|
78
86
|
Key concepts:
|
|
79
87
|
- `class ... speckeeper` marks nodes as managed by speckeeper
|
|
80
88
|
- Additional `class` lines assign **artifact classes** (determines model name/file and node grouping)
|
|
81
|
-
- External node classes (`openapi`, `sqlschema`, `test`)
|
|
89
|
+
- External node classes (`openapi`, `sqlschema`, `test`) describe the artifact type
|
|
82
90
|
- `subgraph` determines model level (L0–L3)
|
|
83
|
-
- `implements` edges
|
|
84
|
-
- `verifiedBy` edges trigger test verification
|
|
91
|
+
- `implements`/`verifiedBy` edges define the relationship semantics
|
|
85
92
|
|
|
86
93
|
### 2. Scaffold models
|
|
87
94
|
|
|
@@ -90,10 +97,9 @@ npx speckeeper scaffold --source requirements.md
|
|
|
90
97
|
```
|
|
91
98
|
|
|
92
99
|
This generates:
|
|
93
|
-
- `design/_models/` — Model classes with base schema
|
|
100
|
+
- `design/_models/` — Model classes with base schema and lint rules
|
|
94
101
|
- `design/*.ts` — Spec data files using `defineSpecs()`
|
|
95
102
|
- `design/index.ts` — Entry point via `mergeSpecs()`
|
|
96
|
-
- Checker bindings from `implements`/`verifiedBy` edges are added as guidance comments
|
|
97
103
|
|
|
98
104
|
See [Scaffold Mermaid Specification](./docs/scaffold-mermaid-spec.md) for the full input format.
|
|
99
105
|
|
|
@@ -152,7 +158,7 @@ npx speckeeper impact FR-001
|
|
|
152
158
|
| `speckeeper check` | Verify consistency with external SSOT |
|
|
153
159
|
| `speckeeper check test --coverage` | Verify test coverage for requirements |
|
|
154
160
|
| `speckeeper scaffold` | Generate model skeletons from a mermaid flowchart |
|
|
155
|
-
| `speckeeper drift` | Detect manual edits to generated `
|
|
161
|
+
| `speckeeper drift` | Detect manual edits to generated `docs/` files |
|
|
156
162
|
| `speckeeper impact <id>` | Analyze change impact for a specific element |
|
|
157
163
|
|
|
158
164
|
**Note**: `speckeeper build` generates machine-readable `specs/` output. For human-readable docs (`docs/`), use [embedoc](https://www.npmjs.com/package/embedoc) or similar tools with the model rendering API.
|
|
@@ -184,44 +190,142 @@ Checks include:
|
|
|
184
190
|
|
|
185
191
|
### External SSOT Validation (check)
|
|
186
192
|
|
|
187
|
-
Validate your specifications against actual implementation artifacts. speckeeper
|
|
193
|
+
Validate your specifications against actual implementation artifacts. speckeeper performs a **global source scan** across all configured sources, then optionally runs **deep validation** using model-specific rules.
|
|
194
|
+
|
|
195
|
+
The check flow has three levels:
|
|
196
|
+
|
|
197
|
+
1. **Existence check** (automatic) — Is the spec ID found in any configured source?
|
|
198
|
+
2. **Structural check** (via `deepValidation`) — Does the matched object's structure match? (e.g. HTTP method, table columns)
|
|
199
|
+
3. **Type check** (via `deepValidation`) — Do types match? (e.g. parameter types, column types)
|
|
188
200
|
|
|
189
|
-
|
|
190
|
-
|---------|--------|-----------|
|
|
191
|
-
| `testChecker()` | Test code | Test file existence + spec ID references in describe/it/test blocks |
|
|
192
|
-
| `externalOpenAPIChecker()` | OpenAPI spec | Spec ID existence (operationId, path, schema, x-spec-id), HTTP method, parameter/response property names and types |
|
|
193
|
-
| `externalSqlSchemaChecker()` | SQL schema | Table existence, column existence, type containment (DDL type must be equal or wider than spec type) |
|
|
194
|
-
| `relationCoverage()` | Cross-model | Coverage of a target model via relations |
|
|
201
|
+
#### Source configuration
|
|
195
202
|
|
|
196
|
-
|
|
203
|
+
Define global scan sources in `speckeeper.config.ts`:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// speckeeper.config.ts
|
|
207
|
+
import { defineConfig } from 'speckeeper';
|
|
208
|
+
|
|
209
|
+
export default defineConfig({
|
|
210
|
+
// ...
|
|
211
|
+
sources: [
|
|
212
|
+
{
|
|
213
|
+
type: 'openapi',
|
|
214
|
+
paths: ['api/openapi.yaml'],
|
|
215
|
+
relation: 'implements',
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
type: 'ddl',
|
|
219
|
+
paths: ['db/schema.sql'],
|
|
220
|
+
relation: 'implements',
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
type: 'annotation',
|
|
224
|
+
paths: ['test/**/*.test.ts', 'tests/**/*.test.ts'],
|
|
225
|
+
relation: 'verifiedBy',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: 'annotation',
|
|
229
|
+
paths: ['src/**/*.ts'],
|
|
230
|
+
exclude: ['src/**/*.test.ts'],
|
|
231
|
+
relation: 'implements',
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Each source defines:
|
|
238
|
+
- **`type`** — Built-in (`'openapi'`, `'ddl'`, `'annotation'`) or custom with a `scanner` plugin
|
|
239
|
+
- **`paths`** — Glob patterns for files to scan
|
|
240
|
+
- **`relation`** — Whether matches represent `'implements'` or `'verifiedBy'`
|
|
241
|
+
|
|
242
|
+
#### Built-in scanners
|
|
243
|
+
|
|
244
|
+
| Scanner | Finds spec IDs via | Deep validation |
|
|
245
|
+
|---------|-------------------|-----------------|
|
|
246
|
+
| `openapi` | operationId, path segment, schema name, `x-spec-id` | HTTP method, parameter names/types, response property names/types |
|
|
247
|
+
| `ddl` | Table name (case-insensitive, schema-prefix stripped) | Column names, column types (containment-based) |
|
|
248
|
+
| `annotation` | `@verifies`, `@implements`, `@traces` annotations | — |
|
|
249
|
+
|
|
250
|
+
Annotations work in any comment style (`//`, `#`, `--`, `/* */`, `<!-- -->`). Multiple IDs can be comma- or space-separated.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
// tests/unit/auth.test.ts
|
|
254
|
+
// @verifies FR-001, FR-001-01
|
|
255
|
+
describe('User Authentication', () => { ... });
|
|
256
|
+
```
|
|
197
257
|
|
|
198
258
|
```typescript
|
|
199
|
-
//
|
|
200
|
-
|
|
259
|
+
// src/auth/handler.ts
|
|
260
|
+
// @implements FR-001
|
|
261
|
+
export class AuthHandler { ... }
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Deep validation (optional)
|
|
201
265
|
|
|
202
|
-
|
|
266
|
+
Models can define `deepValidation` to enable Level 2/3 structural checks on matched source objects:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
class EntityModel extends Model<typeof EntitySchema> {
|
|
203
270
|
// ... schema, lintRules, etc.
|
|
204
271
|
|
|
205
|
-
protected
|
|
272
|
+
protected deepValidation: DeepValidationConfig<Entity> = {
|
|
273
|
+
ddl: {
|
|
274
|
+
mapper: (spec) => ({
|
|
275
|
+
tableName: spec.tableName,
|
|
276
|
+
columns: spec.columns.map(c => ({ name: c.name, type: c.type })),
|
|
277
|
+
checkTypes: true,
|
|
278
|
+
}),
|
|
279
|
+
},
|
|
280
|
+
openapi: {
|
|
281
|
+
mapper: (spec) => ({
|
|
282
|
+
path: spec.apiPath,
|
|
283
|
+
method: spec.httpMethod,
|
|
284
|
+
responseProperties: spec.fields.map(f => ({ name: f.name, type: f.type })),
|
|
285
|
+
}),
|
|
286
|
+
},
|
|
287
|
+
};
|
|
206
288
|
}
|
|
207
289
|
```
|
|
208
290
|
|
|
291
|
+
Without `deepValidation`, speckeeper still performs existence checks for all spec IDs across all configured sources.
|
|
292
|
+
|
|
293
|
+
#### Custom scanners
|
|
294
|
+
|
|
295
|
+
For file formats not covered by the built-in scanners, provide a custom `SourceScanner` plugin:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// speckeeper.config.ts
|
|
299
|
+
import { defineConfig } from 'speckeeper';
|
|
300
|
+
import type { SourceScanner } from 'speckeeper';
|
|
301
|
+
|
|
302
|
+
const protoScanner: SourceScanner = {
|
|
303
|
+
findSpecIds(content, specIds, filePath) {
|
|
304
|
+
// Parse protobuf content, find spec IDs in service/message names
|
|
305
|
+
// Return SourceMatch[] with specId, location, and optional context
|
|
306
|
+
return [];
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export default defineConfig({
|
|
311
|
+
sources: [
|
|
312
|
+
{ type: 'proto', paths: ['proto/**/*.proto'], relation: 'implements', scanner: protoScanner },
|
|
313
|
+
// ... other sources
|
|
314
|
+
],
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
209
318
|
```bash
|
|
210
|
-
$ npx speckeeper check
|
|
319
|
+
$ npx speckeeper check --verbose
|
|
211
320
|
|
|
212
321
|
speckeeper check
|
|
213
322
|
|
|
214
323
|
Design: design/
|
|
215
|
-
Type:
|
|
324
|
+
Type: all
|
|
216
325
|
|
|
217
326
|
✓ All checks passed
|
|
218
|
-
|
|
219
|
-
Coverage: Requirement → UseCase
|
|
220
|
-
Coverage: 100% (7/7 use cases covered)
|
|
221
327
|
```
|
|
222
328
|
|
|
223
|
-
You can also implement custom checkers for any external source by defining an `ExternalChecker<T>` directly. See [Model Definition Guide](./docs/model-guide.md) for details.
|
|
224
|
-
|
|
225
329
|
## Model Levels & Traceability
|
|
226
330
|
|
|
227
331
|
speckeeper organizes models by abstraction level:
|
|
@@ -299,7 +403,7 @@ class RunbookModel extends Model<typeof RunbookSchema> {
|
|
|
299
403
|
}
|
|
300
404
|
```
|
|
301
405
|
|
|
302
|
-
Core DSL factories (`speckeeper/dsl`) include `requireField`, `arrayMinLength`, `idFormat`, `childIdFormat`, `markdownExporter`, `
|
|
406
|
+
Core DSL factories (`speckeeper/dsl`) include `requireField`, `arrayMinLength`, `idFormat`, `childIdFormat`, `markdownExporter`, `annotationCoverage`, `relationCoverage`, and `baseSpecSchema`. Global scanner utilities (`openapiScanner`, `ddlScanner`, `annotationScanner`, `createAnnotationScanner`) are also re-exported for advanced use.
|
|
303
407
|
|
|
304
408
|
## Documentation
|
|
305
409
|
|