@anselmdk/feature-spec-md 0.1.1 → 0.2.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.
Files changed (46) hide show
  1. package/README.md +94 -50
  2. package/SPEC_FORMAT.md +200 -38
  3. package/dist/cli.js +178 -28
  4. package/dist/cli.js.map +1 -1
  5. package/dist/featureSpecs.d.ts +34 -0
  6. package/dist/featureSpecs.d.ts.map +1 -0
  7. package/dist/featureSpecs.js +240 -0
  8. package/dist/featureSpecs.js.map +1 -0
  9. package/dist/filePatterns.d.ts.map +1 -1
  10. package/dist/filePatterns.js +4 -0
  11. package/dist/filePatterns.js.map +1 -1
  12. package/dist/html.d.ts +3 -0
  13. package/dist/html.d.ts.map +1 -1
  14. package/dist/html.js +3 -0
  15. package/dist/html.js.map +1 -1
  16. package/dist/index.d.ts +3 -34
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +7 -338
  19. package/dist/index.js.map +1 -1
  20. package/dist/playwright.d.ts.map +1 -1
  21. package/dist/playwright.js +13 -21
  22. package/dist/playwright.js.map +1 -1
  23. package/dist/reportTemplate.d.ts +4 -1
  24. package/dist/reportTemplate.d.ts.map +1 -1
  25. package/dist/reportTemplate.js +251 -21
  26. package/dist/reportTemplate.js.map +1 -1
  27. package/dist/screenshots.d.ts.map +1 -1
  28. package/dist/screenshots.js +4 -0
  29. package/dist/screenshots.js.map +1 -1
  30. package/dist/specDocuments.d.ts +86 -0
  31. package/dist/specDocuments.d.ts.map +1 -0
  32. package/dist/specDocuments.js +351 -0
  33. package/dist/specDocuments.js.map +1 -0
  34. package/dist/specMarkdown.d.ts +26 -0
  35. package/dist/specMarkdown.d.ts.map +1 -0
  36. package/dist/specMarkdown.js +126 -0
  37. package/dist/specMarkdown.js.map +1 -0
  38. package/dist/testImplementationReport.d.ts +53 -0
  39. package/dist/testImplementationReport.d.ts.map +1 -0
  40. package/dist/testImplementationReport.js +160 -0
  41. package/dist/testImplementationReport.js.map +1 -0
  42. package/dist/types.d.ts +76 -11
  43. package/dist/types.d.ts.map +1 -1
  44. package/docs/releasing.md +107 -0
  45. package/docs/spec-driven-flow.md +175 -0
  46. package/package.json +12 -2
