@sun-asterisk/sungen 3.2.16-beta.2 → 3.2.16-beta.4

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 (42) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +16 -5
  3. package/dist/cli/commands/delivery.js.map +1 -1
  4. package/dist/exporters/matrix/build.d.ts +6 -0
  5. package/dist/exporters/matrix/build.d.ts.map +1 -1
  6. package/dist/exporters/matrix/build.js +32 -8
  7. package/dist/exporters/matrix/build.js.map +1 -1
  8. package/dist/exporters/matrix/export.d.ts +5 -4
  9. package/dist/exporters/matrix/export.d.ts.map +1 -1
  10. package/dist/exporters/matrix/export.js +15 -6
  11. package/dist/exporters/matrix/export.js.map +1 -1
  12. package/dist/exporters/matrix/gates.d.ts.map +1 -1
  13. package/dist/exporters/matrix/gates.js +23 -2
  14. package/dist/exporters/matrix/gates.js.map +1 -1
  15. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  16. package/dist/exporters/matrix/render-csv.js +11 -6
  17. package/dist/exporters/matrix/render-csv.js.map +1 -1
  18. package/dist/exporters/matrix/render-xlsx.d.ts +2 -0
  19. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  20. package/dist/exporters/matrix/render-xlsx.js +73 -25
  21. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  22. package/dist/exporters/matrix/types.d.ts +9 -4
  23. package/dist/exporters/matrix/types.d.ts.map +1 -1
  24. package/dist/exporters/matrix/types.js +2 -2
  25. package/dist/exporters/matrix/types.js.map +1 -1
  26. package/dist/exporters/matrix/wording.d.ts +6 -0
  27. package/dist/exporters/matrix/wording.d.ts.map +1 -1
  28. package/dist/exporters/matrix/wording.js +22 -3
  29. package/dist/exporters/matrix/wording.js.map +1 -1
  30. package/dist/orchestrator/templates/ai-src/commands/delivery.md +33 -18
  31. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +30 -11
  32. package/package.json +3 -3
  33. package/src/cli/commands/delivery.ts +19 -6
  34. package/src/exporters/matrix/build.ts +31 -9
  35. package/src/exporters/matrix/export.ts +21 -6
  36. package/src/exporters/matrix/gates.ts +23 -2
  37. package/src/exporters/matrix/render-csv.ts +12 -7
  38. package/src/exporters/matrix/render-xlsx.ts +73 -25
  39. package/src/exporters/matrix/types.ts +9 -4
  40. package/src/exporters/matrix/wording.ts +20 -3
  41. package/src/orchestrator/templates/ai-src/commands/delivery.md +33 -18
  42. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +30 -11
