@anselmdk/feature-spec-md 0.8.2 → 0.9.0-rc.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 (73) hide show
  1. package/README.md +48 -1
  2. package/SPEC_FORMAT.md +89 -11
  3. package/dist/cli.js +16 -8
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +5 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +97 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/featureSpecs.d.ts +2 -0
  10. package/dist/featureSpecs.d.ts.map +1 -1
  11. package/dist/featureSpecs.js +86 -1
  12. package/dist/featureSpecs.js.map +1 -1
  13. package/dist/githubActionDiffReport.d.ts +5 -0
  14. package/dist/githubActionDiffReport.d.ts.map +1 -1
  15. package/dist/githubActionDiffReport.js +154 -46
  16. package/dist/githubActionDiffReport.js.map +1 -1
  17. package/dist/githubActionFtp.d.ts.map +1 -1
  18. package/dist/githubActionFtp.js +14 -2
  19. package/dist/githubActionFtp.js.map +1 -1
  20. package/dist/githubActionOutput.d.ts.map +1 -1
  21. package/dist/githubActionOutput.js.map +1 -1
  22. package/dist/githubReportMetadata.js +14 -5
  23. package/dist/githubReportMetadata.js.map +1 -1
  24. package/dist/index.d.ts +6 -5
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/mockReports.d.ts.map +1 -1
  29. package/dist/mockReports.js +41 -8
  30. package/dist/mockReports.js.map +1 -1
  31. package/dist/mocks/current/tests/supportDesk.spec.d.ts.map +1 -1
  32. package/dist/mocks/current/tests/supportDesk.spec.js +15 -3
  33. package/dist/mocks/current/tests/supportDesk.spec.js.map +1 -1
  34. package/dist/mocks/previous/tests/supportDesk.spec.d.ts.map +1 -1
  35. package/dist/mocks/previous/tests/supportDesk.spec.js +14 -2
  36. package/dist/mocks/previous/tests/supportDesk.spec.js.map +1 -1
  37. package/dist/playwright.d.ts.map +1 -1
  38. package/dist/playwright.js +3 -1
  39. package/dist/playwright.js.map +1 -1
  40. package/dist/reportArtifacts.d.ts.map +1 -1
  41. package/dist/reportArtifacts.js.map +1 -1
  42. package/dist/reportHtml.d.ts.map +1 -1
  43. package/dist/reportHtml.js +75 -2
  44. package/dist/reportHtml.js.map +1 -1
  45. package/dist/reportTemplate.d.ts +4 -1
  46. package/dist/reportTemplate.d.ts.map +1 -1
  47. package/dist/reportTemplate.js +290 -53
  48. package/dist/reportTemplate.js.map +1 -1
  49. package/dist/reportTemplates/shared.d.ts.map +1 -1
  50. package/dist/reportTemplates/shared.js.map +1 -1
  51. package/dist/screenshots.d.ts.map +1 -1
  52. package/dist/screenshots.js +3 -1
  53. package/dist/screenshots.js.map +1 -1
  54. package/dist/specDocuments.d.ts +3 -1
  55. package/dist/specDocuments.d.ts.map +1 -1
  56. package/dist/specDocuments.js +12 -1
  57. package/dist/specDocuments.js.map +1 -1
  58. package/dist/types.d.ts +29 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/docs/evidence-policy.md +1 -0
  61. package/docs/report-development.md +9 -9
  62. package/docs/spec-driven-flow.md +1 -0
  63. package/package.json +1 -1
  64. package/src/mocks/current/specs/support-desk.design.md +1 -0
  65. package/src/mocks/current/specs/support-desk.model.md +1 -0
  66. package/src/mocks/current/specs/support-platform.stack.md +1 -0
  67. package/src/mocks/current/specs/ticket-inbox.feature.md +1 -0
  68. package/src/mocks/current/specs/ticket-reply.feature.md +1 -0
  69. package/src/mocks/current/tests/supportDesk.spec.ts +19 -3
  70. package/src/mocks/previous/specs/support-desk.model.md +1 -0
  71. package/src/mocks/previous/specs/ticket-inbox.feature.md +1 -0
  72. package/src/mocks/previous/specs/ticket-reply.feature.md +1 -0
  73. package/src/mocks/previous/tests/supportDesk.spec.ts +14 -2
package/README.md CHANGED
@@ -253,6 +253,53 @@ npx feature-spec-md report \
253
253
 