@@ -0,0 +1,160 @@
1
+ export function buildSpecImplementationReport(specs, coverage, models = []) {
2
+ const modelCoverage = new Map(coverage.modelCoverage?.map((item) => [item.id, item]) ?? []);
3
+ const scenarioCoverage = new Map(coverage.scenarioCoverage.map((item) => [item.id, item]));
4
+ const ruleCoverage = new Map(coverage.ruleCoverage.map((item) => [item.id, item]));
5
+ const modelItems = models.map((model) => {
6
+ const coverageItems = model.modelItems.map((modelItem) => modelCoverage.get(modelItem.id) ?? {
7
+ id: modelItem.id,
8
+ title: modelItem.title,
9
+ filePath: model.filePath,
10
+ line: modelItem.line,
11
+ covered: false,
12
+ references: [],
13
+ });
14
+ const coveredModelItems = coverageItems.filter((item) => item.covered);
15
+ const missingModelItems = coverageItems.filter((item) => !item.covered);
16
+ const rules = model.rules.map((rule) => ruleCoverage.get(rule.id) ?? {
17
+ id: rule.id,
18
+ title: rule.text,
19
+ filePath: model.filePath,
20
+ line: rule.line,
21
+ covered: false,
22
+ references: [],
23
+ });
24
+ const coveredRuleItems = rules.filter((rule) => rule.covered);
25
+ const missingRules = rules.filter((rule) => !rule.covered);
26
+ return {
27
+ id: model.frontmatter.id,
28
+ title: model.title,
29
+ filePath: model.filePath,
30
+ totalItems: coverageItems.length,
31
+ coveredItems: coveredModelItems.length,
32
+ totalRules: rules.length,
33
+ coveredRules: coveredRuleItems.length,
34
+ coveredModelItems,
35
+ missingModelItems,
36
+ coveredRuleItems,
37
+ missingRules,
38
+ };
39
+ });
40
+ const items = specs.map((spec) => {
41
+ const scenarios = spec.scenarios.map((scenario) => scenarioCoverage.get(scenario.id) ?? {
42
+ id: scenario.id,
43
+ title: scenario.title,
44
+ filePath: spec.filePath,
45
+ line: scenario.line,
46
+ covered: false,
47
+ references: [],
48
+ });
49
+ const rules = spec.rules.map((rule) => ruleCoverage.get(rule.id) ?? {
50
+ id: rule.id,
51
+ title: rule.text,
52
+ filePath: spec.filePath,
53
+ line: rule.line,
54
+ covered: false,
55
+ references: [],
56
+ });
57
+ const missingScenarios = scenarios.filter((scenario) => !scenario.covered);
58
+ const coveredScenarios = scenarios.length - missingScenarios.length;
59
+ const coveredRuleItems = rules.filter((rule) => rule.covered);
60
+ const missingRules = rules.filter((rule) => !rule.covered);
61
+ const status = statusForCoverage(coveredScenarios, scenarios.length);
62
+ return {
63
+ id: spec.frontmatter.id,
64
+ title: spec.title,
65
+ filePath: spec.filePath,
66
+ totalScenarios: scenarios.length,
67
+ coveredScenarios,
68
+ totalRules: rules.length,
69
+ coveredRules: coveredRuleItems.length,
70
+ missingScenarios,
71
+ coveredRuleItems,
72
+ missingRules,
73
+ status,
74
+ };
75
+ });
76
+ return {
77
+ models: modelItems,
78
+ specs: items,
79
+ implemented: items.filter((item) => item.status === "implemented"),
80
+ partial: items.filter((item) => item.status === "partial"),
81
+ missing: items.filter((item) => item.status === "missing"),
82
+ totalModels: modelItems.length,
83
+ totalModelItems: modelItems.reduce((sum, item) => sum + item.totalItems, 0),
84
+ coveredModelItems: modelItems.reduce((sum, item) => sum + item.coveredItems, 0),
85
+ missingModelItems: modelItems.reduce((sum, item) => sum + item.missingModelItems.length, 0),
86
+ totalSpecs: items.length,
87
+ totalScenarios: items.reduce((sum, item) => sum + item.totalScenarios, 0),
88
+ coveredScenarios: items.reduce((sum, item) => sum + item.coveredScenarios, 0),
89
+ missingScenarios: items.reduce((sum, item) => sum + item.missingScenarios.length, 0),
90
+ totalRules: coverage.ruleCoverage.length,
91
+ coveredRules: coverage.ruleCoverage.filter((item) => item.covered).length,
92
+ missingRules: coverage.ruleCoverage.filter((item) => !item.covered).length,
93
+ };
94
+ }
95
+ export function formatSpecImplementationReport(report) {
96
+ const modelSummary = report.totalModelItems > 0
97
+ ? `, ${report.coveredModelItems}/${report.totalModelItems} model item(s) covered`
98
+ : "";
99
+ const missingModelSummary = report.totalModelItems > 0
100
+ ? `. Missing model items: ${report.missingModelItems}`
101
+ : "";
102
+ return [
103
+ "Spec test implementation report",
104
+ "",
105
+ `Summary: ${report.implemented.length}/${report.totalSpecs} spec(s) implemented, ${report.coveredScenarios}/${report.totalScenarios} scenario(s) covered, ${report.coveredRules}/${report.totalRules} rule(s) covered${modelSummary}.`,
106
+ `Partial: ${report.partial.length}. Not implemented: ${report.missing.length}. Missing scenarios: ${report.missingScenarios}. Missing rules: ${report.missingRules}${missingModelSummary}.`,
107
+ ...(report.totalModels > 0 ? ["", formatModelSection(report.models)] : []),
108
+ "",
109
+ formatSection("Implemented", report.implemented),
110
+ "",
111
+ formatSection("Partial", report.partial),
112
+ "",
113
+ formatSection("Not implemented", report.missing),
114
+ ].join("\n");
115
+ }
116
+ function statusForCoverage(coveredScenarios, totalScenarios) {
117
+ if (totalScenarios > 0 && coveredScenarios === totalScenarios)
118
+ return "implemented";
119
+ if (coveredScenarios > 0)
120
+ return "partial";
121
+ return "missing";
122
+ }
123
+ function formatSection(title, specs) {
124
+ if (!specs.length)
125
+ return `${title}:\n (none)`;
126
+ return [
127
+ `${title}:`,
128
+ ...specs.flatMap((spec) => [
129
+ ` - ${spec.id}: ${spec.title} (${spec.coveredScenarios}/${spec.totalScenarios} scenarios, ${spec.coveredRules}/${spec.totalRules} rules) ${spec.filePath}`,
130
+ ...spec.missingScenarios.map((scenario) => ` missing ${scenario.id}: ${scenario.title ?? "Untitled scenario"}`),
131
+ ...spec.coveredRuleItems.map((rule) => ` covered rule ${rule.id}: ${rule.title ?? "Untitled rule"}${formatCoverageReferenceSuffix(rule)}`),
132
+ ...spec.missingRules.map((rule) => ` missing rule ${rule.id}: ${rule.title ?? "Untitled rule"}`),
133
+ ]),
134
+ ].join("\n");
135
+ }
136
+ function formatModelSection(models) {
137
+ if (!models.length)
138
+ return "Models:\n (none)";
139
+ return [
140
+ "Models:",
141
+ ...models.flatMap((model) => [
142
+ ` - ${model.id}: ${model.title} (${model.coveredItems}/${model.totalItems} model items, ${model.coveredRules}/${model.totalRules} rules) ${model.filePath}`,
143
+ ...model.coveredModelItems.map((item) => ` covered model ${item.id}: ${item.title ?? "Untitled model item"}${formatCoverageReferenceSuffix(item)}`),
144
+ ...model.missingModelItems.map((item) => ` missing model ${item.id}: ${item.title ?? "Untitled model item"}`),
145
+ ...model.coveredRuleItems.map((rule) => ` covered rule ${rule.id}: ${rule.title ?? "Untitled rule"}${formatCoverageReferenceSuffix(rule)}`),
146
+ ...model.missingRules.map((rule) => ` missing rule ${rule.id}: ${rule.title ?? "Untitled rule"}`),
147
+ ]),
148
+ ].join("\n");
149
+ }
150
+ function formatCoverageReferenceSuffix(item) {
151
+ const references = coverageReferenceLabels(item);
152
+ return references.length ? ` (${references.join(", ")})` : "";
153
+ }
154
+ function coverageReferenceLabels(item) {
155
+ return Array.from(new Set(item.references.map((reference) => {
156
+ const line = reference.line ? `:${reference.line}` : "";
157
+ return `${reference.filePath}${line}`;
158
+ })));
159
+ }
160
+ //# sourceMappingURL=testImplementationReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testImplementationReport.js","sourceRoot":"","sources":["../src/testImplementationReport.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,37 @@
1
+ /**
2
+ * Shared TypeScript types for parsed spec documents, validation issues,
3
+ * coverage summaries, test references, and screenshot evidence.
4
+ */
5
+ /** Shared frontmatter fields supported by all spec documents. */
6
+ export type SpecFrontmatter = {
7
+ id: string;
8
+ title: string;
9
+ status?: "draft" | "active" | "deprecated";
10
+ owner?: string;
11
+ };
12
+ /** Frontmatter fields supported by documents that may reference models. */
13
+ export type ModelReferenceFrontmatter = SpecFrontmatter & {
14
+ model?: string;
15
+ models?: string[] | string;
16
+ };
17
+ /** Frontmatter fields supported by `*.feature.md` files. */
18
+ export type FeatureFrontmatter = ModelReferenceFrontmatter;
19
+ /** Frontmatter fields supported by `*.design.md` files. */
20
+ export type DesignFrontmatter = ModelReferenceFrontmatter;
21
+ /** Parsed contents of one `*.model.md` file. */
22
+ export type ModelSpec = {
23
+ kind: "model";
24
+ filePath: string;
25
+ frontmatter: SpecFrontmatter;
26
+ title: string;
27
+ purpose: string;
28
+ modelItems: ModelItem[];
29
+ rules: FeatureRule[];
30
+ source: string;
31
+ };
1
32
  /** Parsed contents of one `*.feature.md` file. */