@@ -1 +1 @@
1
- {"version":3,"file":"wording.js","sourceRoot":"","sources":["../../../src/exporters/matrix/wording.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wording.js","sourceRoot":"","sources":["../../../src/exporters/matrix/wording.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: delivery
3
3
  description: "Export the Test Case & Coverage Matrix (review/manual/customer deliverable) from Gherkin + Playwright results. --legacy exports the classic per-scenario CSV/XLSX."
4
- argument-hint: "[name...] [--env <locale>] [--legacy] (omit names for all; --env for locale-specific export)"
4
+ argument-hint: "[name...] [--format csv] [--env <locale>] [--legacy] (omit names for all)"
5
5
  order: 50
6
6
  claude-tools: "Bash, Read, Write, AskUserQuestion"
7
7
  copilot-tools: "[read, execute, edit, vscode/askQuestions]"
@@ -27,6 +27,8 @@ review → approve → official render.
27
27
 
28
28
  Parse from `$ARGUMENTS`:
29
29
  - **names** — zero or more screen/flow/api names. Empty → all targets.
30
+ - **`--format <xlsx|csv|both>`** — output format. **Default `xlsx` — one artifact only.** Pass
31
+ `--format csv` when the user wants the flat CSV (pipelines/diffing), `--format both` for both.
30
32
  - **`--env <locale>`** — sets `SUNGEN_ENV=<locale>` for the run (accept `--locale` as alias).
31
33
  - **`--legacy` / `--full`** — pass through to the CLI and skip the map flow entirely.
32
34
 
@@ -37,8 +39,8 @@ Parse from `$ARGUMENTS`:
37
39
  ```bash
38
40
  [ -x ./bin/sungen.js ] && ./bin/sungen.js delivery <names> || npx sungen delivery <names>
39
41
  ```
40
- (prepend `SUNGEN_ENV=<locale>` when `--env` was given; append `--legacy` when requested then skip
41
- to step 5.)
42
+ (prepend `SUNGEN_ENV=<locale>` when `--env` was given; append `--format <fmt>` when the user asked
43
+ for a non-default format; append `--legacy` when requested — then skip to step 5.)
42
44
 
43
45
  Three outcomes per target:
44
46
  - **Rendered** → done, go to step 5.
@@ -66,18 +68,28 @@ dispositions: # scenarios intentionally NOT delivered as te
66
68
  # as: excluded | blocked | covered_elsewhere | accepted_risk
67
69
  ```
68
70
 
69
- **Grouping rules (the aggregation signature):**
70
- - One group = **one target + one intent + one oracle family**. When unsure, keep items separate —
71
- the gates and QA decide, never guess-merge.
72
- - MAY share a group (become coverage dimensions): equivalence partitions, boundary values,
73
- different data (`@cases` rows), a different trigger with the same oracle (blur vs submit),
74
- locales.
75
- - MUST split: different target, intent, oracle family, category, execution mode (`@manual` vs
76
- auto), test layer (`@api`/`@query`), or priority tag; sequence-sensitive flows (re-Given/When
77
- after a Then) stay solo. **Different risk classes never merge** XSS and SQL injection are
78
- separate items even though both are "injection on the same field" (different risk, action,
79
- and oracle family); a component's visibility rule and its action/revalidation rule are two
80
- intents, not one.
71
+ **Grouping rules (the aggregation signature) — group COMPACTLY.** The matrix exists to be
72
+ substantially shorter than the scenario list, so a reviewer can see missing viewpoints at a
73
+ glance. Merge whenever the cases share ALL of: target · test intent/business rule ·
74
+ precondition/condition · trigger or procedure shape · **the way the expected result is
75
+ determined** (its oracle *family*, not its exact message).
76
+
77
+ - **Oracle family = the determination method, parameterized.** All validation branches of ONE
78
+ field belong to ONE item — required, format, length, character-class are *expected branches*
79
+ (parameters) of "the field shows the validation message defined for the violated rule", shown
80
+ per variant, never separate items.
81
+ - MAY vary inside one item (coverage dimensions, visible on the sub-rows): data values, boundary
82
+ points, **account states** (a seeded/locked/deleted account next to a wrong-password case),
83
+ provider/browser/locale, `@cases` rows, a different trigger with the same oracle (blur vs
84
+ submit), **execution mode** (auto + manual mix — the parent shows `Auto n · Manual m`), and
85
+ **priority** (the item takes the highest; per-variant priorities stay visible).
86
+ - MUST split: different target, different intent/business rule, different way of determining the
87
+ expected result (a field-error family ≠ a session-established family), different test layer
88
+ (`@api`/`@query`), materially different precondition, or a different procedure shape —
89
+ sequence-sensitive flows (re-Given/When after a Then) stay solo. **Different risk classes never
90
+ merge**: XSS and SQL injection are separate items (different risk and determination), even on
91
+ the same field.
92
+ - When unsure, keep items separate — the gates and QA decide, never guess-merge.
81
93
  - Every scenario must land in exactly one group **or** one disposition (Gate B enforces 100%
82
94
  disposition). Data-setup blocks (`@manual:data-setup`) → `excluded`; SPEC-GAP placeholders →
83
95
  `blocked`.
@@ -141,6 +153,7 @@ counted in variants, never items**). Then `AskUserQuestion`:
141
153
  - **Open the workbook** — inspect `qa/deliverables/<unit>-testcases.xlsx` (Testcases sheet:
142
154
  collapse outline level 1 for the customer view; Coverage sheet: target × category grid + gaps).
143
155
  - **Run tests to refresh results** — `/sungen:run-test <unit>`, then re-run delivery.
156
+ - **Also export CSV** — `sungen delivery <unit> --format csv` (flat `item`/`variant` rows for pipelines).
144
157
  - **Export the legacy workbook too** — `sungen delivery <unit> --legacy`.
145
158
  - **Done**
146
159
 
@@ -158,7 +171,8 @@ counted in variants, never items**). Then `AskUserQuestion`:
158
171
  ## CLI reference
159
172
 
160
173
  ```
161
- sungen delivery [names...] # matrix (default; needs the map)
174
+ sungen delivery [names...] # matrix (default; needs the map) → XLSX only
175
+ --format <xlsx|csv|both> # output format; default xlsx (one artifact)
162
176
  --check # gates only — validate the map, write nothing
163
177
  --approve [DI-a,DI-b] # flip proposed→approved (+ stamp fingerprints); all groups when bare
164
178
  --preview # render despite review findings (DRAFT watermark)
@@ -166,5 +180,6 @@ sungen delivery [names...] # matrix (default; needs the map)
166
180
  --skip-preflight | --continue-on-missing | --env <env> # as before
167
181
  ```
168
182
 
169
- Outputs: `qa/deliverables/<unit>-testcases.xlsx` (Testcases + Coverage sheets) + `.csv`
170
- (flat, `Level` column `item|variant`). Legacy mode writes the classic files instead.
183
+ Outputs: `qa/deliverables/<unit>-testcases.xlsx` (Testcases + Coverage sheets) by default;
184
+ `--format csv` writes `<unit>-testcases.csv` instead (flat, `Level` column `item|variant`),
185
+ `--format both` writes both. Legacy mode writes the classic files instead.
@@ -29,12 +29,15 @@ fingerprints). Schema + grouping rules live in the delivery command instructions
29
29
  spec is `docs/spec/delivery-coverage-matrix-spec.md`.
30
30
 
31
31
  **Gates** (CLI `--check`): A source (VP-ids unique, oracle present, Background setup-only) ·
32
- B mapping (every scenario in exactly one group XOR one disposition) · C aggregation (mode/layer/
33
- priority recomputed and equal within a group — heuristic oracle-shape/precondition mismatches are
34
- review-level, silenced once approved and unchanged) · D executability (precondition · condition+
32
+ B mapping (every scenario in exactly one group XOR one disposition) · C aggregation (test layer
33
+ recomputed and equal within a group — **execution mode and priority are coverage dimensions, not
34
+ splits**: mixed items show `Auto n · Manual m` and take the highest variant priority; heuristic
35
+ oracle-shape/precondition mismatches are review-level, silenced once approved and unchanged) ·
36
+ D executability (precondition · condition+
35
37
  data · trigger · oracle all renderable; every `{{var}}` resolves; **no template token may survive
36
38
  into a rendered cell** — test-data cross-references are resolved for display) · E drift
37
- (fingerprint mismatch → back to review) · G review state (proposed groups block the official
39
+ (scenario fingerprint mismatch → back to review; the map's OWN reviewed
40
+ wording/grouping is fingerprinted as `__map__` too, so post-approval edits re-open review) · G review state (proposed groups block the official
38
41
  render; `--preview` renders a DRAFT watermark) · R requirement coverage (spec FR/TR/NFR ids with
39
42
  no trace and no `requirements:` status → warning) · W wording lint (map intent/oracle containing
40
43
  tokens, `[Selector]` refs, DSL phrasing, or generator labels → warning).
@@ -49,17 +52,33 @@ Precondition, `Action:` → Action, `Observable:` → Expected Result, `Oracle:`
49
52
  mid-flow assertions inline as `Verify: …`; only the final Then block is the Expected Result.
50
53
  Empty test values render as `(empty)`.
51
54
 
55
+ **Output format**: **XLSX only by default** (one artifact). `--format csv` writes the flat CSV
56
+ instead; `--format both` writes both.
57
+
52
58
  **Workbook**: `Testcases` sheet — parent rows + outline-level-1 variant sub-rows for **every**
53
59
  item (single-variant included: the sub-row carries the source VP-id, resolved data, and the
54
- result/evidence entry). Collapse outline for the customer view, expand to execute. Variant Result
55
- cells have a dropdown (Passed/Failed/Blocked/Pending/N/A) and the parent Result is a **live Excel
56
- formula** over its children (failed→blocked→pending→partial→passed, e.g. `2/3 Passed · 1 Failed`)
57
- a parent can never contradict its variants, even after manual edits. ID + Target columns are
58
- frozen; dates are ISO (`2026-08-04`). `Coverage` sheet — requirement coverage table (every FR/TR/
59
- NFR id with an explicit status), target × category grid with explicit `—` gaps, dispositions,
60
- manifest. CSV is flat with a `Level` column (`item`/`variant`) + a requirement-coverage appendix.
60
+ result/evidence entry). Sub-rows are **delta-only**: knowledge common to the whole item
61
+ (precondition, trigger) is written ONCE on the parent; a child repeats only what distinguishes it
62
+ (condition/data, precondition delta, trigger when it differs) plus its own precise oracle and
63
+ execution fields. The parent never carries placeholder text when triggers differ the cell is
64
+ simply empty and the sub-rows carry them.
65
+
66
+ Parent preconditions are the **intersection** of the variants' variant-specific setup stays on
67
+ the variant, so no variant inherits a wrong start state. Variant Result cells have a dropdown
68
+ (Passed/Failed/Blocked/Pending/N/A) and the parent Result is a **live Excel formula** over its
69
+ children (failed→blocked→pending→partial→passed; **`N/A` leaves the denominator**, all-`N/A` →
70
+ `N/A`). The summary band counts results with live formulas too. Evidence and Defect ID are
71
+ separate columns; ID + Target frozen; ISO dates; landscape print with repeated header rows.
72
+
73
+ `Coverage` sheet — requirement coverage table (every FR/TR/NFR id with an explicit status),
74
+ target × category grid with explicit `—` gaps, dispositions, manifest. CSV mirrors the same model
75
+ flat with a `Level` column (`item`/`variant`) + a requirement-coverage appendix.
61
76
  `delivery_item_count` ≠ progress — variants are the execution metric.
62
77
 
78
+ **Data fidelity**: invisible test data is made visible, never normalized — `''` → `(empty)`,
79
+ whitespace-only → `(5 spaces)`, padded → `" value "` quoted verbatim. A trim/collapse here would
80
+ silently break the whitespace tests it describes.
81
+
63
82
  **Authoring guidance the matrix rewards** (create-test side): payload/provider matrices (SQLi
64
83
  payload lists, OAuth provider sets) belong in `@cases` datasets so each case is an atomic,
65
84
  independently-reportable variant; keep dataset `case:` labels short and stable (`CHK-EMAIL-I1`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sungen",
3
- "version": "3.2.16-beta.2",
3
+ "version": "3.2.16-beta.4",
4
4
  "description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -39,8 +39,8 @@
39
39
  "@babel/types": "^7.28.5",
40
40
  "@cucumber/gherkin": "^37.0.0",
41
41
  "@cucumber/messages": "^31.0.0",
42
- "@sungen/driver-data-factory": "3.2.16-beta.2",
43
- "@sungen/driver-ui": "3.2.16-beta.2",
42
+ "@sungen/driver-data-factory": "3.2.16-beta.4",
43
+ "@sungen/driver-ui": "3.2.16-beta.4",
44
44
  "chalk": "^5.6.2",
45
45
  "commander": "^14.0.2",
46
46
  "dotenv": "^17.2.3",
@@ -31,6 +31,7 @@ import {
31
31
  loadMatrixModel,
32
32
  approveMatrix,
33
33
  writeMatrixDeliverables,
34
+ MatrixFormat,
34
35
  hasErrors,
35
36
  hasReview,
36
37
  } from '../../exporters/matrix/export';
@@ -651,7 +652,7 @@ interface MatrixRunSummary {
651
652
  async function exportMatrixTarget(
652
653
  cwd: string,
653
654
  target: DeliveryTarget,
654
- opts: { check?: boolean; preview?: boolean },
655
+ opts: { check?: boolean; preview?: boolean; format?: MatrixFormat },
655
656
  ): Promise<MatrixRunSummary | null> {
656
657
  const paths = matrixPathsFor(cwd, target);
657
658
  const { model, mapMissing, mapErrors } = loadMatrixModel(paths);
@@ -689,24 +690,25 @@ async function exportMatrixTarget(
689
690
  return null;
690
691
  }
691
692
 
692
- const { csvPath, xlsxPath } = await writeMatrixDeliverables(paths, model);
693
+ const { csvPath, xlsxPath } = await writeMatrixDeliverables(paths, model, opts.format ?? 'xlsx');
693
694
  const passed = model.items.reduce((a, i) => a + i.resultCounts.passed, 0);
694
695
  const failed = model.items.reduce((a, i) => a + i.resultCounts.failed, 0);
695
- log(` ${COLOR.green}→ ${path.relative(cwd, xlsxPath)}${COLOR.reset} ${COLOR.gray}(+ ${path.relative(cwd, csvPath)})${COLOR.reset}`);
696
+ const written = [xlsxPath, csvPath].filter((p): p is string => !!p).map((p) => path.relative(cwd, p));
697
+ for (const rel of written) log(` ${COLOR.green}→ ${rel}${COLOR.reset}`);
696
698
  return {
697
699
  label: paths.label,
698
700
  items: model.manifest.itemCount,
699
701
  variants: model.manifest.variantCount,
700
702
  passed,
701
703
  failed,
702
- file: path.relative(cwd, xlsxPath),
704
+ file: written.join(' + '),
703
705
  };
704
706
  }
705
707
 
706
708
  function printMatrixSummaryTable(summaries: MatrixRunSummary[]): void {
707
709
  log(`\n${COLOR.bold}Delivery matrix export complete${COLOR.reset}\n`);
708
710
  const colWidth = Math.max(20, ...summaries.map((s) => s.label.length)) + 1;
709
- log(` ${'Feature'.padEnd(colWidth)}Items Variants Passed Failed File`);
711
+ log(` ${'Feature'.padEnd(colWidth)}Items Variants Passed Failed File(s)`);
710
712
  log(' ' + '-'.repeat(colWidth + 50));
711
713
  for (const s of summaries) {
712
714
  log(
@@ -796,9 +798,11 @@ export function registerDeliveryCommand(program: Command): void {
796
798
  .option('--check', 'Matrix gates only — validate the delivery map, write nothing')
797
799
  .option('--approve [ids]', 'Approve proposed groups (all, or a comma-separated id list) + stamp fingerprints')
798
800
  .option('--preview', 'Render the matrix despite review-required findings (DRAFT watermark)')
801
+ .option('--format <format>', 'Matrix output format: xlsx (default) | csv | both', 'xlsx')
799
802
  .action(async (names: string[], options: {
800
803
  skipPreflight?: boolean; continueOnMissing?: boolean; env?: string;
801
804
  legacy?: boolean; full?: boolean; check?: boolean; approve?: boolean | string; preview?: boolean;
805
+ format?: string;
802
806
  }) => {
803
807
  try {
804
808
  // Same effect as running with SUNGEN_ENV=<env> — result-file resolution,
@@ -806,6 +810,13 @@ export function registerDeliveryCommand(program: Command): void {
806
810
  if (options.env) process.env.SUNGEN_ENV = options.env;
807
811
  const cwd = process.cwd();
808
812
 
813
+ // Matrix output format — one artifact by default (xlsx); csv/both on request.
814
+ const format = (options.format ?? 'xlsx').toLowerCase();
815
+ if (!['xlsx', 'csv', 'both'].includes(format)) {
816
+ console.error(`${COLOR.red}Invalid --format "${options.format}"${COLOR.reset} — use xlsx | csv | both`);
817
+ process.exit(1);
818
+ }
819
+
809
820
  // 1. Scope detection — each positional name expands into one target
810
821
  // per `.feature` file inside that screen/flow. Passing a specific
811
822
  // feature basename (e.g. `home-modal`) narrows to that one file.
@@ -886,7 +897,9 @@ export function registerDeliveryCommand(program: Command): void {
886
897
  const matrixSummaries: MatrixRunSummary[] = [];
887
898
  let failedTargets = 0;
888
899
  for (const target of toExport) {
889
- const s = await exportMatrixTarget(cwd, target, { check: options.check, preview: options.preview });
900
+ const s = await exportMatrixTarget(cwd, target, {
901
+ check: options.check, preview: options.preview, format: format as MatrixFormat,
902
+ });
890
903
  if (s) matrixSummaries.push(s);
891
904
  else failedTargets++;
892
905
  }
@@ -14,7 +14,7 @@ import {
14
14
  splitVpAndName,
15
15
  } from '../feature-parser';
16
16
  import { getCasesDatasetRows, resolveResultVariants } from '../result-variants';
17
- import { classifyManualComments, renderAction, renderExpected, renderPrecondition } from './wording';
17
+ import { classifyManualComments, renderAction, renderExpected, renderPrecondition, renderSetupInstruction } from './wording';
18
18
  import { scenarioFingerprint, combinedFingerprint, mapContentFingerprint } from './fingerprint';
19
19
  import {
20
20
  CoverageVariant,
@@ -72,12 +72,12 @@ function resolveDataPairs(
72
72
  if (row) {
73
73
  for (const [k, v] of Object.entries(row)) {
74
74
  if (k.startsWith('__') || k === 'case' || k === 'name' || k === 'label') continue;
75
- pairs.push(`${k}: ${String(v)}`);
75
+ pairs.push(`${k}: ${displayValue(String(v))}`);
76
76
  }
77
77
  }
78
78
  for (const v of vars) {
79
79
  const val = row && v in row ? undefined : testData?.[v]; // row columns already listed
80
- if (val !== undefined) pairs.push(`${v}: ${val}`);
80
+ if (val !== undefined) pairs.push(`${v}: ${displayValue(val)}`);
81
81
  }
82
82
  return pairs;
83
83
  }
@@ -141,7 +141,7 @@ export function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' |
141
141
  ...(authRole ? [authRole === 'no-auth' ? 'The user is signed out.' : `The user is signed in as ${authRole}.`] : []),
142
142
  ...inputs.feature.backgroundGivenSteps.map(renderPrecondition),
143
143
  ...m.feature.rawGivenSteps.map(renderPrecondition),
144
- ...(manual?.preconditions ?? []).map((t) => renderPrecondition(t)),
144
+ ...(manual?.preconditions ?? []).map((t) => renderSetupInstruction(t)),
145
145
  ]));
146
146
 
147
147
  const base = {
@@ -247,11 +247,22 @@ export function deriveVariants(inputs: Pick<BuildInputs, 'feature' | 'merged' |
247
247
  function substituteDisplayVars(text: string, vars: Record<string, string>): string {
248
248
  return text.replace(/\{\{\s*([^}\s]+)\s*\}\}/g, (m, key: string) => {
249
249
  if (!(key in vars)) return m; // unknown stays literal → Gate D flags it
250
- const v = vars[key];
251
- return v === '' ? '(empty)' : v;
250
+ return displayValue(vars[key]);
252
251
  });
253
252
  }
254
253
 
254
+ /**
255
+ * Make invisible test data VISIBLE instead of losing it (review GAP-04):
256
+ * '' → (empty) · whitespace-only → (N spaces) · padded → quoted verbatim.
257
+ * The canonical value is never changed — only its presentation.
258
+ */
259
+ export function displayValue(v: string): string {
260
+ if (v === '') return '(empty)';
261
+ if (/^\s+$/.test(v)) return `(${v.length} space${v.length > 1 ? 's' : ''})`;
262
+ if (v !== v.trim()) return `"${v}"`;
263
+ return v;
264
+ }
265
+
255
266
  function sentenceOf(text: string): string {
256
267
  const s = text.trim();
257
268
  if (!s) return s;
@@ -368,6 +379,12 @@ export function buildMatrix(inputs: BuildInputs): MatrixModel {
368
379
  const { result, counts } = rollUp(groupVariants);
369
380
  const first = groupVariants[0];
370
381
  const triggerShapes = new Set(groupVariants.map((v) => v.triggerShape.join(' ; ')));
382
+ const modes = new Set(groupVariants.map((v) => v.mode));
383
+ // Item priority = highest variant priority (per-variant priorities stay visible).
384
+ const priorityRank: Record<string, number> = { High: 0, Normal: 1, Low: 2 };
385
+ const priority = groupVariants
386
+ .map((v) => v.priority)
387
+ .sort((a, b) => (priorityRank[a] ?? 1) - (priorityRank[b] ?? 1))[0] ?? 'Normal';
371
388
  return {
372
389
  id: g.id,
373
390
  target: g.target,
@@ -376,11 +393,16 @@ export function buildMatrix(inputs: BuildInputs): MatrixModel {
376
393
  category: g.category,
377
394
  // A stale (drifted) group presents as proposed regardless of its stored state.
378
395
  review: stale.has(g.id) ? 'proposed' : g.review,
379
- priority: first?.priority ?? 'Normal',
380
- mode: first?.mode ?? 'auto',
396
+ priority,
397
+ mode: modes.size > 1 ? 'mixed' : (first?.mode ?? 'auto'),
381
398
  layers: Array.from(new Set(groupVariants.flatMap((v) => v.layers))),
382
399
  traces: Array.from(new Set(groupVariants.flatMap((v) => v.traces))),
383
- precondition: first?.precondition ?? [],
400
+ // Only the preconditions COMMON to every variant belong on the parent —
401
+ // copying the first variant's setup mis-states the start state of the
402
+ // others (review GAP-03). Variant-specific lines render as the sub-row's
403
+ // precondition delta.
404
+ precondition: (first?.precondition ?? []).filter((line) =>
405
+ groupVariants.every((v) => v.precondition.includes(line))),
384
406
  trigger: triggerShapes.size === 1 ? (first?.trigger ?? []) : ['(per variant)'],
385
407
  variants: groupVariants,
386
408
  result,
@@ -17,6 +17,7 @@ import { getPackageVersion } from '../package-info';
17
17
  import { writeCsv } from '../csv-exporter';
18
18
  import { writeXlsx } from '../xlsx-exporter';
19
19
  import { loadDeliveryMap, writeDeliveryMap } from './map-loader';
20
+ import { mapContentFingerprint } from './fingerprint';
20
21
  import { buildMatrix, deriveVariants } from './build';
21
22
  import { renderMatrixXlsx } from './render-xlsx';
22
23
  import { renderMatrixCsv } from './render-csv';
@@ -121,14 +122,28 @@ export function approveMatrix(paths: MatrixTargetPaths, groupIds?: string[]): {
121
122
  g.review = 'approved';
122
123
  approved.push(g.id);
123
124
  }
125
+ // Freeze the reviewed map semantics as well (GAP-09) — computed AFTER the
126
+ // review flips so re-running approve on an unchanged map is idempotent.
127
+ map.fingerprints.__map__ = mapContentFingerprint(map.groups, map.dispositions);
124
128
  writeDeliveryMap(paths.mapFile, map);
125
129
  return { findings: model.findings.filter((f) => f.severity !== 'error'), approved };
126
130
  }
127
131
 
128
- /** Render + write both artifacts. Caller has already enforced the gate policy. */
129
- export async function writeMatrixDeliverables(paths: MatrixTargetPaths, model: MatrixModel): Promise<{ csvPath: string; xlsxPath: string }> {
130
- const csvPath = writeCsv(paths.cwd, paths.unit, renderMatrixCsv(model));
131
- const wb = renderMatrixXlsx(model, getPackageVersion());
132
- const xlsxPath = await writeXlsx(paths.cwd, paths.unit, wb);
133
- return { csvPath, xlsxPath };
132
+ export type MatrixFormat = 'xlsx' | 'csv' | 'both';
133
+
134
+ /** Render + write the requested format(s). Caller has already enforced the gate policy. */
135
+ export async function writeMatrixDeliverables(
136
+ paths: MatrixTargetPaths,
137
+ model: MatrixModel,
138
+ format: MatrixFormat = 'xlsx',
139
+ ): Promise<{ csvPath?: string; xlsxPath?: string }> {
140
+ const out: { csvPath?: string; xlsxPath?: string } = {};
141
+ if (format === 'csv' || format === 'both') {
142
+ out.csvPath = writeCsv(paths.cwd, paths.unit, renderMatrixCsv(model));
143
+ }
144
+ if (format === 'xlsx' || format === 'both') {
145
+ const wb = renderMatrixXlsx(model, getPackageVersion());
146
+ out.xlsxPath = await writeXlsx(paths.cwd, paths.unit, wb);
147
+ }
148
+ return out;
134
149
  }
@@ -12,6 +12,7 @@
12
12
  */
13
13
 
14
14
  import { splitVpAndName, extractTestcaseType } from '../feature-parser';
15
+ import { mapContentFingerprint } from './fingerprint';
15
16
  import { CoverageVariant, MatrixFinding, MAX_VARIANTS_PER_ITEM } from './types';
16
17
  import { expandMapRef, BuildInputs } from './build';
17
18
 
@@ -156,10 +157,11 @@ function gateCAggregation(ctx: GateContext, findings: MatrixFinding[]): void {
156
157
  const heuristicsConfirmed = g.review === 'approved' && !stale;
157
158
 
158
159
  // Hard signature parts — recomputed, never trusted from the map. ERROR on mismatch.
160
+ // Execution mode and priority are deliberately NOT here: they are coverage
161
+ // dimensions (account states may need seeded manual variants next to auto ones;
162
+ // an item takes the highest variant priority) — shown per variant, never split on.
159
163
  const hard: Array<[string, (v: CoverageVariant) => string]> = [
160
- ['execution mode', (v) => v.mode],
161
164
  ['test layer', (v) => [...v.layers].sort().join('+')],
162
- ['priority', (v) => v.priority],
163
165
  ];
164
166
  for (const [label, keyOf] of hard) {
165
167
  const distinct = new Set(vs.map(keyOf));
@@ -265,6 +267,25 @@ function gateEDrift(ctx: GateContext, findings: MatrixFinding[]): void {
265
267
  const { map } = ctx.inputs;
266
268
  const { variantsByVp } = ctx;
267
269
 
270
+ // The map's own semantics (targets/intents/oracles/grouping) are part of what
271
+ // was approved — an edit after approval must be re-reviewed, not silently
272
+ // published (review GAP-09).
273
+ const stampedMap = map.fingerprints.__map__;
274
+ const liveMap = mapContentFingerprint(map.groups, map.dispositions);
275
+ if (map.groups.some((g) => g.review === 'approved')) {
276
+ if (!stampedMap) {
277
+ findings.push({
278
+ gate: 'E', severity: 'review',
279
+ message: 'the delivery map has no stamped content fingerprint — run `sungen delivery --approve` to record the reviewed wording',
280
+ });
281
+ } else if (stampedMap !== liveMap) {
282
+ findings.push({
283
+ gate: 'E', severity: 'review',
284
+ message: 'the delivery map wording/grouping changed since approval — re-review, then `sungen delivery --approve`',
285
+ });
286
+ }
287
+ }
288
+
268
289
  for (const g of map.groups) {
269
290
  if (g.review !== 'approved') continue; // proposed groups are already under review
270
291
  for (const ref of g.variants) {
@@ -6,13 +6,13 @@
6
6
  */
7
7
 
8
8
  import { statusToTestResult } from '../playwright-report-parser';
9
- import { itemResultLabel } from './render-xlsx';
9
+ import { itemModeLabel, itemResultLabel } from './render-xlsx';
10
10
  import { MatrixModel } from './types';
11
11
 
12
12
  const HEADERS = [
13
13
  'Level', 'ID', 'Target', 'Test Intent / Condition', 'Category', 'Priority',
14
14
  'Precondition', 'Coverage / Test Data', 'Action / Trigger', 'Expected Result',
15
- 'Mode', 'Trace', 'Result', 'Executed Date', 'Note',
15
+ 'Mode', 'Trace', 'Result', 'Executed Date', 'Note / Evidence', 'Defect ID',
16
16
  ];
17
17
 
18
18
  function esc(value: string): string {
@@ -36,7 +36,8 @@ export function renderMatrixCsv(model: MatrixModel): string {
36
36
 
37
37
  for (const item of model.items) {
38
38
  const triggerTexts = new Set(item.variants.map((v) => v.trigger.join('\n')));
39
- const commonTrigger = triggerTexts.size === 1 ? item.variants[0].trigger.join('\n') : '(differs per variant — see variant rows)';
39
+ const triggerIsCommon = triggerTexts.size === 1;
40
+ const commonPre = new Set(item.precondition);
40
41
  lines.push([
41
42
  'item',
42
43
  item.id,
@@ -46,13 +47,15 @@ export function renderMatrixCsv(model: MatrixModel): string {
46
47
  item.priority,
47
48
  item.precondition.join('\n'),
48
49
  `${item.variants.length} variant(s): ${item.variants.map((v) => v.condition).join(' · ')}`,
49
- commonTrigger,
50
+ // No placeholder text: when triggers differ the variant rows carry them (GAP-01).
51
+ triggerIsCommon ? item.variants[0].trigger.join('\n') : '',
50
52
  item.oracle,
51
- item.mode === 'manual' ? 'Manual' : 'Auto',
53
+ itemModeLabel(item),
52
54
  item.traces.join(' '),
53
55
  itemResultLabel(item),
54
56
  '',
55
57
  item.review === 'proposed' ? 'REVIEW REQUIRED' : '',
58
+ '',
56
59
  ].map(esc).join(','));
57
60
 
58
61
  for (const v of item.variants) {
@@ -65,15 +68,17 @@ export function renderMatrixCsv(model: MatrixModel): string {
65
68
  '',
66
69
  v.condition,
67
70
  '', '',
68
- '',
71
+ // Precondition DELTA — variant-specific setup only (review GAP-03).
72
+ v.precondition.filter((line) => !commonPre.has(line)).join('\n'),
69
73
  v.data.join('\n'),
70
- v.trigger.join('\n'),
74
+ triggerIsCommon ? '' : v.trigger.join('\n'),
71
75
  expected,
72
76
  v.mode === 'manual' ? 'Manual' : 'Auto',
73
77
  v.traces.join(' '),
74
78
  v.result ? statusToTestResult(v.result.status) : 'Pending',
75
79
  isoDate(v.result?.startTime),
76
80
  v.result?.error ? String(v.result.error).slice(0, 200) : '',
81
+ '',
77
82
  ].map(esc).join(','));
78
83
  }
79
84
  }