@sun-asterisk/sungen 3.2.15 → 3.2.16-beta.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 (84) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +138 -1
  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.js +1 -1
  6. package/dist/exporters/feature-parser.js.map +1 -1
  7. package/dist/exporters/matrix/build.d.ts +36 -0
  8. package/dist/exporters/matrix/build.d.ts.map +1 -0
  9. package/dist/exporters/matrix/build.js +267 -0
  10. package/dist/exporters/matrix/build.js.map +1 -0
  11. package/dist/exporters/matrix/export.d.ts +47 -0
  12. package/dist/exporters/matrix/export.d.ts.map +1 -0
  13. package/dist/exporters/matrix/export.js +136 -0
  14. package/dist/exporters/matrix/export.js.map +1 -0
  15. package/dist/exporters/matrix/fingerprint.d.ts +20 -0
  16. package/dist/exporters/matrix/fingerprint.d.ts.map +1 -0
  17. package/dist/exporters/matrix/fingerprint.js +83 -0
  18. package/dist/exporters/matrix/fingerprint.js.map +1 -0
  19. package/dist/exporters/matrix/gates.d.ts +21 -0
  20. package/dist/exporters/matrix/gates.d.ts.map +1 -0
  21. package/dist/exporters/matrix/gates.js +258 -0
  22. package/dist/exporters/matrix/gates.js.map +1 -0
  23. package/dist/exporters/matrix/map-loader.d.ts +22 -0
  24. package/dist/exporters/matrix/map-loader.d.ts.map +1 -0
  25. package/dist/exporters/matrix/map-loader.js +173 -0
  26. package/dist/exporters/matrix/map-loader.js.map +1 -0
  27. package/dist/exporters/matrix/render-csv.d.ts +8 -0
  28. package/dist/exporters/matrix/render-csv.d.ts.map +1 -0
  29. package/dist/exporters/matrix/render-csv.js +69 -0
  30. package/dist/exporters/matrix/render-csv.js.map +1 -0
  31. package/dist/exporters/matrix/render-xlsx.d.ts +17 -0
  32. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -0
  33. package/dist/exporters/matrix/render-xlsx.js +298 -0
  34. package/dist/exporters/matrix/render-xlsx.js.map +1 -0
  35. package/dist/exporters/matrix/types.d.ts +153 -0
  36. package/dist/exporters/matrix/types.d.ts.map +1 -0
  37. package/dist/exporters/matrix/types.js +15 -0
  38. package/dist/exporters/matrix/types.js.map +1 -0
  39. package/dist/exporters/scenario-merger.js +1 -1
  40. package/dist/exporters/scenario-merger.js.map +1 -1
  41. package/dist/exporters/spec-parser.js +1 -1
  42. package/dist/exporters/spec-parser.js.map +1 -1
  43. package/dist/exporters/xlsx-report-builder.d.ts +1 -1
  44. package/dist/exporters/xlsx-report-builder.d.ts.map +1 -1
  45. package/dist/exporters/xlsx-report-builder.js +3 -3
  46. package/dist/exporters/xlsx-report-builder.js.map +1 -1
  47. package/dist/harness/audit.d.ts.map +1 -1
  48. package/dist/harness/audit.js +6 -1
  49. package/dist/harness/audit.js.map +1 -1
  50. package/dist/harness/capability.d.ts +25 -0
  51. package/dist/harness/capability.d.ts.map +1 -1
  52. package/dist/harness/capability.js +44 -2
  53. package/dist/harness/capability.js.map +1 -1
  54. package/dist/orchestrator/templates/ai-src/commands/create-test.md +1 -1
  55. package/dist/orchestrator/templates/ai-src/commands/delivery.md +118 -120
  56. package/dist/orchestrator/templates/ai-src/config/claude.md +1 -1
  57. package/dist/orchestrator/templates/ai-src/config/copilot.md +1 -1
  58. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +36 -6
  59. package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +1 -1
  60. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +1 -0
  61. package/package.json +4 -4
  62. package/src/cli/commands/delivery.ts +168 -2
  63. package/src/dashboard/templates/index.html +1 -1
  64. package/src/exporters/feature-parser.ts +1 -1
  65. package/src/exporters/matrix/build.ts +294 -0
  66. package/src/exporters/matrix/export.ts +124 -0
  67. package/src/exporters/matrix/fingerprint.ts +49 -0
  68. package/src/exporters/matrix/gates.ts +284 -0
  69. package/src/exporters/matrix/map-loader.ts +142 -0
  70. package/src/exporters/matrix/render-csv.ts +71 -0
  71. package/src/exporters/matrix/render-xlsx.ts +289 -0
  72. package/src/exporters/matrix/types.ts +176 -0
  73. package/src/exporters/scenario-merger.ts +1 -1
  74. package/src/exporters/spec-parser.ts +1 -1
  75. package/src/exporters/xlsx-report-builder.ts +3 -2
  76. package/src/harness/audit.ts +7 -2
  77. package/src/harness/capability.ts +53 -3
  78. package/src/orchestrator/templates/ai-src/commands/create-test.md +1 -1
  79. package/src/orchestrator/templates/ai-src/commands/delivery.md +118 -120
  80. package/src/orchestrator/templates/ai-src/config/claude.md +1 -1
  81. package/src/orchestrator/templates/ai-src/config/copilot.md +1 -1
  82. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +36 -6
  83. package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +1 -1
  84. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +1 -0
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ /**
3
+ * Deterministic quality gates for the Test Case & Coverage Matrix
4
+ * (docs/spec/delivery-coverage-matrix-spec.md §6).
5
+ *
6
+ * Severity behavior:
7
+ * error → blocks any render
8
+ * review → blocks the official render; `--preview` renders with a DRAFT watermark
9
+ * warning → prints + renders
10
+ *
11
+ * The gates recompute every signature part from the .feature — the map is never
12
+ * trusted for derivable facts, only for the semantic fields (target/intent/oracle).
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.runGates = runGates;
16
+ const feature_parser_1 = require("../feature-parser");
17
+ const types_1 = require("./types");
18
+ const build_1 = require("./build");
19
+ function runGates(ctx) {
20
+ const findings = [];
21
+ gateASource(ctx, findings);
22
+ gateBMapping(ctx, findings);
23
+ gateCAggregation(ctx, findings);
24
+ gateDExecutability(ctx, findings);
25
+ gateEDrift(ctx, findings);
26
+ gateGReviewState(ctx, findings);
27
+ return findings;
28
+ }
29
+ // --- Gate A — source quality ------------------------------------------------
30
+ function gateASource(ctx, findings) {
31
+ const { feature, merged } = ctx.inputs;
32
+ if (feature.backgroundWhenSteps.length > 0 || feature.backgroundThenSteps.length > 0) {
33
+ findings.push({
34
+ gate: 'A', severity: 'error',
35
+ message: 'Background contains When/Then steps — setup only; move the action/oracle into scenarios',
36
+ });
37
+ }
38
+ const seen = new Map();
39
+ for (const m of merged) {
40
+ const { vpId } = (0, feature_parser_1.splitVpAndName)(m.feature.name);
41
+ if (!vpId) {
42
+ findings.push({
43
+ gate: 'A', severity: 'error', ref: m.feature.name,
44
+ message: `scenario "${m.feature.name}" has no VP-id prefix — matrix variants must be addressable`,
45
+ });
46
+ continue;
47
+ }
48
+ seen.set(vpId, (seen.get(vpId) ?? 0) + 1);
49
+ const isManual = (0, feature_parser_1.extractTestcaseType)(m.feature.tags) === 'Manual';
50
+ if (m.resolvedExpected.length === 0) {
51
+ findings.push({
52
+ gate: 'A', severity: 'error', ref: vpId,
53
+ message: isManual
54
+ ? `manual scenario ${vpId} has no observable oracle (no Then steps and no Observable/Oracle comment lines)`
55
+ : `scenario ${vpId} has no Then step — a variant without an observable oracle cannot be delivered`,
56
+ });
57
+ }
58
+ }
59
+ for (const [vpId, n] of seen) {
60
+ if (n > 1)
61
+ findings.push({ gate: 'A', severity: 'error', ref: vpId, message: `duplicate VP-id ${vpId} (${n} scenarios)` });
62
+ }
63
+ }
64
+ // --- Gate B — mapping completeness -------------------------------------------
65
+ function gateBMapping(ctx, findings) {
66
+ const { map } = ctx.inputs;
67
+ const { variants, variantsByVp } = ctx;
68
+ // Where each derived variant landed: 0 → unmapped, >1 → double-mapped.
69
+ const owners = new Map();
70
+ for (const g of map.groups) {
71
+ for (const ref of g.variants) {
72
+ const expanded = (0, build_1.expandMapRef)(ref, variantsByVp);
73
+ if (expanded.length === 0) {
74
+ findings.push({
75
+ gate: 'B', severity: 'error', ref: g.id,
76
+ message: `group ${g.id} references ${ref} which matches no scenario/@cases row in the .feature`,
77
+ });
78
+ continue;
79
+ }
80
+ for (const v of expanded) {
81
+ const list = owners.get(v.ref) ?? [];
82
+ list.push(g.id);
83
+ owners.set(v.ref, list);
84
+ }
85
+ }
86
+ }
87
+ for (const [ref, groups] of owners) {
88
+ if (groups.length > 1) {
89
+ findings.push({
90
+ gate: 'B', severity: 'error', ref,
91
+ message: `variant ${ref} belongs to ${groups.length} groups (${groups.join(', ')}) — exactly one required`,
92
+ });
93
+ }
94
+ }
95
+ for (const v of variants) {
96
+ const grouped = owners.has(v.ref);
97
+ const disposed = v.vpId in map.dispositions;
98
+ if (!grouped && !disposed) {
99
+ findings.push({
100
+ gate: 'B', severity: 'error', ref: v.ref,
101
+ message: `variant ${v.ref} is in no group and has no disposition — 100% source disposition is required`,
102
+ });
103
+ }
104
+ if (grouped && disposed) {
105
+ findings.push({
106
+ gate: 'B', severity: 'error', ref: v.ref,
107
+ message: `variant ${v.ref} is grouped AND disposed (${map.dispositions[v.vpId].as}) — pick one`,
108
+ });
109
+ }
110
+ }
111
+ for (const vpId of Object.keys(map.dispositions)) {
112
+ if (!variantsByVp.has(vpId)) {
113
+ findings.push({
114
+ gate: 'B', severity: 'warning', ref: vpId,
115
+ message: `disposition for ${vpId} matches no scenario (stale entry?)`,
116
+ });
117
+ }
118
+ }
119
+ }
120
+ // --- Gate C — aggregation safety ---------------------------------------------
121
+ function gateCAggregation(ctx, findings) {
122
+ const { map } = ctx.inputs;
123
+ const { variantsByVp } = ctx;
124
+ for (const g of map.groups) {
125
+ const vs = g.variants.flatMap((ref) => (0, build_1.expandMapRef)(ref, variantsByVp));
126
+ if (vs.length <= 1)
127
+ continue;
128
+ // Approval IS the QA confirmation of the heuristic parts (oracle family,
129
+ // precondition equivalence, sequence safety) — once approved AND unchanged
130
+ // (fingerprints intact), only the hard signature checks keep firing. A
131
+ // drifted variant re-opens the heuristics (Gate E flips the item to
132
+ // proposed at the same time).
133
+ const stale = vs.some((v) => {
134
+ const stamped = map.fingerprints[v.ref] ?? map.fingerprints[v.vpId];
135
+ return !stamped || stamped !== v.fingerprint;
136
+ });
137
+ const heuristicsConfirmed = g.review === 'approved' && !stale;
138
+ // Hard signature parts — recomputed, never trusted from the map. ERROR on mismatch.
139
+ const hard = [
140
+ ['execution mode', (v) => v.mode],
141
+ ['test layer', (v) => [...v.layers].sort().join('+')],
142
+ ['priority', (v) => v.priority],
143
+ ];
144
+ for (const [label, keyOf] of hard) {
145
+ const distinct = new Set(vs.map(keyOf));
146
+ if (distinct.size > 1) {
147
+ findings.push({
148
+ gate: 'C', severity: 'error', ref: g.id,
149
+ message: `group ${g.id} mixes ${label}s (${[...distinct].join(' vs ')}) — mandatory split`,
150
+ });
151
+ }
152
+ }
153
+ // Heuristic signature parts — REVIEW_REQUIRED (equivalence was inferred, not declared).
154
+ const preProfiles = new Set(vs.map((v) => v.preconditionProfile));
155
+ if (!heuristicsConfirmed && preProfiles.size > 1) {
156
+ findings.push({
157
+ gate: 'C', severity: 'review', ref: g.id,
158
+ message: `group ${g.id} variants have different precondition profiles — confirm the grouping is safe or split`,
159
+ });
160
+ }
161
+ const oracleShapes = new Set(vs.map((v) => v.oracleShape.join(' ; ')));
162
+ if (!heuristicsConfirmed && oracleShapes.size > 1) {
163
+ findings.push({
164
+ gate: 'C', severity: 'review', ref: g.id,
165
+ message: `group ${g.id} variants assert different oracle shapes (${oracleShapes.size} shapes) — confirm they are one oracle family`,
166
+ });
167
+ }
168
+ if (!heuristicsConfirmed && vs.some((v) => v.procedureProfile === 'sequence')) {
169
+ findings.push({
170
+ gate: 'C', severity: 'review', ref: g.id,
171
+ message: `group ${g.id} contains a sequence-sensitive scenario — ordered flows stay solo items unless QA confirms`,
172
+ });
173
+ }
174
+ if (vs.length > types_1.MAX_VARIANTS_PER_ITEM) {
175
+ findings.push({
176
+ gate: 'C', severity: 'warning', ref: g.id,
177
+ message: `group ${g.id} has ${vs.length} variants (> ${types_1.MAX_VARIANTS_PER_ITEM}) — consider splitting for reviewability`,
178
+ });
179
+ }
180
+ }
181
+ }
182
+ // --- Gate D — manual executability -------------------------------------------
183
+ function gateDExecutability(ctx, findings) {
184
+ const { map, testData, feature } = ctx.inputs;
185
+ const { variantsByVp } = ctx;
186
+ for (const g of map.groups) {
187
+ const vs = g.variants.flatMap((ref) => (0, build_1.expandMapRef)(ref, variantsByVp));
188
+ for (const v of vs) {
189
+ const hasPrecondition = v.precondition.length > 0 || feature.backgroundGivenSteps.length > 0;
190
+ if (!hasPrecondition) {
191
+ findings.push({
192
+ gate: 'D', severity: 'error', ref: v.ref,
193
+ message: `${v.ref}: no precondition (no Background, auth tag, or Given) — a tester cannot establish the start state`,
194
+ });
195
+ }
196
+ if (v.trigger.length === 0) {
197
+ findings.push({
198
+ gate: 'D', severity: 'error', ref: v.ref,
199
+ message: `${v.ref}: no action/trigger (no When steps${v.mode === 'manual' ? ' and no Setup/Action comment lines' : ''})`,
200
+ });
201
+ }
202
+ // Oracle emptiness is Gate A (source) — not repeated here.
203
+ }
204
+ }
205
+ // Every {{var}} must resolve — data the tester cannot obtain is not executable.
206
+ for (const [vpId, vs] of variantsByVp) {
207
+ const scenario = ctx.inputs.merged.find((m) => (0, feature_parser_1.splitVpAndName)(m.feature.name).vpId === vpId);
208
+ if (!scenario)
209
+ continue;
210
+ for (const varName of scenario.feature.referencedVars) {
211
+ const inRows = vs.some((v) => v.caseLabel !== undefined); // dataset rows carry their own columns
212
+ if (!inRows && (!testData || !(varName in testData))) {
213
+ findings.push({
214
+ gate: 'D', severity: 'error', ref: vpId,
215
+ message: `${vpId}: {{${varName}}} does not resolve in test-data — the variant is not reproducible`,
216
+ });
217
+ }
218
+ }
219
+ }
220
+ }
221
+ // --- Gate E — drift (stale approval) ------------------------------------------
222
+ function gateEDrift(ctx, findings) {
223
+ const { map } = ctx.inputs;
224
+ const { variantsByVp } = ctx;
225
+ for (const g of map.groups) {
226
+ if (g.review !== 'approved')
227
+ continue; // proposed groups are already under review
228
+ for (const ref of g.variants) {
229
+ const vs = (0, build_1.expandMapRef)(ref, variantsByVp);
230
+ for (const v of vs) {
231
+ const stamped = map.fingerprints[v.ref] ?? map.fingerprints[v.vpId];
232
+ if (!stamped) {
233
+ findings.push({
234
+ gate: 'E', severity: 'review', ref: g.id,
235
+ message: `group ${g.id}: ${v.ref} has no stamped fingerprint — run \`sungen delivery --approve\` after review`,
236
+ });
237
+ }
238
+ else if (stamped !== v.fingerprint) {
239
+ findings.push({
240
+ gate: 'E', severity: 'review', ref: g.id,
241
+ message: `group ${g.id}: ${v.ref} changed since approval (fingerprint drift) — re-review the grouping`,
242
+ });
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+ // --- Gate G — review state -----------------------------------------------------
249
+ function gateGReviewState(ctx, findings) {
250
+ const proposed = ctx.inputs.map.groups.filter((g) => g.review !== 'approved');
251
+ if (proposed.length > 0) {
252
+ findings.push({
253
+ gate: 'G', severity: 'review',
254
+ message: `${proposed.length} group(s) still \`proposed\` (${proposed.slice(0, 5).map((g) => g.id).join(', ')}${proposed.length > 5 ? ', …' : ''}) — approve them or render with --preview`,
255
+ });
256
+ }
257
+ }
258
+ //# sourceMappingURL=gates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../../src/exporters/matrix/gates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Delivery Map loader — `qa/<kind>/<unit>/delivery/<unit>.map.yaml`.
3
+ *
4
+ * Structural validation only (shape, required fields, enum values, duplicate ids).
5
+ * Semantic validation against the .feature is the gates' job (gates.ts) — the loader
6
+ * never reads the feature.
7
+ */
8
+ import { DeliveryMap } from './types';
9
+ export interface MapLoadResult {
10
+ map: DeliveryMap | null;
11
+ /** Structural problems — any entry blocks the matrix path (fix the file first). */
12
+ errors: string[];
13
+ }
14
+ /** Path of the map file for a unit directory (qa/<kind>/<screen>) + feature basename. */
15
+ export declare function mapFilePath(unitDir: string, featureBaseName: string): string;
16
+ export declare function loadDeliveryMap(file: string): MapLoadResult;
17
+ /**
18
+ * Write the map back (used by `--approve` to flip review states + stamp fingerprints).
19
+ * Field order is kept stable so approve-diffs stay minimal and reviewable.
20
+ */
21
+ export declare function writeDeliveryMap(file: string, map: DeliveryMap): void;
22
+ //# sourceMappingURL=map-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-loader.d.ts","sourceRoot":"","sources":["../../../src/exporters/matrix/map-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,WAAW,EAAsD,MAAM,SAAS,CAAC;AAM1F,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACxB,mFAAmF;IACnF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAwF3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAmBrE"}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ /**
3
+ * Delivery Map loader — `qa/<kind>/<unit>/delivery/<unit>.map.yaml`.
4
+ *
5
+ * Structural validation only (shape, required fields, enum values, duplicate ids).
6
+ * Semantic validation against the .feature is the gates' job (gates.ts) — the loader
7
+ * never reads the feature.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.mapFilePath = mapFilePath;
44
+ exports.loadDeliveryMap = loadDeliveryMap;
45
+ exports.writeDeliveryMap = writeDeliveryMap;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const yaml_1 = require("yaml");
49
+ const CATEGORIES = ['normal', 'abnormal', 'security', 'nfr'];
50
+ const REVIEW_STATES = ['proposed', 'approved'];
51
+ const DISPOSITIONS = ['excluded', 'blocked', 'covered_elsewhere', 'accepted_risk'];
52
+ /** Path of the map file for a unit directory (qa/<kind>/<screen>) + feature basename. */
53
+ function mapFilePath(unitDir, featureBaseName) {
54
+ return path.join(unitDir, 'delivery', `${featureBaseName}.map.yaml`);
55
+ }
56
+ function loadDeliveryMap(file) {
57
+ if (!fs.existsSync(file))
58
+ return { map: null, errors: [] };
59
+ const errors = [];
60
+ let raw;
61
+ try {
62
+ raw = (0, yaml_1.parse)(fs.readFileSync(file, 'utf-8'));
63
+ }
64
+ catch (e) {
65
+ return { map: null, errors: [`map YAML does not parse: ${e instanceof Error ? e.message : e}`] };
66
+ }
67
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
68
+ return { map: null, errors: ['map root must be a YAML mapping'] };
69
+ }
70
+ const doc = raw;
71
+ const groups = [];
72
+ const seenIds = new Set();
73
+ const rawGroups = doc.groups;
74
+ if (!Array.isArray(rawGroups) || rawGroups.length === 0) {
75
+ errors.push('map has no `groups` list');
76
+ }
77
+ else {
78
+ rawGroups.forEach((g, i) => {
79
+ if (!g || typeof g !== 'object') {
80
+ errors.push(`groups[${i}] is not a mapping`);
81
+ return;
82
+ }
83
+ const grp = g;
84
+ const where = `groups[${i}]${typeof grp.id === 'string' ? ` (${grp.id})` : ''}`;
85
+ for (const field of ['id', 'target', 'intent', 'oracle']) {
86
+ if (typeof grp[field] !== 'string' || !grp[field].trim()) {
87
+ errors.push(`${where}: missing/empty \`${field}\``);
88
+ }
89
+ }
90
+ if (!CATEGORIES.includes(grp.category)) {
91
+ errors.push(`${where}: \`category\` must be one of ${CATEGORIES.join(' | ')}`);
92
+ }
93
+ const review = (grp.review ?? 'proposed');
94
+ if (!REVIEW_STATES.includes(review)) {
95
+ errors.push(`${where}: \`review\` must be proposed | approved`);
96
+ }
97
+ const variants = grp.variants;
98
+ if (!Array.isArray(variants) || variants.length === 0 || variants.some((v) => typeof v !== 'string' || !v.trim())) {
99
+ errors.push(`${where}: \`variants\` must be a non-empty list of VP refs`);
100
+ }
101
+ const id = String(grp.id ?? '');
102
+ if (id) {
103
+ if (seenIds.has(id))
104
+ errors.push(`duplicate group id \`${id}\``);
105
+ seenIds.add(id);
106
+ }
107
+ groups.push({
108
+ id,
109
+ target: String(grp.target ?? ''),
110
+ intent: String(grp.intent ?? ''),
111
+ oracle: String(grp.oracle ?? ''),
112
+ category: grp.category,
113
+ review,
114
+ variants: Array.isArray(variants) ? variants.map(String) : [],
115
+ });
116
+ });
117
+ }
118
+ const dispositions = {};
119
+ if (doc.dispositions !== undefined) {
120
+ if (!doc.dispositions || typeof doc.dispositions !== 'object' || Array.isArray(doc.dispositions)) {
121
+ errors.push('`dispositions` must be a mapping of VP-id → { as, reason }');
122
+ }
123
+ else {
124
+ for (const [vpId, d] of Object.entries(doc.dispositions)) {
125
+ const dd = (d && typeof d === 'object' ? d : {});
126
+ if (!DISPOSITIONS.includes(String(dd.as))) {
127
+ errors.push(`dispositions.${vpId}: \`as\` must be one of ${DISPOSITIONS.join(' | ')}`);
128
+ }
129
+ dispositions[vpId] = { as: dd.as, reason: dd.reason ? String(dd.reason) : undefined };
130
+ }
131
+ }
132
+ }
133
+ const fingerprints = {};
134
+ if (doc.fingerprints && typeof doc.fingerprints === 'object' && !Array.isArray(doc.fingerprints)) {
135
+ for (const [k, v] of Object.entries(doc.fingerprints)) {
136
+ fingerprints[k] = String(v);
137
+ }
138
+ }
139
+ const map = {
140
+ version: Number(doc.version ?? 1),
141
+ unit: String(doc.unit ?? ''),
142
+ formNo: doc.form_no !== undefined ? String(doc.form_no) : undefined,
143
+ groups,
144
+ dispositions,
145
+ fingerprints,
146
+ };
147
+ return { map: errors.length > 0 ? null : map, errors };
148
+ }
149
+ /**
150
+ * Write the map back (used by `--approve` to flip review states + stamp fingerprints).
151
+ * Field order is kept stable so approve-diffs stay minimal and reviewable.
152
+ */
153
+ function writeDeliveryMap(file, map) {
154
+ const doc = {
155
+ version: map.version,
156
+ unit: map.unit,
157
+ ...(map.formNo !== undefined ? { form_no: map.formNo } : {}),
158
+ groups: map.groups.map((g) => ({
159
+ id: g.id,
160
+ target: g.target,
161
+ intent: g.intent,
162
+ oracle: g.oracle,
163
+ category: g.category,
164
+ review: g.review,
165
+ variants: g.variants,
166
+ })),
167
+ ...(Object.keys(map.dispositions).length > 0 ? { dispositions: map.dispositions } : {}),
168
+ ...(Object.keys(map.fingerprints).length > 0 ? { fingerprints: map.fingerprints } : {}),
169
+ };
170
+ fs.mkdirSync(path.dirname(file), { recursive: true });
171
+ fs.writeFileSync(file, (0, yaml_1.stringify)(doc, { lineWidth: 0 }), 'utf-8');
172
+ }
173
+ //# sourceMappingURL=map-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-loader.js","sourceRoot":"","sources":["../../../src/exporters/matrix/map-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Flat CSV rendering of the matrix — same model as the workbook, one row per
3
+ * delivery item (`Level: item`) followed by its variant rows (`Level: variant`),
4
+ * so downstream pipelines can re-derive both views from one file.
5
+ */
6
+ import { MatrixModel } from './types';
7
+ export declare function renderMatrixCsv(model: MatrixModel): string;
8
+ //# sourceMappingURL=render-csv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-csv.d.ts","sourceRoot":"","sources":["../../../src/exporters/matrix/render-csv.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAatC,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAkD1D"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Flat CSV rendering of the matrix — same model as the workbook, one row per
4
+ * delivery item (`Level: item`) followed by its variant rows (`Level: variant`),
5
+ * so downstream pipelines can re-derive both views from one file.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.renderMatrixCsv = renderMatrixCsv;
9
+ const playwright_report_parser_1 = require("../playwright-report-parser");
10
+ const HEADERS = [
11
+ 'Level', 'ID', 'Target', 'Test Intent / Condition', 'Category', 'Priority',
12
+ 'Precondition', 'Coverage / Test Data', 'Action / Trigger', 'Expected (Oracle)',
13
+ 'Mode', 'Trace', 'Result', 'Executed Date', 'Note',
14
+ ];
15
+ function esc(value) {
16
+ if (/[",\n]/.test(value))
17
+ return `"${value.replace(/"/g, '""')}"`;
18
+ return value;
19
+ }
20
+ function renderMatrixCsv(model) {
21
+ const BOM = '\ufeff'; // Excel compatibility (Vietnamese/Japanese content)
22
+ const lines = [];
23
+ lines.push(`# Test Case & Coverage Matrix — ${model.unit}`);
24
+ lines.push(`# delivery items: ${model.manifest.itemCount} · coverage variants: ${model.manifest.variantCount} · state: ${model.manifest.approvalState}`);
25
+ lines.push(HEADERS.map(esc).join(','));
26
+ for (const item of model.items) {
27
+ const single = item.variants.length === 1;
28
+ const only = single ? item.variants[0] : undefined;
29
+ lines.push([
30
+ 'item',
31
+ item.id,
32
+ item.target,
33
+ item.intent,
34
+ item.category,
35
+ item.priority,
36
+ item.precondition.join('\n'),
37
+ single ? only.data.join('\n') : `${item.variants.length} variants`,
38
+ item.trigger.join('\n'),
39
+ item.oracle,
40
+ item.mode === 'manual' ? 'Manual' : 'Auto',
41
+ item.traces.join(' '),
42
+ item.result,
43
+ single ? (0, playwright_report_parser_1.formatExecutedDate)(only.result?.startTime) : '',
44
+ item.review === 'proposed' ? 'REVIEW REQUIRED' : '',
45
+ ].map(esc).join(','));
46
+ if (!single) {
47
+ for (const v of item.variants) {
48
+ lines.push([
49
+ 'variant',
50
+ v.ref,
51
+ '',
52
+ v.condition,
53
+ '', '',
54
+ '',
55
+ v.data.join('\n'),
56
+ v.trigger.join('\n'),
57
+ v.oracle.join('\n'),
58
+ v.mode === 'manual' ? 'Manual' : 'Auto',
59
+ v.traces.join(' '),
60
+ v.result ? (0, playwright_report_parser_1.statusToTestResult)(v.result.status) : 'Pending',
61
+ (0, playwright_report_parser_1.formatExecutedDate)(v.result?.startTime),
62
+ v.result?.error ? String(v.result.error).slice(0, 200) : '',
63
+ ].map(esc).join(','));
64
+ }
65
+ }
66
+ }
67
+ return BOM + lines.join('\n') + '\n';
68
+ }
69
+ //# sourceMappingURL=render-csv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-csv.js","sourceRoot":"","sources":["../../../src/exporters/matrix/render-csv.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Render the Test Case & Coverage Matrix workbook.
3
+ *
4
+ * Sheets:
5
+ * 1. Testcases — one parent row per delivery item, variant sub-rows grouped with
6
+ * Excel outline (expanded for execution; the level-1 outline button collapses
7
+ * to the customer/review view — same sheet, one model, two views).
8
+ * 2. Coverage — target × category grid (items + variants, `—` marks the gaps),
9
+ * dispositions, and the generation manifest.
10
+ *
11
+ * Every sheet keeps the company ISO masthead (renderReportHeaderBand). A draft
12
+ * matrix (unapproved groups / review findings) carries a red DRAFT banner.
13
+ */
14
+ import * as ExcelJS from 'exceljs';
15
+ import { MatrixModel } from './types';
16
+ export declare function renderMatrixXlsx(model: MatrixModel, sungenVersion?: string): ExcelJS.Workbook;
17
+ //# sourceMappingURL=render-xlsx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-xlsx.d.ts","sourceRoot":"","sources":["../../../src/exporters/matrix/render-xlsx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AASnC,OAAO,EAA6C,WAAW,EAAe,MAAM,SAAS,CAAC;AAoQ9F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAK7F"}