2
33
  export type FeatureSpec = {
34
+ kind?: "feature";
3
35
  filePath: string;
4
36
  frontmatter: FeatureFrontmatter;
5
37
  title: string;
@@ -8,14 +40,45 @@ export type FeatureSpec = {
8
40
  scenarios: FeatureScenario[];
9
41
  source: string;
10
42
  };
11
- /** Frontmatter fields supported by the feature spec format. */
12
- export type FeatureFrontmatter = {
43
+ /** Parsed contents of one `*.stack.md` file. */
44
+ export type StackSpec = {
45
+ kind: "stack";
46
+ filePath: string;
47
+ frontmatter: SpecFrontmatter;
48
+ title: string;
49
+ purpose: string;
50
+ stack: string;
51
+ context: string;
52
+ rationale: string;
53
+ consequences: string;
54
+ rules: FeatureRule[];
55
+ source: string;
56
+ };
57
+ /** Parsed contents of one `*.design.md` file. */
58
+ export type DesignSpec = {
59
+ kind: "design";
60
+ filePath: string;
61
+ frontmatter: DesignFrontmatter;
62
+ title: string;
63
+ purpose: string;
64
+ design: string;
65
+ principles: string;
66
+ layout: string;
67
+ interaction: string;
68
+ visualStyle: string;
69
+ rules: FeatureRule[];
70
+ source: string;
71
+ };
72
+ /** Any parsed spec document. */
73
+ export type SpecDocument = ModelSpec | FeatureSpec | StackSpec | DesignSpec;
74
+ /** A model concept declared in the `## Model` section. */
75
+ export type ModelItem = {
13
76
  id: string;
14
77
  title: string;
15
- status?: "draft" | "active" | "deprecated";
16
- owner?: string;
78
+ body: string;
79
+ line: number;
17
80
  };
18
- /** A business rule declared in the `## Rules` section. */
81
+ /** A rule declared in the `## Rules` section. */
19
82
  export type FeatureRule = {
20
83
  id: string;
21
84
  text: string;
@@ -46,15 +109,15 @@ export type ValidationIssue = {
46
109
  filePath?: string;
47
110
  line?: number;
48
111
  };
49
- /** A rule or scenario ID found in executable tests. */
112
+ /** A model item, rule, or scenario ID found in executable tests. */
50
113
  export type TestReference = {
51
114
  id: string;
52
115
  filePath: string;
53
116
  line: number;
54
- kind: "scenario" | "rule";
117
+ kind: "model" | "rule" | "scenario";
55
118
  source: "title" | "tag" | "covers" | "annotation" | "free-text";
56
119
  };
57
- /** Coverage state for one expected rule or scenario. */
120
+ /** Coverage state for one expected model item, rule, or scenario. */
58
121
  export type CoverageItem = {
59
122
  id: string;
60
123
  title?: string;
@@ -63,12 +126,14 @@ export type CoverageItem = {
63
126
  covered: boolean;
64
127
  references: TestReference[];
65
128
  };
66
- /** Complete test coverage mapping for a set of feature specs. */
129
+ /** Complete test coverage mapping for a set of spec documents. */
67
130
  export type CoverageSummary = {
68
- scenarioCoverage: CoverageItem[];
131
+ modelCoverage?: CoverageItem[];
69
132
  ruleCoverage: CoverageItem[];
70
- orphanScenarioReferences: TestReference[];
133
+ scenarioCoverage: CoverageItem[];
134
+ orphanModelReferences?: TestReference[];
71
135
  orphanRuleReferences: TestReference[];
136
+ orphanScenarioReferences: TestReference[];
72
137
  };
73
138
  /** Screenshot evidence associated with an exact spec line. */
74
139
  export type SpecScreenshot = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ # Releasing
2
+
3
+ This package uses npm semver versions and bare git tags. Use `0.2.0`, not `v0.2.0`.
4
+
5
+ Bare semver tags are valid git tags and match the package version exactly. The `v` prefix is common in many projects because it makes tag names visually distinct from branch names, but npm does not require it. For this repository, exact package-version tags are simpler because the tag, `package.json`, `package-lock.json`, and npm version all use the same string.
6
+
7
+ ## Release Candidate
8
+
9
+ Use an RC when you want a testable npm package for the next release without updating the `latest` npm dist-tag.
10
+
11
+ 1. Make sure `main` contains the intended final version in `package.json` and `package-lock.json`.
12
+ - For the next minor release from `0.1.1`, the base version should be `0.2.0`.
13
+ - For the next major release from `0.2.0`, the base version should be `1.0.0`.
14
+ 2. Open GitHub Actions.
15
+ 3. Run the `Publish to npm` workflow from `main`.
16
+ 4. Choose `rc` for the release type.
17
+ 5. The workflow runs verification, changes the package version only inside the workflow to `<base>-rc.<run>.<attempt>`, and publishes it with the npm `rc` dist-tag.
18
+
19
+ Install the latest RC with:
20
+
21
+ ```bash
22
+ npm install @anselmdk/feature-spec-md@rc
23
+ ```
24
+
25
+ Install a specific RC with:
26
+
27
+ ```bash
28
+ npm install @anselmdk/feature-spec-md@0.2.0-rc.123.1
29
+ ```
30
+
31
+ Repeat the workflow as needed. Each run publishes a new RC and moves the `rc` dist-tag to that version.
32
+
33
+ ## Stable Minor Release
34
+
35
+ Use this for backward-compatible features.
36
+
37
+ 1. Start from a clean branch based on `main`.
38
+ 2. Bump the package version:
39
+
40
+ ```bash
41
+ npm version minor --no-git-tag-version
42
+ ```
43
+
44
+ 3. Run verification locally:
45
+
46
+ ```bash
47
+ npm run verify
48
+ npm run format
49
+ ```
50
+
51
+ 4. Open and merge a pull request containing the version bump and any release notes.
52
+ 5. After the PR is merged, update local `main` and create a bare semver tag that exactly matches `package.json`:
53
+
54
+ ```bash
55
+ git checkout main
56
+ git pull --ff-only
57
+ git tag 0.2.0
58
+ git push origin 0.2.0
59
+ ```
60
+
61
+ 6. Confirm the `Publish to npm` workflow succeeds.
62
+
63
+ The workflow validates that the tag is a stable semver version and exactly matches `package.json` before publishing to npm with the `latest` dist-tag.
64
+
65
+ ## Stable Major Release
66
+
67
+ Use this for breaking changes.
68
+
69
+ 1. Document the breaking changes in the release PR.
70
+ 2. Bump the package version:
71
+
72
+ ```bash
73
+ npm version major --no-git-tag-version
74
+ ```
75
+
76
+ 3. Run verification locally:
77
+
78
+ ```bash
79
+ npm run verify
80
+ npm run format
81
+ ```
82
+
83
+ 4. Open and merge the release PR.
84
+ 5. Tag the merged commit with the exact version, for example:
85
+
86
+ ```bash
87
+ git checkout main
88
+ git pull --ff-only
89
+ git tag 1.0.0
90
+ git push origin 1.0.0
91
+ ```
92
+
93
+ 6. Confirm the `Publish to npm` workflow succeeds.
94
+
95
+ ## npm Publishing Setup
96
+
97
+ The publish workflows are ready for npm provenance. The best setup is npm trusted publishing with GitHub Actions OIDC, which avoids long-lived npm publish tokens.
98
+
99
+ On npmjs.com, configure this package with trusted publishing:
100
+
101
+ - Publisher: GitHub Actions
102
+ - Repository owner: `anselmdk`
103
+ - Repository name: `feature-spec-md`
104
+ - Workflow filename: `publish.yml`
105
+ - Allowed action: `npm publish`
106
+
107
+ If trusted publishing is not configured yet, the workflow can still use the `NPM_TOKEN` repository secret. Keep RC and stable publishing in the same workflow because npm trusted publishing allows only one trusted publisher workflow per package.
@@ -0,0 +1,175 @@
1
+ # AI Spec Driven Development Flow
2
+
3
+ `feature-spec-md` is built for a loop where specs and tests are both AI-assisted, but the contract between them is explicit and testable.
4
+
5
+ ```txt
6
+ AI drafts specs
7
+ -> humans review intent
8
+ -> AI writes tests from stable IDs
9
+ -> tooling checks coverage
10
+ -> implementation follows failing tests
11
+ -> reports show what is implemented
12
+ ```
13
+
14
+ ## Install
15
+
16
+ Install the package in the project that owns the specs and tests:
17
+
18
+ ```bash
19
+ npm install -D @anselmdk/feature-spec-md
20
+ ```
21
+
22
+ Add scripts if you want short project commands:
23
+
24
+ ```json
25
+ {
26
+ "scripts": {
27
+ "spec": "feature-spec-md check",
28
+ "spec:coverage": "feature-spec-md coverage --fail-on-missing",
29
+ "spec:report": "feature-spec-md report"
30
+ }
31
+ }
32
+ ```
33
+
34
+ Create starter documents:
35
+
36
+ ```bash
37
+ npx feature-spec-md init --kind model --dir specs
38
+ npx feature-spec-md init --kind feature --dir specs
39
+ npx feature-spec-md init --kind stack --dir specs
40
+ npx feature-spec-md init --kind design --dir specs
41
+ ```
42
+
43
+ ## 1. Ask AI To Draft The Spec Set
44
+
45
+ Give the AI product intent and ask it to create or update:
46
+
47
+ - `*.model.md` for domain vocabulary and global invariants
48
+ - `*.feature.md` for capabilities, rules, and scenarios
49
+ - `*.stack.md` for implementation platform choices
50
+ - `*.design.md` for product, UI, and interaction direction
51
+
52
+ Useful instruction:
53
+
54
+ ```txt
55
+ Create feature-spec-md documents for this change. Keep the documents small.
56
+ Use stable uppercase IDs. Put durable behavior in rules. Put testable examples
57
+ in scenarios. Do not include test mappings inside the specs.
58
+ ```
59
+
60
+ Run:
61
+
62
+ ```bash
63
+ npx feature-spec-md check --tests ""
64
+ ```
65
+
66
+ Use `--tests ""` while the spec set is still being drafted so validation focuses on document structure and graph references.
67
+
68
+ ## 2. Review The Specs Before Implementation
69
+
70
+ Review the Markdown as product intent, not as generated test code.
71
+
72
+ Check that:
73
+
74
+ - model terms are clear enough for test authors
75
+ - feature rules are durable product truths
76
+ - scenarios are concrete enough to become executable tests
77
+ - stack choices are specific enough to guide implementation
78
+ - design direction covers the visible behavior users will judge
79
+
80
+ Then run:
81
+
82
+ ```bash
83
+ npx feature-spec-md check --require-scenario-coverage=false
84
+ ```
85
+
86
+ This keeps the spec set valid while allowing missing tests.
87
+
88
+ ## 3. Ask AI To Write Tests From The Specs
89
+
90
+ Give the AI the relevant spec files and tell it to write executable tests that preserve spec IDs in the test source.
91
+
92
+ Useful instruction:
93
+
94
+ ```txt
95
+ Write tests from these feature-spec-md specs. Each scenario test must include
96
+ the scenario ID in the test title. Add comments or annotations for covered
97
+ rule IDs and model item IDs. Do not invent IDs that are not in the specs.
98
+ ```
99
+
100
+ Example:
101
+
102
+ ```ts
103
+ test("ACCOUNT-ACCESS-S001 registered person signs in", async ({ page }) => {
104
+ // Covers ACCOUNT-ACCESS-R001 and ACCOUNT-M001.
105
+ });
106
+ ```
107
+
108
+ The test can reference IDs in titles, tags, annotations, comments, or metadata. The important part is that the ID text is present in the test source.
109
+
110
+ ## 4. Check Coverage
111
+
112
+ Run:
113
+
114
+ ```bash
115
+ npx feature-spec-md coverage
116
+ ```
117
+
118
+ The coverage command groups specs by implementation state and shows missing scenario, rule, and model item references.
119
+
120
+ Use this in CI when missing scenario tests should block a change:
121
+
122
+ ```bash
123
+ npx feature-spec-md coverage --fail-on-missing
124
+ ```
125
+
126
+ Use stricter checks when you also want rule coverage to fail CI:
127
+
128
+ ```bash
129
+ npx feature-spec-md check --require-rule-coverage=true
130
+ ```
131
+
132
+ ## 5. Generate A Report
133
+
134
+ Run:
135
+
136
+ ```bash
137
+ npx feature-spec-md report --out test-results/feature-spec-report/index.html
138
+ ```
139
+
140
+ The report is useful as a PR artifact because it shows specs, coverage state, validation issues, and optional screenshot evidence.
141
+
142
+ If your tests produce screenshot manifests, include them:
143
+
144
+ ```bash
145
+ npx feature-spec-md report \
146
+ --screenshots "test-results/spec-report/screenshots-*.json" \
147
+ --out test-results/feature-spec-report/index.html
148
+ ```
149
+
150
+ Screenshot manifest shape:
151
+
152
+ ```json
153
+ {
154
+ "screenshots": [
155
+ {
156
+ "specPath": "specs/account-access.feature.md",
157
+ "line": 24,
158
+ "path": "screenshots/account-access-s001-line-24.png",
159
+ "title": "ACCOUNT-ACCESS-S001:24 Given a registered person is on the sign-in page"
160
+ }
161
+ ]
162
+ }
163
+ ```
164
+
165
+ ## 6. Keep The Loop Honest
166
+
167
+ When behavior changes, update specs first, then regenerate or update tests from the changed specs.
168
+
169
+ The expected loop is:
170
+
171
+ ```txt
172
+ spec change -> validation -> AI test update -> coverage -> implementation -> report
173
+ ```
174
+
175
+ That keeps the AI-generated work anchored to a small, reviewable contract instead of a loose conversation history.
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@anselmdk/feature-spec-md",
3
- "version": "0.1.1",
4
- "description": "Markdown feature specs with rule/scenario IDs, validation, coverage checks, and generated reports.",
3
+ "version": "0.2.1",
4
+ "description": "Markdown specs for AI-assisted, testable spec driven development across model, feature, stack, and design documents.",
5
5
  "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/anselmdk/feature-spec-md.git"
9
+ },
6
10
  "bin": {
7
11
  "feature-spec-md": "./dist/cli.js"
8
12
  },
@@ -11,6 +15,10 @@
11
15
  "types": "./dist/index.d.ts",
12
16
  "import": "./dist/index.js"
13
17
  },
18
+ "./specDocuments": {
19
+ "types": "./dist/specDocuments.d.ts",
20
+ "import": "./dist/specDocuments.js"
21
+ },
14
22
  "./playwright": {
15
23
  "types": "./dist/playwright.d.ts",
16
24
  "import": "./dist/playwright.js"
@@ -20,6 +28,7 @@
20
28
  "dist",
21
29
  "README.md",
22
30
  "SPEC_FORMAT.md",
31
+ "docs",
23
32
  "templates",
24
33
  "examples",
25
34
  "LICENSE"
@@ -49,6 +58,7 @@
49
58
  "gherkin",
50
59
  "playwright",
51
60
  "specification",
61
+ "spec-driven-development",
52
62
  "testing"
53
63
  ],
54
64
  "license": "MIT",