254
254
  This gate only fails for scenarios whose resolved screenshot policy is `required`. In GitHub Actions, the report also includes source links and report metadata derived from the repository, ref, SHA, run, build number, and pull request context when available.
255
255
 
256
+ Reports include a persistent light/dark theme toggle. Screenshot evidence is
257
+ clickable and opens at its native size in a scrollable full-screen viewer. PR
258
+ diff reports keep before and after images side by side, with red and green
259
+ borders respectively.
260
+
261
+ Projects can group model, stack, design, and feature documents into collapsible
262
+ report layers. Add a `layer` to each document's frontmatter and define the
263
+ ordered layer catalogue in `package.json`:
264
+
265
+ ```json
266
+ {
267
+ "featureSpecMd": {
268
+ "report": {
269
+ "layers": [
270
+ {
271
+ "id": "context",
272
+ "title": "Context",
273
+ "description": "Architecture, design, and domain vocabulary"
274
+ },
275
+ {
276
+ "id": "capability",
277
+ "title": "Capabilities",
278
+ "description": "Authoritative business behavior"
279
+ },
280
+ {
281
+ "id": "surface",
282
+ "title": "Delivery surfaces",
283
+ "description": "Applications, hosting, and documentation"
284
+ },
285
+ {
286
+ "id": "journey",
287
+ "title": "Journeys",
288
+ "description": "Cross-system release paths"
289
+ }
290
+ ],
291
+ "layersDefaultOpen": false,
292
+ "documentsDefaultOpen": false
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ When layers are configured, unassigned documents remain visible in an `Other`
299
+ layer and produce a warning; unknown layer ids are errors. Deep links open all
300
+ containing layers and documents automatically. Projects without layer
301
+ configuration retain the flat report layout.
302
+
256
303
  ### `github-report`
257
304
 
258
305
  Writes a GitHub Actions job summary and prepares the generated report for either artifact upload or FTP publishing.
@@ -283,7 +330,7 @@ npx feature-spec-md github-diff-report \
283
330
  ```
284
331
 
285
332
  The diff report lists changed report assets, extracts changed spec sections,
286
- groups screenshot changes by spec/scenario, writes a GitHub Actions summary,
333
+ groups configured projects by layer and screenshot changes by spec/scenario, writes a GitHub Actions summary,
287
334
  and exposes a `diff-comment-body` output. The reusable PR workflow maintains
288
335
  one compact PR comment linking to the latest full spec report and diff report.
289
336
  Earlier build links remain available in a collapsed history below the current
package/SPEC_FORMAT.md CHANGED
@@ -44,6 +44,7 @@ Optional fields:
44
44
 
45
45
  - `status`: `draft`, `active`, or `deprecated`
46
46
  - `owner`
47
+ - `layer`: a project-defined report layer id
47
48
  - `model`: a single referenced model id, for feature and design files
48
49
  - `models`: comma-separated referenced model ids, for feature and design files
49
50
  - `test`: default scenario test type for feature files
@@ -51,6 +52,19 @@ Optional fields:
51
52
 
52
53
  IDs use uppercase words separated by hyphens. IDs are the contract between specs, tests, reports, and implementation work.
53
54
 
55
+ ### Report Layers
56
+
57
+ Any model, feature, stack, or design document MAY declare a project-defined
58
+ `layer` in frontmatter. Layer definitions belong in the consuming project's
59
+ `package.json` under `featureSpecMd.report.layers`; the configuration controls
60
+ their titles, descriptions, and order. `layersDefaultOpen` and
61
+ `documentsDefaultOpen` control the initial nested report state.
62
+
63
+ Layer ids MUST use lowercase words separated by hyphens. When a layer catalogue
64
+ is configured, an unknown layer is an error. A document without a layer remains
65
+ visible under `Other` and produces a warning so report content is never silently
66
+ discarded.
67
+
54
68
  ## Purpose
55
69
 
56
70
  Every model, feature, stack, and design file MUST include a short `## Purpose` section.
@@ -75,6 +89,7 @@ Optional sections:
75
89
 
76
90
  ```md
77
91
  ## Rules
92
+
78
93
  ## Model Diagram
79
94
  ```
80
95
 
@@ -165,6 +180,7 @@ Scenario-level overrides go directly below a scenario heading. The Given / When
165
180
 
166
181
  ````md
