@sun-asterisk/sungen 3.2.15 → 3.2.16-beta.10

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 (165) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +197 -13
  3. package/dist/cli/commands/delivery.js.map +1 -1
  4. package/dist/dashboard/templates/index.html +1 -1
  5. package/dist/exporters/feature-parser.d.ts +16 -1
  6. package/dist/exporters/feature-parser.d.ts.map +1 -1
  7. package/dist/exporters/feature-parser.js +21 -2
  8. package/dist/exporters/feature-parser.js.map +1 -1
  9. package/dist/exporters/matrix/build.d.ts +61 -0
  10. package/dist/exporters/matrix/build.d.ts.map +1 -0
  11. package/dist/exporters/matrix/build.js +497 -0
  12. package/dist/exporters/matrix/build.js.map +1 -0
  13. package/dist/exporters/matrix/export.d.ts +50 -0
  14. package/dist/exporters/matrix/export.d.ts.map +1 -0
  15. package/dist/exporters/matrix/export.js +152 -0
  16. package/dist/exporters/matrix/export.js.map +1 -0
  17. package/dist/exporters/matrix/fingerprint.d.ts +20 -0
  18. package/dist/exporters/matrix/fingerprint.d.ts.map +1 -0
  19. package/dist/exporters/matrix/fingerprint.js +83 -0
  20. package/dist/exporters/matrix/fingerprint.js.map +1 -0
  21. package/dist/exporters/matrix/gates.d.ts +21 -0
  22. package/dist/exporters/matrix/gates.d.ts.map +1 -0
  23. package/dist/exporters/matrix/gates.js +367 -0
  24. package/dist/exporters/matrix/gates.js.map +1 -0
  25. package/dist/exporters/matrix/map-loader.d.ts +22 -0
  26. package/dist/exporters/matrix/map-loader.d.ts.map +1 -0
  27. package/dist/exporters/matrix/map-loader.js +193 -0
  28. package/dist/exporters/matrix/map-loader.js.map +1 -0
  29. package/dist/exporters/matrix/render-csv.d.ts +9 -0
  30. package/dist/exporters/matrix/render-csv.d.ts.map +1 -0
  31. package/dist/exporters/matrix/render-csv.js +92 -0
  32. package/dist/exporters/matrix/render-csv.js.map +1 -0
  33. package/dist/exporters/matrix/render-xlsx.d.ts +41 -0
  34. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -0
  35. package/dist/exporters/matrix/render-xlsx.js +430 -0
  36. package/dist/exporters/matrix/render-xlsx.js.map +1 -0
  37. package/dist/exporters/matrix/types.d.ts +199 -0
  38. package/dist/exporters/matrix/types.d.ts.map +1 -0
  39. package/dist/exporters/matrix/types.js +15 -0
  40. package/dist/exporters/matrix/types.js.map +1 -0
  41. package/dist/exporters/matrix/wording.d.ts +61 -0
  42. package/dist/exporters/matrix/wording.d.ts.map +1 -0
  43. package/dist/exporters/matrix/wording.js +221 -0
  44. package/dist/exporters/matrix/wording.js.map +1 -0
  45. package/dist/exporters/scenario-merger.d.ts.map +1 -1
  46. package/dist/exporters/scenario-merger.js +2 -1
  47. package/dist/exporters/scenario-merger.js.map +1 -1
  48. package/dist/exporters/spec-parser.d.ts.map +1 -1
  49. package/dist/exporters/spec-parser.js +2 -1
  50. package/dist/exporters/spec-parser.js.map +1 -1
  51. package/dist/exporters/xlsx-report-builder.d.ts +1 -1
  52. package/dist/exporters/xlsx-report-builder.d.ts.map +1 -1
  53. package/dist/exporters/xlsx-report-builder.js +3 -3
  54. package/dist/exporters/xlsx-report-builder.js.map +1 -1
  55. package/dist/harness/audit.d.ts.map +1 -1
  56. package/dist/harness/audit.js +16 -2
  57. package/dist/harness/audit.js.map +1 -1
  58. package/dist/harness/blindspot.d.ts.map +1 -1
  59. package/dist/harness/blindspot.js +2 -1
  60. package/dist/harness/blindspot.js.map +1 -1
  61. package/dist/harness/capability-plan.d.ts.map +1 -1
  62. package/dist/harness/capability-plan.js +3 -2
  63. package/dist/harness/capability-plan.js.map +1 -1
  64. package/dist/harness/capability.d.ts +25 -0
  65. package/dist/harness/capability.d.ts.map +1 -1
  66. package/dist/harness/capability.js +44 -2
  67. package/dist/harness/capability.js.map +1 -1
  68. package/dist/harness/feedback.d.ts.map +1 -1
  69. package/dist/harness/feedback.js +3 -2
  70. package/dist/harness/feedback.js.map +1 -1
  71. package/dist/harness/flow-check.d.ts.map +1 -1
  72. package/dist/harness/flow-check.js +2 -1
  73. package/dist/harness/flow-check.js.map +1 -1
  74. package/dist/harness/flow-plan.d.ts.map +1 -1
  75. package/dist/harness/flow-plan.js +3 -2
  76. package/dist/harness/flow-plan.js.map +1 -1
  77. package/dist/harness/intent.d.ts.map +1 -1
  78. package/dist/harness/intent.js +2 -1
  79. package/dist/harness/intent.js.map +1 -1
  80. package/dist/harness/journey.d.ts.map +1 -1
  81. package/dist/harness/journey.js +3 -2
  82. package/dist/harness/journey.js.map +1 -1
  83. package/dist/harness/ledger.d.ts.map +1 -1
  84. package/dist/harness/ledger.js +3 -2
  85. package/dist/harness/ledger.js.map +1 -1
  86. package/dist/harness/manifest.d.ts.map +1 -1
  87. package/dist/harness/manifest.js +4 -3
  88. package/dist/harness/manifest.js.map +1 -1
  89. package/dist/harness/parse.d.ts.map +1 -1
  90. package/dist/harness/parse.js +16 -3
  91. package/dist/harness/parse.js.map +1 -1
  92. package/dist/harness/quality-gates.d.ts.map +1 -1
  93. package/dist/harness/quality-gates.js +2 -1
  94. package/dist/harness/quality-gates.js.map +1 -1
  95. package/dist/harness/read-text.d.ts +22 -0
  96. package/dist/harness/read-text.d.ts.map +1 -0
  97. package/dist/harness/read-text.js +64 -0
  98. package/dist/harness/read-text.js.map +1 -0
  99. package/dist/harness/script-check.d.ts.map +1 -1
  100. package/dist/harness/script-check.js +3 -2
  101. package/dist/harness/script-check.js.map +1 -1
  102. package/dist/harness/sensors.d.ts.map +1 -1
  103. package/dist/harness/sensors.js +2 -10
  104. package/dist/harness/sensors.js.map +1 -1
  105. package/dist/harness/spec-coverage.d.ts +5 -0
  106. package/dist/harness/spec-coverage.d.ts.map +1 -1
  107. package/dist/harness/spec-coverage.js +17 -7
  108. package/dist/harness/spec-coverage.js.map +1 -1
  109. package/dist/harness/trace.d.ts.map +1 -1
  110. package/dist/harness/trace.js +4 -3
  111. package/dist/harness/trace.js.map +1 -1
  112. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  113. package/dist/harness/viewpoint-ledger.js +2 -1
  114. package/dist/harness/viewpoint-ledger.js.map +1 -1
  115. package/dist/orchestrator/templates/ai-src/commands/create-test.md +10 -1
  116. package/dist/orchestrator/templates/ai-src/commands/delivery.md +203 -120
  117. package/dist/orchestrator/templates/ai-src/config/claude.md +1 -1
  118. package/dist/orchestrator/templates/ai-src/config/copilot.md +1 -1
  119. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +102 -6
  120. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -0
  121. package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +1 -1
  122. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +23 -0
  123. package/package.json +4 -4
  124. package/src/cli/commands/delivery.ts +227 -15
  125. package/src/dashboard/templates/index.html +1 -1
  126. package/src/exporters/feature-parser.ts +21 -2
  127. package/src/exporters/matrix/build.ts +532 -0
  128. package/src/exporters/matrix/export.ts +149 -0
  129. package/src/exporters/matrix/fingerprint.ts +49 -0
  130. package/src/exporters/matrix/gates.ts +400 -0
  131. package/src/exporters/matrix/map-loader.ts +163 -0
  132. package/src/exporters/matrix/render-csv.ts +94 -0
  133. package/src/exporters/matrix/render-xlsx.ts +420 -0
  134. package/src/exporters/matrix/types.ts +226 -0
  135. package/src/exporters/matrix/wording.ts +221 -0
  136. package/src/exporters/scenario-merger.ts +2 -1
  137. package/src/exporters/spec-parser.ts +2 -1
  138. package/src/exporters/xlsx-report-builder.ts +3 -2
  139. package/src/harness/audit.ts +17 -3
  140. package/src/harness/blindspot.ts +2 -1
  141. package/src/harness/capability-plan.ts +3 -2
  142. package/src/harness/capability.ts +53 -3
  143. package/src/harness/feedback.ts +3 -2
  144. package/src/harness/flow-check.ts +2 -1
  145. package/src/harness/flow-plan.ts +3 -2
  146. package/src/harness/intent.ts +2 -1
  147. package/src/harness/journey.ts +3 -2
  148. package/src/harness/ledger.ts +3 -2
  149. package/src/harness/manifest.ts +4 -3
  150. package/src/harness/parse.ts +17 -3
  151. package/src/harness/quality-gates.ts +2 -1
  152. package/src/harness/read-text.ts +28 -0
  153. package/src/harness/script-check.ts +3 -2
  154. package/src/harness/sensors.ts +2 -1
  155. package/src/harness/spec-coverage.ts +22 -7
  156. package/src/harness/trace.ts +4 -3
  157. package/src/harness/viewpoint-ledger.ts +2 -1
  158. package/src/orchestrator/templates/ai-src/commands/create-test.md +10 -1
  159. package/src/orchestrator/templates/ai-src/commands/delivery.md +203 -120
  160. package/src/orchestrator/templates/ai-src/config/claude.md +1 -1
  161. package/src/orchestrator/templates/ai-src/config/copilot.md +1 -1
  162. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +102 -6
  163. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +1 -0
  164. package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +1 -1
  165. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +23 -0
@@ -4,6 +4,7 @@
4
4
  * Reuses the existing GherkinParser.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SCENARIO_ID = void 0;
7
8
  exports.parseFeatureMetadata = parseFeatureMetadata;
8
9
  exports.isStepsBaseScenario = isStepsBaseScenario;
9
10
  exports.isSampleScaffoldScenario = isSampleScaffoldScenario;
@@ -173,12 +174,27 @@ function extractAuthRole(tags) {
173
174
  return null;
174
175
  }
175
176
  /**
176
- * Extract VP ID and human-readable name from scenario name like
177
+ * The leading viewpoint/requirement id of a scenario title.
178
+ *
179
+ * The `VP-` prefix is the scheme sungen suggests, NOT a requirement: real projects
180
+ * bring their own (`SEC-123`, `PER-345`, `MS-HP-001`, `VP0-001`), and the harness
181
+ * has always been format-tolerant about it. The exporters were not — a project
182
+ * using `SEC-123` got no id at all, which made every scenario "unaddressable" and
183
+ * blocked the whole delivery matrix at Gate A.
184
+ *
185
+ * Shape: uppercase segments joined by `-`, ending in a number (with an optional
186
+ * letter or sub-code suffix). Requiring the trailing number is what keeps an
187
+ * ordinary title word ("A11y check…") from being mistaken for an id.
188
+ */
189
+ exports.SCENARIO_ID = /^([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*-\d+(?:[a-zA-Z]|-[A-Z0-9]+)?)/;
190
+ /**
191
+ * Extract the id and the human-readable name from a scenario title:
177
192
  * "VP-UI-001 Modal displays all required fields" →
178
193
  * { vpId: "VP-UI-001", category1: "Modal displays all required fields" }
194
+ * "SEC-123 Login is protected" → { vpId: "SEC-123", category1: "Login is protected" }
179
195
  */
180
196
  function splitVpAndName(scenarioName) {
181
- const match = scenarioName.match(/^(VP-[A-Z][A-Z0-9]*-\d+[a-zA-Z]?)\s+(.+)$/);
197
+ const match = scenarioName.match(new RegExp(exports.SCENARIO_ID.source + '\\s+(.+)$'));
182
198
  if (match) {
183
199
  return { vpId: match[1], category1: match[2] };
184
200
  }
@@ -195,6 +211,9 @@ function splitVpAndName(scenarioName) {
195
211
  function mapVpToCategory2(vpId, scenarioName) {
196
212
  if (!vpId)
197
213
  return 'Function';
214
+ // Compare on the category segment so a project scheme without the `VP-` prefix
215
+ // (`SEC-123`) classifies the same as `VP-SEC-001`.
216
+ vpId = /^VP-/.test(vpId) ? vpId : `VP-${vpId}`;
198
217
  if (vpId.startsWith('VP-SEC-')) {
199
218
  if (scenarioName && /xss|injection/i.test(scenarioName))
200
219
  return 'Function';
@@ -1 +1 @@
1
- {"version":3,"file":"feature-parser.js","sourceRoot":"","sources":["../../src/exporters/feature-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-parser.js","sourceRoot":"","sources":["../../src/exporters/feature-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Build the matrix model: derive atomic coverage variants from the merged
3
+ * feature/spec view, assemble delivery items per the Delivery Map, attach
4
+ * per-variant Playwright results, and roll parents up (derived only — Gate F
5
+ * is structural: there is no independent parent result input).
6
+ */
7
+ import { FeatureMetadata, PlaywrightResult } from '../types';
8
+ import { MergedScenario } from '../scenario-merger';
9
+ import { CoverageVariant, DeliveryItem, DeliveryMap, ItemResult, VariantState, MatrixModel, RequirementCoverage } from './types';
10
+ export interface BuildInputs {
11
+ unit: string;
12
+ feature: FeatureMetadata;
13
+ merged: MergedScenario[];
14
+ testData: Record<string, string> | null;
15
+ results: Map<string, PlaywrightResult> | null;
16
+ map: DeliveryMap;
17
+ transformerVersion: string;
18
+ /** requirements/spec.md content — source of the requirement-id inventory (FR/TR/NFR). */
19
+ specText?: string;
20
+ }
21
+ /**
22
+ * Derive every atomic coverage variant of the unit (one per scenario, or one per
23
+ * `@cases` dataset row). Exported separately so the gates + the map-proposal
24
+ * support tooling see the same universe the builder does.
25
+ */
26
+ export declare function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' | 'testData' | 'results'>): CoverageVariant[];
27
+ /**
28
+ * Make invisible test data VISIBLE instead of losing it (review GAP-04):
29
+ * '' → (empty) · whitespace-only → (N spaces) · padded → quoted verbatim.
30
+ * The canonical value is never changed — only its presentation.
31
+ */
32
+ export declare function displayValue(v: string): string;
33
+ /**
34
+ * Requirement inventory ∪ traces → coverage table. Ids are scanned from the spec
35
+ * text (FR-/TR-/NFR-<n>); map overrides win over the derived covered/gap status.
36
+ */
37
+ export declare function computeRequirements(specText: string, map: DeliveryMap, items: DeliveryItem[]): RequirementCoverage[];
38
+ /**
39
+ * The exact word rendered in a variant's Result cell. This is the SINGLE
40
+ * vocabulary both the renderers and the parent's COUNTIF roll-up use — the
41
+ * legacy exporter's statusToTestResult disagreed on two statuses (`skipped`
42
+ * showed N/A but counted as not-run; `interrupted` showed Pending but counted
43
+ * as blocked), which silently skewed the derived parent result.
44
+ */
45
+ export declare function variantState(v: CoverageVariant): VariantState;
46
+ /**
47
+ * Derived parent result — precedence failed → blocked → all-N/A → not_run →
48
+ * partial → passed. `N/A` variants leave the denominator (an intentionally
49
+ * skipped case must not make the parent look incomplete).
50
+ */
51
+ export declare function rollUp(variants: CoverageVariant[]): {
52
+ result: ItemResult;
53
+ counts: DeliveryItem['resultCounts'];
54
+ };
55
+ /**
56
+ * Expand one map variant ref to concrete variant refs:
57
+ * a bare VP-id whose scenario has a dataset means ALL its rows.
58
+ */
59
+ export declare function expandMapRef(ref: string, variantsByVp: Map<string, CoverageVariant[]>): CoverageVariant[];
60
+ export declare function buildMatrix(inputs: BuildInputs): MatrixModel;
61
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/exporters/matrix/build.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAUpD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,EAGZ,WAAW,EACX,mBAAmB,EAEpB,MAAM,SAAS,CAAC;AAwDjB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAC9C,GAAG,EAAE,WAAW,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC,GAAG,eAAe,EAAE,CAmJ1H;AA2BD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9C;AASD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,YAAY,EAAE,GACpB,mBAAmB,EAAE,CA8BvB;AAyBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,eAAe,GAAG,YAAY,CAW7D;AAMD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC,cAAc,CAAC,CAAA;CAAE,CAYhH;AAUD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,GAAG,eAAe,EAAE,CAMzG;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CA8G5D"}
@@ -0,0 +1,497 @@
1
+ "use strict";
2
+ /**
3
+ * Build the matrix model: derive atomic coverage variants from the merged
4
+ * feature/spec view, assemble delivery items per the Delivery Map, attach
5
+ * per-variant Playwright results, and roll parents up (derived only — Gate F
6
+ * is structural: there is no independent parent result input).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.deriveVariants = deriveVariants;
10
+ exports.displayValue = displayValue;
11
+ exports.computeRequirements = computeRequirements;
12
+ exports.variantState = variantState;
13
+ exports.rollUp = rollUp;
14
+ exports.expandMapRef = expandMapRef;
15
+ exports.buildMatrix = buildMatrix;
16
+ const feature_parser_1 = require("../feature-parser");
17
+ const result_variants_1 = require("../result-variants");
18
+ const wording_1 = require("./wording");
19
+ const fingerprint_1 = require("./fingerprint");
20
+ const types_1 = require("./types");
21
+ const gates_1 = require("./gates");
22
+ // ---------------------------------------------------------------------------
23
+ // Variant derivation
24
+ // ---------------------------------------------------------------------------
25
+ /** Collapse `{{var}}` placeholders so data values become parameters, not shape. */
26
+ function normalizeShape(text) {
27
+ return text.replace(/\{\{[^}]*\}\}/g, '{{*}}').replace(/\s+/g, ' ').trim();
28
+ }
29
+ function deriveLayers(tags) {
30
+ const layers = new Set(['ui']);
31
+ if (tags.some((t) => t === '@api' || t.startsWith('@api:') || t === '@requires:api'))
32
+ layers.add('api');
33
+ if (tags.some((t) => t.startsWith('@query') || t === '@requires:db'))
34
+ layers.add('db');
35
+ return Array.from(layers);
36
+ }
37
+ /** 'simple' single G*→W*→T* pass; 'sequence' when the flow re-enters Given/When after a Then. */
38
+ function deriveProcedureProfile(m) {
39
+ if ((0, feature_parser_1.extractTestcaseType)(m.feature.tags) === 'Manual')
40
+ return 'manual';
41
+ const order = m.feature.orderedSteps.map((s) => s.bucket);
42
+ let seenThen = false;
43
+ for (const bucket of order) {
44
+ if (bucket === 'then')
45
+ seenThen = true;
46
+ else if (seenThen)
47
+ return 'sequence'; // action/setup after an assertion → ordered flow
48
+ }
49
+ return 'simple';
50
+ }
51
+ function manualReason(tags) {
52
+ const t = tags.find((x) => x.startsWith('@manual:'));
53
+ return t ? t.slice('@manual:'.length) : undefined;
54
+ }
55
+ /** Resolve `{{var}}` refs of a scenario into display `key: value` pairs. */
56
+ function resolveDataPairs(vars, testData, row) {
57
+ const pairs = [];
58
+ if (row) {
59
+ for (const [k, v] of Object.entries(row)) {
60
+ if (k.startsWith('__') || k === 'case' || k === 'name' || k === 'label')
61
+ continue;
62
+ pairs.push(`${k}: ${displayValue(String(v))}`);
63
+ }
64
+ }
65
+ for (const v of vars) {
66
+ const val = row && v in row ? undefined : testData?.[v]; // row columns already listed
67
+ if (val !== undefined)
68
+ pairs.push(`${v}: ${displayValue(val)}`);
69
+ }
70
+ return pairs;
71
+ }
72
+ /**
73
+ * Derive every atomic coverage variant of the unit (one per scenario, or one per
74
+ * `@cases` dataset row). Exported separately so the gates + the map-proposal
75
+ * support tooling see the same universe the builder does.
76
+ */
77
+ function deriveVariants(inputs) {
78
+ const { merged, results } = inputs;
79
+ // Test-data values may cross-reference other keys (email_padded: " {{valid_email}} ") —
80
+ // resolve one level so display cells never leak a template token (review B-04).
81
+ const testData = resolveCrossRefs(inputs.testData);
82
+ const variants = [];
83
+ for (const m of merged) {
84
+ const { vpId, category1 } = (0, feature_parser_1.splitVpAndName)(m.feature.name);
85
+ if (!vpId)
86
+ continue; // Gate A reports it — no variant can be addressed without a VP-id
87
+ const tags = m.feature.tags;
88
+ const mode = (0, feature_parser_1.extractTestcaseType)(tags) === 'Manual' ? 'manual' : 'auto';
89
+ const authRole = (0, feature_parser_1.extractAuthRole)(tags);
90
+ // Category segment of the id, whatever the project's scheme:
91
+ // VP-SEC-001 → SEC · SEC-123 → SEC · MS-HP-001 → MS-HP · PER-345 → PER.
92
+ const vpCategory = vpId.replace(/^VP-/, '').replace(/-\d+(?:[a-zA-Z]|-[A-Z0-9]+)?$/, '');
93
+ const procedureProfile = deriveProcedureProfile(m);
94
+ // Manual scenarios: the `# Tester verifies:` block is classified into structured
95
+ // fields — Setup → precondition (review B-02), Action → trigger, Observable →
96
+ // expected, Oracle → verification method. Labels never remain inside prose.
97
+ const manual = mode === 'manual' && m.feature.comments?.length
98
+ ? (0, wording_1.classifyManualComments)(m.feature.comments)
99
+ : null;
100
+ // Raw (pre-wording) step texts — these feed shapes + Gate C, never the cells.
101
+ const rawTrigger = manual ? manual.actions : m.feature.rawWhenSteps;
102
+ const rawOracle = manual
103
+ ? (manual.expected.length > 0 ? manual.expected : m.feature.rawThenSteps)
104
+ : m.resolvedExpected.filter((s) => s.bucket === 'then').map((s) => s.text);
105
+ // Values the scenario itself produces during the run — captured from the page
106
+ // or bound by a capability precondition. The compiler registers these as
107
+ // "captured" and skips YAML validation; the matrix does the same.
108
+ const runtimeVars = (0, wording_1.runtimeVarsOf)([...m.resolvedSteps.map((st) => st.text), ...m.resolvedExpected.map((st) => st.text)], tags);
109
+ const preconditionProfile = [
110
+ authRole ?? '-',
111
+ m.feature.extendsName ?? '-',
112
+ ...m.feature.rawGivenSteps.map(normalizeShape),
113
+ ...(manual?.preconditions ?? []).map(normalizeShape),
114
+ ].join(' | ');
115
+ // Display precondition = auth state + Background Given (shared start state) +
116
+ // the scenario's own Given steps + manual Setup lines — deduplicated (a manual
117
+ // scenario often repeats the Background navigation as its own Given).
118
+ const precondition = Array.from(new Set([
119
+ ...(authRole ? [authRole === 'no-auth' ? 'The user is signed out.' : `The user is signed in as ${authRole}.`] : []),
120
+ ...inputs.feature.backgroundGivenSteps.map(wording_1.renderPrecondition),
121
+ ...m.feature.rawGivenSteps.map(wording_1.renderPrecondition),
122
+ ...(manual?.preconditions ?? []).map((t) => (0, wording_1.renderSetupInstruction)(t)),
123
+ ]));
124
+ const base = {
125
+ vpId,
126
+ vpCategory,
127
+ priority: (0, feature_parser_1.extractPriority)(tags),
128
+ mode: mode,
129
+ manualReason: manualReason(tags),
130
+ layers: deriveLayers(tags),
131
+ traces: tags.filter((t) => t.startsWith('@spec:')).map((t) => t.slice('@spec:'.length)),
132
+ runtimeVars: [...runtimeVars],
133
+ triggerShape: rawTrigger.map(normalizeShape),
134
+ oracleShape: rawOracle.map(normalizeShape),
135
+ preconditionProfile,
136
+ precondition,
137
+ procedureProfile,
138
+ verification: manual?.verification.map((t) => sentenceOf(t)) ?? [],
139
+ };
140
+ /** Render the display cells for one data context (vars resolved first). */
141
+ const renderCells = (vars) => {
142
+ const sub = (s) => substituteDisplayVars(s, vars, runtimeVars);
143
+ const preconditionOut = precondition.map(sub);
144
+ const verificationOut = base.verification.map(sub);
145
+ if (procedureProfile === 'sequence' && !manual) {
146
+ // Ordered flow (review B-03): keep the event order — actions stay numbered in
147
+ // the trigger, mid-flow assertions render inline as "Verify:", and only the
148
+ // FINAL Then block becomes the expected result.
149
+ const steps = m.feature.orderedSteps;
150
+ let lastActionIdx = -1;
151
+ steps.forEach((s, i) => { if (s.bucket !== 'then')
152
+ lastActionIdx = i; });
153
+ const trigger = [];
154
+ const oracle = [];
155
+ steps.forEach((s, i) => {
156
+ if (i > lastActionIdx)
157
+ oracle.push((0, wording_1.renderExpected)(sub(s.text))); // trailing Then block
158
+ else if (s.bucket === 'then')
159
+ trigger.push(`Verify: ${(0, wording_1.renderExpected)(sub(s.text))}`);
160
+ else if (s.bucket === 'when')
161
+ trigger.push((0, wording_1.renderAction)(sub(s.text)));
162
+ // leading given steps already live in the precondition
163
+ });
164
+ return { trigger, oracle, precondition: preconditionOut, verification: verificationOut };
165
+ }
166
+ const trigger = rawTrigger.map((s) => (0, wording_1.renderAction)(sub(s)));
167
+ const oracle = rawOracle.map((s) => (0, wording_1.renderExpected)(sub(s)));
168
+ return {
169
+ // A pure-render check (Given + Then only) is checked on page load — say so
170
+ // in words instead of a placeholder token (review §10.3).
171
+ trigger: trigger.length > 0 ? trigger : ['No action — the state is checked on page load.'],
172
+ oracle,
173
+ precondition: preconditionOut,
174
+ verification: verificationOut,
175
+ };
176
+ };
177
+ const rows = (0, result_variants_1.getCasesDatasetRows)(m, testData ?? undefined);
178
+ if (rows) {
179
+ // One variant per dataset row; results matched per row label by the shared resolver.
180
+ const resultVariants = (0, result_variants_1.resolveResultVariants)(m, results ?? null, testData ?? undefined);
181
+ const resultByLabel = new Map(resultVariants.map((rv) => [rv.nameSuffix.replace(/^ — /, ''), rv.result]));
182
+ rows.forEach((row, i) => {
183
+ const label = String(row.case ?? row.name ?? row.label ?? `row ${i + 1}`);
184
+ const cells = renderCells({ ...(testData ?? {}), ...rowAsStrings(row) });
185
+ variants.push({
186
+ ...base,
187
+ ref: `${vpId}#${label}`,
188
+ caseLabel: label,
189
+ title: `${category1} — ${label}`,
190
+ condition: label,
191
+ data: resolveDataPairs(m.feature.referencedVars, testData, row),
192
+ trigger: cells.trigger,
193
+ oracle: cells.oracle,
194
+ precondition: cells.precondition,
195
+ verification: cells.verification,
196
+ fingerprint: (0, fingerprint_1.scenarioFingerprint)(m.feature, row),
197
+ result: resultByLabel.get(label),
198
+ });
199
+ });
200
+ }
201
+ else {
202
+ const cells = renderCells(testData ?? {});
203
+ variants.push({
204
+ ...base,
205
+ ref: vpId,
206
+ title: category1,
207
+ condition: category1,
208
+ data: resolveDataPairs(m.feature.referencedVars, testData),
209
+ trigger: cells.trigger,
210
+ oracle: cells.oracle,
211
+ precondition: cells.precondition,
212
+ verification: cells.verification,
213
+ fingerprint: (0, fingerprint_1.scenarioFingerprint)(m.feature),
214
+ result: (0, result_variants_1.resolveResultVariants)(m, results ?? null, testData ?? undefined)[0]?.result,
215
+ });
216
+ }
217
+ }
218
+ return variants;
219
+ }
220
+ /**
221
+ * Display substitution for matrix cells. Unlike the legacy exporter's
222
+ * substituteTestDataVars (which keeps EMPTY values literal for the Steps
223
+ * column), an empty value is a legitimate test input here (an intentionally
224
+ * empty field) — it renders as `(empty)` so the tester sees the intent and no
225
+ * `{{token}}` survives into the deliverable (Gate D would reject it).
226
+ */
227
+ function substituteDisplayVars(text, vars, runtimeVars = new Set()) {
228
+ // `remember … as {{v}}` DECLARES v — leave that token for renderAction, which
229
+ // turns it into a quoted name ("note it as …"), not a value to look up.
230
+ const isCapture = /\bremember\b/i.test(text);
231
+ return text.replace(/\{\{\s*([^}\s]+)\s*\}\}/g, (m, key, offset) => {
232
+ if (isCapture && /\bas\s+$/i.test(text.slice(0, offset)))
233
+ return m;
234
+ // A value the test produces at run time has no static form — name it so the
235
+ // tester knows to compare against what the earlier step captured.
236
+ if (runtimeVars.has(key) || runtimeVars.has(key.split(/[.[]/)[0]))
237
+ return `the captured ${key}`;
238
+ if (!(key in vars))
239
+ return m; // unknown stays literal → Gate D flags it
240
+ return displayValue(vars[key]);
241
+ });
242
+ }
243
+ /**
244
+ * Make invisible test data VISIBLE instead of losing it (review GAP-04):
245
+ * '' → (empty) · whitespace-only → (N spaces) · padded → quoted verbatim.
246
+ * The canonical value is never changed — only its presentation.
247
+ */
248
+ function displayValue(v) {
249
+ if (v === '')
250
+ return '(empty)';
251
+ if (/^\s+$/.test(v))
252
+ return `(${v.length} space${v.length > 1 ? 's' : ''})`;
253
+ if (v !== v.trim())
254
+ return `"${v}"`;
255
+ return v;
256
+ }
257
+ function sentenceOf(text) {
258
+ const s = text.trim();
259
+ if (!s)
260
+ return s;
261
+ const cap = s.charAt(0).toUpperCase() + s.slice(1);
262
+ return /[.!?…]$/.test(cap) ? cap : `${cap}.`;
263
+ }
264
+ /**
265
+ * Requirement inventory ∪ traces → coverage table. Ids are scanned from the spec
266
+ * text (FR-/TR-/NFR-<n>); map overrides win over the derived covered/gap status.
267
+ */
268
+ function computeRequirements(specText, map, items) {
269
+ const ids = [];
270
+ const seen = new Set();
271
+ const add = (id) => { if (!seen.has(id)) {
272
+ seen.add(id);
273
+ ids.push(id);
274
+ } };
275
+ // A spec declares its requirements in bold — `- **FR-001**: …`, `- **REQ-12**: …`.
276
+ // Reading the DECLARATION (rather than any `PREFIX-123` token in the prose) keeps
277
+ // a project's own scheme working without matching ISO numbers, dates, or the form
278
+ // number in a header.
279
+ for (const m of specText.matchAll(/\*\*([A-Z][A-Z0-9]{1,7}-\d+)\*\*/g))
280
+ add(m[1]);
281
+ // Specs that do not bold their ids still work for the conventional prefixes.
282
+ if (ids.length === 0) {
283
+ for (const m of specText.matchAll(/\b(?:FR|TR|NFR)-\d+\b/g))
284
+ add(m[0]);
285
+ }
286
+ // Overrides may reference ids the spec text doesn't list (e.g. a shared catalog).
287
+ for (const id of Object.keys(map.requirements ?? {})) {
288
+ if (!seen.has(id)) {
289
+ seen.add(id);
290
+ ids.push(id);
291
+ }
292
+ }
293
+ if (ids.length === 0)
294
+ return [];
295
+ return ids.map((id) => {
296
+ const traced = items.filter((it) => it.variants.some((v) => v.traces.includes(id)));
297
+ const override = (map.requirements ?? {})[id];
298
+ return {
299
+ id,
300
+ status: override?.status ?? (traced.length > 0 ? 'covered' : 'gap'),
301
+ items: traced.map((it) => it.id),
302
+ variantCount: traced.reduce((a, it) => a + it.variants.filter((v) => v.traces.includes(id)).length, 0),
303
+ note: override?.note ?? '',
304
+ };
305
+ });
306
+ }
307
+ /** Resolve one level of {{key}} cross-references inside test-data VALUES. */
308
+ function resolveCrossRefs(testData) {
309
+ if (!testData)
310
+ return null;
311
+ const out = {};
312
+ for (const [k, v] of Object.entries(testData)) {
313
+ out[k] = typeof v === 'string' && v.includes('{{') ? substituteDisplayVars(v, testData) : v;
314
+ }
315
+ return out;
316
+ }
317
+ function rowAsStrings(row) {
318
+ const out = {};
319
+ for (const [k, v] of Object.entries(row)) {
320
+ out[k] = String(v);
321
+ out[`row.${k}`] = String(v); // steps reference dataset columns as {{row.<col>}}
322
+ }
323
+ return out;
324
+ }
325
+ // ---------------------------------------------------------------------------
326
+ // Item assembly + roll-up
327
+ // ---------------------------------------------------------------------------
328
+ /**
329
+ * The exact word rendered in a variant's Result cell. This is the SINGLE
330
+ * vocabulary both the renderers and the parent's COUNTIF roll-up use — the
331
+ * legacy exporter's statusToTestResult disagreed on two statuses (`skipped`
332
+ * showed N/A but counted as not-run; `interrupted` showed Pending but counted
333
+ * as blocked), which silently skewed the derived parent result.
334
+ */
335
+ function variantState(v) {
336
+ const r = v.result;
337
+ if (!r)
338
+ return 'Pending';
339
+ switch (r.status) {
340
+ case 'passed': return 'Passed';
341
+ case 'failed':
342
+ case 'timedOut': return 'Failed';
343
+ case 'interrupted': return 'Blocked';
344
+ case 'skipped': return 'N/A';
345
+ default: return 'Pending';
346
+ }
347
+ }
348
+ const STATE_TO_COUNT = {
349
+ Passed: 'passed', Failed: 'failed', Blocked: 'blocked', Pending: 'notRun', 'N/A': 'na',
350
+ };
351
+ /**
352
+ * Derived parent result — precedence failed → blocked → all-N/A → not_run →
353
+ * partial → passed. `N/A` variants leave the denominator (an intentionally
354
+ * skipped case must not make the parent look incomplete).
355
+ */
356
+ function rollUp(variants) {
357
+ const counts = { passed: 0, failed: 0, blocked: 0, notRun: 0, na: 0 };
358
+ for (const v of variants)
359
+ counts[STATE_TO_COUNT[variantState(v)]]++;
360
+ const effective = variants.length - counts.na;
361
+ let result;
362
+ if (counts.failed > 0)
363
+ result = 'failed';
364
+ else if (counts.blocked > 0)
365
+ result = 'blocked';
366
+ else if (effective === 0)
367
+ result = 'na';
368
+ else if (counts.passed === 0)
369
+ result = 'not_run';
370
+ else if (counts.passed === effective)
371
+ result = 'passed';
372
+ else
373
+ result = 'partial';
374
+ return { result, counts };
375
+ }
376
+ /** Longest shared leading run of steps — hoisted onto the parent row. */
377
+ function commonPrefix(lists) {
378
+ if (lists.length === 0)
379
+ return 0;
380
+ let n = 0;
381
+ while (lists.every((l) => l.length > n) && new Set(lists.map((l) => l[n])).size === 1)
382
+ n++;
383
+ return n;
384
+ }
385
+ /**
386
+ * Expand one map variant ref to concrete variant refs:
387
+ * a bare VP-id whose scenario has a dataset means ALL its rows.
388
+ */
389
+ function expandMapRef(ref, variantsByVp) {
390
+ if (ref.includes('#')) {
391
+ const [vp] = ref.split('#');
392
+ return (variantsByVp.get(vp) ?? []).filter((v) => v.ref === ref);
393
+ }
394
+ return variantsByVp.get(ref) ?? [];
395
+ }
396
+ function buildMatrix(inputs) {
397
+ const { unit, map, transformerVersion } = inputs;
398
+ const variants = deriveVariants(inputs);
399
+ const variantsByVp = new Map();
400
+ for (const v of variants) {
401
+ const list = variantsByVp.get(v.vpId) ?? [];
402
+ list.push(v);
403
+ variantsByVp.set(v.vpId, list);
404
+ }
405
+ const findings = (0, gates_1.runGates)({ inputs, variants, variantsByVp });
406
+ const stale = new Set(findings.filter((f) => f.gate === 'E' && f.ref).map((f) => f.ref));
407
+ const items = map.groups.map((g) => {
408
+ const groupVariants = g.variants.flatMap((ref) => expandMapRef(ref, variantsByVp));
409
+ const { result, counts } = rollUp(groupVariants);
410
+ const first = groupVariants[0];
411
+ const modes = new Set(groupVariants.map((v) => v.mode));
412
+ const commonPre = (first?.precondition ?? []).filter((line) => groupVariants.every((v) => v.precondition.includes(line)));
413
+ // Steps every variant starts with belong on the parent once; each variant
414
+ // renders only its remaining steps (review: the shared prefix was repeated
415
+ // on every child while the parent cell sat empty).
416
+ const prefixLen = commonPrefix(groupVariants.map((v) => v.trigger));
417
+ // Item priority = highest variant priority (per-variant priorities stay visible).
418
+ const priorityRank = { High: 0, Normal: 1, Low: 2 };
419
+ const priority = groupVariants
420
+ .map((v) => v.priority)
421
+ .sort((a, b) => (priorityRank[a] ?? 1) - (priorityRank[b] ?? 1))[0] ?? 'Normal';
422
+ return {
423
+ id: g.id,
424
+ target: g.target,
425
+ intent: g.intent,
426
+ oracle: g.oracle,
427
+ category: g.category,
428
+ // A stale (drifted) group presents as proposed regardless of its stored state.
429
+ review: stale.has(g.id) ? 'proposed' : g.review,
430
+ priority,
431
+ mode: modes.size > 1 ? 'mixed' : (first?.mode ?? 'auto'),
432
+ layers: Array.from(new Set(groupVariants.flatMap((v) => v.layers))),
433
+ traces: Array.from(new Set(groupVariants.flatMap((v) => v.traces))),
434
+ dimensions: g.dimensions,
435
+ // Only the preconditions COMMON to every variant belong on the parent —
436
+ // copying the first variant's setup mis-states the start state of the
437
+ // others (review GAP-03). Variant-specific lines render as the sub-row's
438
+ // precondition delta.
439
+ precondition: commonPre,
440
+ preconditionDeltas: Object.fromEntries(groupVariants.map((v) => [v.ref, v.precondition.filter((line) => !commonPre.includes(line))])),
441
+ triggerDeltas: Object.fromEntries(groupVariants.map((v) => [v.ref, v.trigger.slice(prefixLen)])),
442
+ trigger: (first?.trigger ?? []).slice(0, prefixLen),
443
+ variants: groupVariants,
444
+ result,
445
+ resultCounts: counts,
446
+ };
447
+ });
448
+ const dispositions = Object.entries(map.dispositions).map(([vpId, d]) => ({
449
+ vpId,
450
+ title: variantsByVp.get(vpId)?.[0]?.title ?? '',
451
+ as: d.as,
452
+ reason: d.reason ?? '',
453
+ }));
454
+ // Requirement coverage (review §6): the requirement-id inventory comes from
455
+ // requirements/spec.md; @spec: traces mark `covered`; the map's `requirements:`
456
+ // section carries the reviewed overrides (partially_covered / not_applicable / …).
457
+ const requirements = computeRequirements(inputs.specText ?? '', map, items);
458
+ const gaps = requirements.filter((r) => r.status === 'gap');
459
+ if (gaps.length > 0) {
460
+ findings.push({
461
+ gate: 'R', severity: 'warning',
462
+ message: `${gaps.length} requirement id(s) with no coverage or disposition: ${gaps.map((g) => g.id).join(', ')} — trace them, or record a status in the map \`requirements:\` section`,
463
+ });
464
+ }
465
+ // A `covered` claim with no traced variant is prose, not traceability: nothing
466
+ // detects it when the proving scenario is later changed or deleted. Either tag
467
+ // the scenario that proves it (`@spec:<id>`) or say where it IS covered.
468
+ const unbacked = requirements.filter((r) => r.status === 'covered' && r.items.length === 0);
469
+ if (unbacked.length > 0) {
470
+ findings.push({
471
+ gate: 'R', severity: 'warning',
472
+ message: `${unbacked.length} requirement id(s) declared \`covered\` with no variant tracing to them: ${unbacked.map((r) => r.id).join(', ')} — add \`@spec:<id>\` to the scenario that proves each, or use covered_elsewhere / partially_covered with a named reference`,
473
+ });
474
+ }
475
+ const variantCount = items.reduce((a, i) => a + i.variants.length, 0);
476
+ const approved = items.every((i) => i.review === 'approved')
477
+ && !findings.some((f) => f.severity === 'error' || f.severity === 'review');
478
+ return {
479
+ unit,
480
+ formNo: map.formNo ?? 'BM-2-901-13',
481
+ items,
482
+ dispositions,
483
+ requirements,
484
+ findings,
485
+ manifest: {
486
+ unit,
487
+ transformerVersion,
488
+ sourceFingerprint: (0, fingerprint_1.combinedFingerprint)(variants.map((v) => v.fingerprint)),
489
+ mapFingerprint: (0, fingerprint_1.mapContentFingerprint)(map.groups, map.dispositions),
490
+ approvalState: approved ? 'approved' : 'draft',
491
+ itemCount: items.length,
492
+ variantCount,
493
+ thresholds: { maxVariantsPerItem: types_1.MAX_VARIANTS_PER_ITEM },
494
+ },
495
+ };
496
+ }
497
+ //# sourceMappingURL=build.js.map