167
182
  ### KANBAN-CARD-AUTHORING-S002: Card title is normalized
183
+
168
184
  Test: unit
169
185
  Screenshots: skip
170
186
 
@@ -187,6 +203,66 @@ Defaults:
187
203
 
188
204
  See [Scenario Test And Evidence Policy](docs/evidence-policy.md) for details and CI examples.
189
205
 
206
+ ### End-to-end journey metadata
207
+
208
+ Scenarios that cross multiple product or system boundaries can be identified as
209
+ end-to-end journeys. When most or all scenarios in a feature share the same
210
+ journey metadata, declare the defaults in frontmatter:
211
+
212
+ ```md
213
+ ---
214
+ id: CHECKOUT
215
+ title: Checkout
216
+ test: playwright
217
+ screenshots: required
218
+ journey: end-to-end
219
+ path: happy
220
+ critical: true
221
+ ---
222
+ ```
223
+
224
+ Scenarios inherit those values and only need to declare their systems:
225
+
226
+ ````md
227
+ ### CHECKOUT-S001: Attendee buys access and books
228
+
229
+ Systems: consumer UI, API, payment provider, email
230
+
231
+ ```
232
+ Given a new attendee is viewing a public class
233
+ When they purchase access and complete the booking
234
+ Then the booking appears in their account
235
+ ```
236
+ ````
237
+
238
+ Scenario-level metadata overrides feature defaults, so an exceptional failure
239
+ path can remain explicit:
240
+
241
+ ````md
242
+ ### CHECKOUT-S002: Payment is declined
243
+
244
+ Path: failure
245
+ Critical: false
246
+ Systems: consumer UI, API, payment provider, email
247
+
248
+ ```
249
+ Given an attendee is checking out
250
+ When the payment provider declines the payment
251
+ Then access is not granted
252
+ ```
253
+ ````
254
+
255
+ `Path` is either `happy` or `failure`. `Critical` marks release-gating
256
+ journeys, and `Systems` is a comma-separated list shown in the report. Journey
257
+ scenarios appear in a dedicated report overview and otherwise retain normal
258
+ scenario coverage and evidence requirements. CI can enforce critical journeys
259
+ even when general scenario coverage is disabled by passing
260
+ `--require-critical-journey-coverage`.
261
+
262
+ For a mixed feature, `Journey: end-to-end`, `Path`, and `Critical` may still be
263
+ declared per scenario. Feature defaults are optional; `path` and `critical`
264
+ frontmatter require `journey: end-to-end`.
265
+
190
266
  ## Stack Files
191
267
 
192
268
  Stack files use the `.stack.md` suffix and define technical platform choices and the reasoning behind them.
@@ -258,10 +334,10 @@ Use `## API Contract` for API-first features and services. This section SHOULD d
258
334
  ```md
259
335
  ## API Contract
260
336
 
261
- | Method | Path | Purpose | Auth |
262
- | --- | --- | --- | --- |
263
- | POST | /api/events | Create an event | administrator |
264
- | GET | /api/events | List visible events | account member |
337
+ | Method | Path | Purpose | Auth |
338
+ | ------ | ----------- | ------------------- | -------------- |
339
+ | POST | /api/events | Create an event | administrator |
340
+ | GET | /api/events | List visible events | account member |
265
341
  ```
266
342
 
267
343
  API contract details can be covered by integration tests that reference the relevant scenario and rule IDs.
@@ -273,10 +349,10 @@ Use `## Permissions` for role, group, and tenant capability matrices.
273
349
  ```md
274
350
  ## Permissions
275
351
 
276
- | Capability | Owner | Administrator | Teacher | Attendee |
277
- | --- | --- | --- | --- | --- |
278
- | Manage payment connection | yes | no | no | no |
279
- | Move own class instance | yes | yes | yes | no |
352
+ | Capability | Owner | Administrator | Teacher | Attendee |
353
+ | ------------------------- | ----- | ------------- | ------- | -------- |
354
+ | Manage payment connection | yes | no | no | no |
355
+ | Move own class instance | yes | yes | yes | no |
280
356
  ```
281
357
 
282
358
  Permissions that must be enforced by the implementation SHOULD also be written as rules so coverage can track them.
@@ -285,7 +361,7 @@ Permissions that must be enforced by the implementation SHOULD also be written a
285
361
 
286
362
  Use `## Lifecycle` for state machines and transition rules for entities such as bookings, payments, subscriptions, passes, and recurring event instances.
287
363
 
288
- ```md
364
+ ````md
289
365
  ## Lifecycle
290
366
 
291
367
  Payment states:
@@ -295,9 +371,11 @@ pending -> paid
295
371
  pending -> failed
296
372
  paid -> refunded
297
373
  ```
374
+ ````
298
375
 
299
376
  Invalid transitions MUST be rejected by the API.
300
- ```
377
+
378
+ ````
301
379
 
302
380
  Lifecycle behavior that must be executable SHOULD be represented by rules and scenarios in the same feature file.
303
381
 
@@ -311,7 +389,7 @@ Use `## Test Environment` for mocks, seed data, fixed-time behavior, provider ad
311
389
  - Email delivery is mocked and exposes the latest magic link to tests.
312
390
  - MobilePay runs through a deterministic mock in CI.
313
391
  - Time is frozen during recurring-event generation tests.
314
- ```
392
+ ````
315
393
 
316
394
  This section is especially useful for SaaS apps with external dependencies such as payment providers, email, calendars, or third-party APIs.
317
395
 
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { mkdir, readFile, writeFile } from "node:fs/promises";
7
7
  import path from "node:path";
8
- import { collectSpecScreenshots, insertReportMetadata, renderHtmlReport, validateScenarioScreenshots, writeTextFile, } from "./index.js";
8
+ import { collectSpecScreenshots, insertReportMetadata, loadProjectConfiguration, renderHtmlReport, validateScenarioScreenshots, writeTextFile, } from "./index.js";
9
9
  import { githubReportMetadata } from "./githubReportMetadata.js";
10
10
  import { publishGithubActionDiffReport } from "./githubActionDiffReport.js";
11
11
  import { publishGithubActionReport } from "./githubActionReport.js";
@@ -22,12 +22,13 @@ main().catch((error) => {
22
22
  async function main() {
23
23
  const [command = "help", ...args] = process.argv.slice(2);
24
24
  const options = parseArgs(args);
25
+ const configuration = await loadProjectConfiguration();
25
26
  if (command === "check")
26
- return runCheck(options);
27
+ return runCheck(options, configuration);
27
28
  if (command === "report")
28
- return runReport(options);
29
+ return runReport(options, configuration);
29
30
  if (command === "coverage")
30
- return runCoverage(options);
31
+ return runCoverage(options, configuration);
31
32
  if (command === "github-report")
32
33
  return publishGithubActionReport(options);
33
34
  if (command === "github-diff-report")
@@ -37,13 +38,15 @@ async function main() {
37
38
  printHelp();
38
39
  process.exit(command === "help" || command === "--help" || command === "-h" ? 0 : 1);
39
40
  }
40
- async function runCheck(options) {
41
+ async function runCheck(options, configuration) {
41
42
  const result = await checkSpecDocuments({
42
43
  specs: optionList(options.specs, defaultSpecPattern),
43
44
  tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
44
45
  requireModelCoverage: booleanOption(options, "require-model-coverage", true),
45
46
  requireRuleCoverage: booleanOption(options, "require-rule-coverage", true),
46
47
  requireScenarioCoverage: booleanOption(options, "require-scenario-coverage", true),
48
+ requireCriticalJourneyCoverage: booleanOption(options, "require-critical-journey-coverage", false),
49
+ layers: configuration.report?.layers,
47
50
  });
48
51
  printIssues([...result.validationIssues, ...result.coverageIssues]);
49
52
  if (!result.ok)
@@ -53,13 +56,14 @@ async function runCheck(options) {
53
56
  const scenarioCount = result.features.reduce((sum, spec) => sum + spec.scenarios.length, 0);
54
57
  console.log(`Spec check passed: ${result.models.length} model(s), ${result.features.length} feature(s), ${result.stacks.length} stack(s), ${result.designs.length} design(s), ${modelItemCount} model item(s), ${ruleCount} rule(s), ${scenarioCount} scenario(s).`);
55
58
  }
56
- async function runCoverage(options) {
59
+ async function runCoverage(options, configuration) {
57
60
  const result = await checkSpecDocuments({
58
61
  specs: optionList(options.specs, defaultSpecPattern),
59
62
  tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
60
63
  requireModelCoverage: false,
61
64
  requireRuleCoverage: false,
62
65
  requireScenarioCoverage: false,
66
+ layers: configuration.report?.layers,
63
67
  });
64
68
  printIssues(result.coverageIssues);
65
69
  if (!result.coverage) {
@@ -70,16 +74,18 @@ async function runCoverage(options) {
70
74
  }
71
75
  const report = buildSpecImplementationReport(result.features, result.coverage, result.models);
72
76
  console.log(formatSpecImplementationReport(report));
73
- if (booleanOption(options, "fail-on-missing", true) && hasMissingCoverage(report)) {
77
+ if (booleanOption(options, "fail-on-missing", true) &&
78
+ hasMissingCoverage(report)) {
74
79
  process.exit(1);
75
80
  }
76
81
  }
77
- async function runReport(options) {
82
+ async function runReport(options, configuration) {
78
83
  const result = await checkSpecDocuments({
79
84
  specs: optionList(options.specs, defaultSpecPattern),
80
85
  tests: options.tests === "" ? [] : optionList(options.tests, defaultTestPattern),
81
86
  requireRuleCoverage: booleanOption(options, "require-rule-coverage", false),
82
87
  requireScenarioCoverage: false,
88
+ layers: configuration.report?.layers,
83
89
  });
84
90
  const out = options.out ?? defaultReportPath;
85
91
  const screenshots = options.screenshots === ""
@@ -104,6 +110,7 @@ async function runReport(options) {
104
110
  coverage: result.coverage,
105
111
  screenshots,
106
112
  validationIssues,
113
+ ...configuration.report,
107
114
  ...githubSourceLinkOptions(),
108
115
  });
109
116
  await writeTextFile(out, insertReportMetadata(report, await githubReportMetadata({ includeGitFallbacks: true })));
@@ -226,6 +233,7 @@ Options:
226
233
  --require-model-coverage Defaults to true for check. Use --require-model-coverage=false to disable.
227
234
  --require-rule-coverage Defaults to true for check. Use --require-rule-coverage=false to disable.
228
235
  --require-scenario-coverage Defaults to true for check. Use --require-scenario-coverage=false to disable.
236
+ --require-critical-journey-coverage Require every critical end-to-end journey to have a test reference.
229
237
  --enforce-evidence Defaults to true for report. Use --enforce-evidence=false to disable.
230
238
  --require-declared-evidence Alias for --enforce-evidence.
231
239
  --require-screenshots Deprecated alias for --enforce-evidence.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FeatureSpecMdConfiguration, ReportLayer, SpecDocument, ValidationIssue } from "./types.js";
2
+ export declare function loadProjectConfiguration(cwd?: string): Promise<FeatureSpecMdConfiguration>;
3
+ export declare function normalizeProjectConfiguration(value: unknown): FeatureSpecMdConfiguration;
4
+ export declare function validateDocumentLayers(documents: SpecDocument[], layers?: ReportLayer[]): ValidationIssue[];
5
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACX,YAAY,EACZ,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,wBAAsB,wBAAwB,CAC5C,GAAG,SAAgB,GAClB,OAAO,CAAC,0BAA0B,CAAC,CAMrC;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,GACb,0BAA0B,CA0B5B;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,YAAY,EAAE,EACzB,MAAM,GAAE,WAAW,EAAO,GACzB,eAAe,EAAE,CAyCnB"}
package/dist/config.js ADDED
@@ -0,0 +1,97 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ export async function loadProjectConfiguration(cwd = process.cwd()) {
4
+ const packagePath = path.join(cwd, "package.json");
5
+ const packageJson = JSON.parse(await readFile(packagePath, "utf8"));
6
+ return normalizeProjectConfiguration(packageJson.featureSpecMd);
7
+ }
8
+ export function normalizeProjectConfiguration(value) {
9
+ if (value === undefined)
10
+ return {};
11
+ if (!isRecord(value))
12
+ throw new Error("package.json featureSpecMd must be an object.");
13
+ const report = value.report;
14
+ if (report === undefined)
15
+ return {};
16
+ if (!isRecord(report))
17
+ throw new Error("package.json featureSpecMd.report must be an object.");
18
+ const layers = report.layers;
19
+ if (layers !== undefined && !Array.isArray(layers))
20
+ throw new Error("featureSpecMd.report.layers must be an array.");
21
+ return {
22
+ report: {
23
+ layers: layers?.map(normalizeLayer),
24
+ layersDefaultOpen: optionalBoolean(report.layersDefaultOpen, "featureSpecMd.report.layersDefaultOpen"),
25
+ documentsDefaultOpen: optionalBoolean(report.documentsDefaultOpen, "featureSpecMd.report.documentsDefaultOpen"),
26
+ },
27
+ };
28
+ }
29
+ export function validateDocumentLayers(documents, layers = []) {
30
+ if (!layers.length)
31
+ return [];
32
+ const issues = [];
33
+ const seen = new Set();
34
+ for (const layer of layers) {
35
+ if (!/^[a-z][a-z0-9-]*$/.test(layer.id)) {
36
+ issues.push({
37
+ code: "invalid-report-layer-id",
38
+ severity: "error",
39
+ message: `Report layer id "${layer.id}" must use lowercase words separated by hyphens.`,
40
+ });
41
+ }
42
+ if (seen.has(layer.id)) {
43
+ issues.push({
44
+ code: "duplicate-report-layer-id",
45
+ severity: "error",
46
+ message: `Report layer id "${layer.id}" is configured more than once.`,
47
+ });
48
+ }
49
+ seen.add(layer.id);
50
+ }
51
+ for (const document of documents) {
52
+ const layer = document.frontmatter.layer;
53
+ if (!layer) {
54
+ issues.push({
55
+ code: "missing-report-layer",
56
+ severity: "warning",
57
+ message: `Spec "${document.frontmatter.id}" has no report layer and will appear under Other.`,
58
+ filePath: document.filePath,
59
+ });
60
+ }
61
+ else if (!seen.has(layer)) {
62
+ issues.push({
63
+ code: "unknown-report-layer",
64
+ severity: "error",
65
+ message: `Spec "${document.frontmatter.id}" references unknown report layer "${layer}".`,
66
+ filePath: document.filePath,
67
+ });
68
+ }
69
+ }
70
+ return issues;
71
+ }
72
+ function normalizeLayer(value, index) {
73
+ if (!isRecord(value))
74
+ throw new Error(`featureSpecMd.report.layers[${index}] must be an object.`);
75
+ if (typeof value.id !== "string" || !value.id.trim())
76
+ throw new Error(`featureSpecMd.report.layers[${index}].id is required.`);
77
+ if (typeof value.title !== "string" || !value.title.trim())
78
+ throw new Error(`featureSpecMd.report.layers[${index}].title is required.`);
79
+ if (value.description !== undefined && typeof value.description !== "string")
80
+ throw new Error(`featureSpecMd.report.layers[${index}].description must be a string.`);
81
+ return {
82
+ id: value.id.trim(),
83
+ title: value.title.trim(),
84
+ description: value.description?.trim(),
85
+ };
86
+ }
87
+ function optionalBoolean(value, name) {
88
+ if (value === undefined)
89
+ return undefined;
90
+ if (typeof value !== "boolean")
91
+ throw new Error(`${name} must be boolean.`);
92
+ return value;
93
+ }
94
+ function isRecord(value) {
95
+ return typeof value === "object" && value !== null && !Array.isArray(value);
96
+ }
97
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ export declare function buildCoverageSummary(specs: FeatureSpec[], references: T
15
15
  export declare function validateCoverage(coverage: CoverageSummary, options?: {
16
16
  requireRuleCoverage?: boolean;
17
17
  requireScenarioCoverage?: boolean;
18
+ criticalJourneyIds?: string[];
18
19
  }): ValidationIssue[];
19
20
  /** Load and parse all feature specs matching the provided globs. */
20
21
  export declare function loadFeatureSpecs(patterns: string[]): Promise<FeatureSpec[]>;
@@ -24,6 +25,7 @@ export declare function checkFeatureSpecs(options: {
24
25
  tests?: string[];
25
26
  requireRuleCoverage?: boolean;
26
27
  requireScenarioCoverage?: boolean;
28
+ requireCriticalJourneyCoverage?: boolean;
27
29
  }): Promise<{
28
30
  specs: FeatureSpec[];
29
31
  validationIssues: ValidationIssue[];
@@ -1 +1 @@
1
- {"version":3,"file":"featureSpecs.d.ts","sourceRoot":"","sources":["../src/featureSpecs.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAEV,eAAe,EAGf,WAAW,EAKX,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAWpB,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,WAAW,CAcb;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,EAAE,CA6GxE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,SAAa,GACpB,aAAa,EAAE,CAyBjB;AAED,qFAAqF;AACrF,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,4BAM7D;AAED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,aAAa,EAAE,GAC1B,eAAe,CAkCjB;AAED,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC9B,qBAmDP;AAED,oEAAoE;AACpE,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,0BAQxD;AAED,6EAA6E;AAC7E,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;;;;;;GAsBA"}
1
+ {"version":3,"file":"featureSpecs.d.ts","sourceRoot":"","sources":["../src/featureSpecs.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAEV,eAAe,EAGf,WAAW,EAMX,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAYpB,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,WAAW,CAcb;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,EAAE,CA6GxE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,SAAa,GACpB,aAAa,EAAE,CAyBjB;AAED,qFAAqF;AACrF,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,4BAM7D;AAED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,aAAa,EAAE,GAC1B,eAAe,CAkCjB;AAED,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,qBAkEP;AAED,oEAAoE;AACpE,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,0BAQxD;AAED,6EAA6E;AAC7E,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;;;;;;GA4BA"}
@@ -13,6 +13,7 @@ const scenarioTestTypes = [
13
13
  "skip",
14
14
  ];
15
15
  const screenshotPolicies = ["required", "optional", "skip"];
16
+ const journeyPaths = ["happy", "failure"];
16
17
  /** Parse one feature spec Markdown document into structured metadata, rules, and scenarios. */
17
18
  export function parseFeatureSpec(source, options = {}) {
18
19
  const filePath = options.filePath ?? "<inline>";
@@ -137,6 +138,18 @@ export function validateCoverage(coverage, options = {}) {
137
138
  });
138
139
  }
139
140
  }
141
+ for (const id of options.criticalJourneyIds ?? []) {
142
+ const item = coverage.scenarioCoverage.find((candidate) => candidate.id === id);
143
+ if (item && !item.covered) {
144
+ issues.push({
145
+ code: "missing-critical-journey-coverage",
146
+ severity: "error",
147
+ message: `Critical end-to-end journey "${item.id}" has no matching test reference.`,
148
+ filePath: item.filePath,
149
+ line: item.line,
150
+ });
151
+ }
152
+ }
140
153
  for (const ref of coverage.orphanScenarioReferences) {
141
154
  issues.push({
142
155
  code: "orphan-scenario-reference",
@@ -176,6 +189,12 @@ export async function checkFeatureSpecs(options) {
176
189
  ? validateCoverage(coverage, {
177
190
  requireRuleCoverage: options.requireRuleCoverage,
178
191
  requireScenarioCoverage: options.requireScenarioCoverage,
192
+ criticalJourneyIds: options.requireCriticalJourneyCoverage
193
+ ? specs
194
+ .flatMap((spec) => spec.scenarios)
195
+ .filter((scenario) => scenario.journey?.critical)
196
+ .map((scenario) => scenario.id)
197
+ : [],
179
198
  })
180
199
  : [];
181
200
  return {
@@ -194,6 +213,11 @@ function parseScenarios(lines, bodyStartLine, frontmatter) {
194
213
  continue;
195
214
  const steps = [];
196
215
  const overrides = {};
216
+ const journey = {
217
+ scope: normalizeJourneyScope(frontmatter.journey),
218
+ path: normalizeJourneyPath(frontmatter.path),
219
+ critical: normalizeBoolean(frontmatter.critical),
220
+ };
197
221
  for (let j = i + 1; j < lines.length; j += 1) {
198
222
  if (/^##?#\s+/.test(lines[j]))
199
223
  break;
@@ -203,6 +227,21 @@ function parseScenarios(lines, bodyStartLine, frontmatter) {
203
227
  const screenshotsMatch = lines[j].trim().match(/^Screenshots:\s*(.+)$/i);
204
228
  if (screenshotsMatch)
205
229
  overrides.screenshots = normalizeScreenshotPolicy(screenshotsMatch[1]);
230
+ const journeyMatch = lines[j].trim().match(/^Journey:\s*(.+)$/i);
231
+ if (journeyMatch && journeyMatch[1].trim().toLowerCase() === "end-to-end")
232
+ journey.scope = "end-to-end";
233
+ const pathMatch = lines[j].trim().match(/^Path:\s*(.+)$/i);
234
+ if (pathMatch)
235
+ journey.path = normalizeJourneyPath(pathMatch[1]);
236
+ const criticalMatch = lines[j].trim().match(/^Critical:\s*(.+)$/i);
237
+ if (criticalMatch)
238
+ journey.critical = normalizeBoolean(criticalMatch[1]);
239
+ const systemsMatch = lines[j].trim().match(/^Systems:\s*(.+)$/i);
240
+ if (systemsMatch)
241
+ journey.systems = systemsMatch[1]
242
+ .split(",")
243
+ .map((item) => item.trim())
244
+ .filter(Boolean);
206
245
  const step = lines[j].trim().match(/^(Given|When|Then|And|But)\s+(.+)$/);
207
246
  if (step)
208
247
  steps.push({
@@ -216,6 +255,14 @@ function parseScenarios(lines, bodyStartLine, frontmatter) {
216
255
  title: match[2].trim(),
217
256
  line: bodyStartLine + i,
218
257
  evidence: resolveEvidencePolicy(frontmatter, overrides),
258
+ journey: journey.scope === "end-to-end"
259
+ ? {
260
+ scope: journey.scope,
261
+ path: journey.path ?? "happy",
262
+ critical: journey.critical ?? false,
263
+ systems: journey.systems ?? [],
264
+ }
265
+ : undefined,
219
266
  steps,
220
267
  });
221
268
  }
@@ -242,14 +289,52 @@ function normalizeScreenshotPolicy(value) {
242
289
  return "skip";
243
290
  return screenshotPolicies.find((candidate) => candidate === normalized);
244
291
  }
292
+ function normalizeJourneyScope(value) {
293
+ if (typeof value !== "string")
294
+ return undefined;
295
+ return value.trim().toLowerCase() === "end-to-end" ? "end-to-end" : undefined;
296
+ }
297
+ function normalizeJourneyPath(value) {
298
+ if (typeof value !== "string")
299
+ return undefined;
300
+ const normalized = value.trim().toLowerCase();
301
+ return journeyPaths.find((candidate) => candidate === normalized);
302
+ }
303
+ function normalizeBoolean(value) {
304
+ if (typeof value === "boolean")
305
+ return value;
306
+ if (typeof value !== "string")
307
+ return undefined;
308
+ const normalized = value.trim().toLowerCase();
309
+ if (normalized === "true")
310
+ return true;
311
+ if (normalized === "false")
312
+ return false;
313
+ return undefined;
314
+ }
245
315
  function validateEvidencePolicy(spec, frontmatter) {
246
316
  const issues = [];
247
317
  if (frontmatter.test && !normalizeTestType(frontmatter.test)) {
248
318
  issues.push(issue(spec, "invalid-test-type", "error", `Feature test policy must be one of ${scenarioTestTypes.join(", ")}.`));
249
319
  }
250
- if (frontmatter.screenshots && !normalizeScreenshotPolicy(frontmatter.screenshots)) {
320
+ if (frontmatter.screenshots &&
321
+ !normalizeScreenshotPolicy(frontmatter.screenshots)) {
251
322
  issues.push(issue(spec, "invalid-screenshot-policy", "error", `Feature screenshots policy must be one of ${screenshotPolicies.join(", ")} or none.`));
252
323
  }
324
+ if (frontmatter.journey && !normalizeJourneyScope(frontmatter.journey)) {
325
+ issues.push(issue(spec, "invalid-journey-scope", "error", 'Feature journey policy must be "end-to-end".'));
326
+ }
327
+ if (frontmatter.path && !normalizeJourneyPath(frontmatter.path)) {
328
+ issues.push(issue(spec, "invalid-journey-path", "error", `Feature journey path must be one of ${journeyPaths.join(", ")}.`));
329
+ }
330
+ if (frontmatter.critical !== undefined &&
331
+ normalizeBoolean(frontmatter.critical) === undefined) {
332
+ issues.push(issue(spec, "invalid-journey-criticality", "error", "Feature journey critical policy must be true or false."));
333
+ }
334
+ if (!normalizeJourneyScope(frontmatter.journey) &&
335
+ (frontmatter.path !== undefined || frontmatter.critical !== undefined)) {
336
+ issues.push(issue(spec, "journey-default-without-scope", "error", "Feature path and critical defaults require journey: end-to-end."));
337
+ }
253
338
  return issues;
254
339
  }
255
340
  function issue(spec, code, severity, message, line) {