@sun-asterisk/sungen 3.2.14 → 3.2.15

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 (50) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +29 -50
  3. package/dist/cli/commands/delivery.js.map +1 -1
  4. package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
  5. package/dist/dashboard/snapshot-builder.js +3 -46
  6. package/dist/dashboard/snapshot-builder.js.map +1 -1
  7. package/dist/exporters/locale-variants.d.ts +38 -0
  8. package/dist/exporters/locale-variants.d.ts.map +1 -0
  9. package/dist/exporters/locale-variants.js +159 -0
  10. package/dist/exporters/locale-variants.js.map +1 -0
  11. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +3 -11
  12. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +11 -1
  13. package/dist/generators/test-generator/code-generator.js +1 -1
  14. package/dist/generators/test-generator/code-generator.js.map +1 -1
  15. package/dist/generators/test-generator/diagnostics.d.ts +4 -1
  16. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  17. package/dist/generators/test-generator/diagnostics.js +3 -0
  18. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  19. package/dist/generators/test-generator/step-mapper.d.ts +6 -0
  20. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  21. package/dist/generators/test-generator/step-mapper.js +41 -2
  22. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  23. package/dist/harness/annotation-overrides.d.ts +4 -1
  24. package/dist/harness/annotation-overrides.d.ts.map +1 -1
  25. package/dist/harness/annotation-overrides.js +5 -2
  26. package/dist/harness/annotation-overrides.js.map +1 -1
  27. package/dist/harness/quality-gates.d.ts.map +1 -1
  28. package/dist/harness/quality-gates.js +5 -0
  29. package/dist/harness/quality-gates.js.map +1 -1
  30. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +7 -1
  31. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +1 -0
  32. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -0
  33. package/dist/orchestrator/templates/ai-src/skills/sungen-locale/SKILL.md +8 -0
  34. package/dist/orchestrator/templates/specs-test-data.ts +13 -4
  35. package/package.json +4 -4
  36. package/src/cli/commands/delivery.ts +32 -70
  37. package/src/dashboard/snapshot-builder.ts +11 -61
  38. package/src/exporters/locale-variants.ts +157 -0
  39. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +3 -11
  40. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +11 -1
  41. package/src/generators/test-generator/code-generator.ts +1 -1
  42. package/src/generators/test-generator/diagnostics.ts +4 -1
  43. package/src/generators/test-generator/step-mapper.ts +43 -2
  44. package/src/harness/annotation-overrides.ts +5 -2
  45. package/src/harness/quality-gates.ts +4 -0
  46. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +7 -1
  47. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +1 -0
  48. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +8 -0
  49. package/src/orchestrator/templates/ai-src/skills/sungen-locale/SKILL.md +8 -0
  50. package/src/orchestrator/templates/specs-test-data.ts +13 -4
@@ -5,10 +5,13 @@ exports.parseQueryOverrides = parseQueryOverrides;
5
5
  * Shared annotation-override grammar for precondition annotations (`@query`/`@api`).
6
6
  *
7
7
  * Parses `name(a={{x}},b="lit",c=3)` overrides into a map of JS expressions, e.g.
8
- * `{ a: "testData.get('x')", b: "\"lit\"", c: "3" }`. Used by the DB and API capability drivers'
8
+ * `{ a: "testData.raw('x')", b: "\"lit\"", c: "3" }`. Used by the DB and API capability drivers'
9
9
  * precondition codegen; lives in core so both drivers can share it. Gherkin tags carry no whitespace,
10
10
  * so values are single tokens — flows thread a prior response via a whole-value ref, e.g.
11
11
  * `@api:get_profile(token={{login.body.token}})`, with the auth scheme declared in the catalog header.
12
+ * A `{{ref}}` override binds into a typed sink (DB query param, JSON request body), so it resolves
13
+ * via `testData.raw()` (native type, still interpolates embedded refs) rather than `get()`
14
+ * (Gherkin-text stringify) — a numeric override otherwise reaches the DB/API as a JSON string.
12
15
  */
13
16
  function parseQueryOverrides(raw) {
14
17
  const out = {};
@@ -25,7 +28,7 @@ function parseQueryOverrides(raw) {
25
28
  const v = val.match(/^\{\{\s*([^}]+?)\s*\}\}$/);
26
29
  const q = val.match(/^["'](.*)["']$/);
27
30
  if (v)
28
- out[key] = `testData.get(${JSON.stringify(v[1])})`;
31
+ out[key] = `testData.raw(${JSON.stringify(v[1])})`;
29
32
  else if (q)
30
33
  out[key] = JSON.stringify(q[1]);
31
34
  else if (/^-?\d+(?:\.\d+)?$/.test(val))
@@ -1 +1 @@
1
- {"version":3,"file":"annotation-overrides.js","sourceRoot":"","sources":["../../src/harness/annotation-overrides.ts"],"names":[],"mappings":";;AASA,kDAiBC;AA1BD;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CAAC,GAAY;IAC9C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;aACrD,IAAI,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACvC,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;;YAClD,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"annotation-overrides.js","sourceRoot":"","sources":["../../src/harness/annotation-overrides.ts"],"names":[],"mappings":";;AAYA,kDAiBC;AA7BD;;;;;;;;;;;GAWG;AACH,SAAgB,mBAAmB,CAAC,GAAY;IAC9C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;aACrD,IAAI,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACvC,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;;YAClD,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"quality-gates.d.ts","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAA2B,MAAM,SAAS,CAAC;AAKhE,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAoBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAG7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAMpF;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAe7F;AAID,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAMD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAgCpE;AAMD,+GAA+G;AAC/G,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,CAStE;AAID;kFACkF;AAClF,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBxJ;AAID,MAAM,WAAW,eAAe;IAAG,UAAU,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE;AAErF,kGAAkG;AAClG,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,eAAe,CAqBpG;AAGD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C"}
1
+ {"version":3,"file":"quality-gates.d.ts","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAA2B,MAAM,SAAS,CAAC;AAKhE,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAoBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAG7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAMpF;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAe7F;AAID,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAMD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAgCpE;AAMD,+GAA+G;AAC/G,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,CAStE;AAID;kFACkF;AAClF,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBxJ;AAID,MAAM,WAAW,eAAe;IAAG,UAAU,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE;AAErF,kGAAkG;AAClG,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,eAAe,CAyBpG;AAGD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C"}
@@ -205,6 +205,11 @@ function sourceBacked(scenarios, frIds, viewpointItems, viewpointIds, featureTex
205
205
  }
206
206
  /** Scenarios whose step-skeleton also appears in a sibling flow feature → duplicate ownership. */
207
207
  function crossArtifactOwnership(screenDir, scenarios) {
208
+ // A behavior's ownership is judged from the screen side; flow/api units are the owners, so the
209
+ // gate does not apply to them. Without this guard, auditing qa/flows/<x>, qa/api/<x>, or
210
+ // qa/api/flows/<x> resolves flowsRoot to the unit's own parent and every scenario self-matches.
211
+ if (path.basename(path.dirname(screenDir)) !== 'screens')
212
+ return { duplicates: [] };
208
213
  const duplicates = [];
209
214
  // screenDir = <root>/qa/screens/<name>; flows live at <root>/qa/flows/*/features/*.feature
210
215
  const flowsRoot = path.resolve(screenDir, '..', '..', 'flows');
@@ -1 +1 @@
1
- {"version":3,"file":"quality-gates.js","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,sCAGC;AAcD,8CAMC;AAED,0CAeC;AAaD,oCAgCC;AAOD,gDASC;AAMD,oCAqBC;AAOD,wDAqBC;AAGD,4BAEC;AAzMD;;;;GAIG;AACH,uCAAyB;AACzB,2CAA6B;AAC7B,mCAAgE;AAChE,kEAAmE;AASnE,mGAAmG;AACnG,SAAS,gBAAgB,CAAC,QAAgB;IACxC,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,mCAAmC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACrD,kGAAkG;QAClG,qFAAqF;QACrF,0FAA0F;QAC1F,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,2CAA2C,CAAC,EAAE,CAAC;YAC3E,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IACD,oFAAoF;IACpF,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9H,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,WAAmB,EAAE,QAAiB;IAClE,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,OAAO,CAAC,+EAA+E,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC5G,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,iBAAiB,CAAC,WAAmB,EAAE,aAAqB;IAC1E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,CAAC,CAAC,CAAQ,mCAAmC;IACzF,IAAI,aAAa,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC,CAAsB,2CAA2C;IACjG,MAAM,aAAa,GAAG,4CAA4C,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACrF,IAAI,CAAC,aAAa;QAAE,OAAO,CAAC,CAAC,CAAyB,+DAA+D;IACrH,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAgB,eAAe,CAAC,QAAgB,EAAE,SAAyB;IACzE,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAsC,EAAE,CAAC;IAC3D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7E,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC5G,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,SAAS,CAAC,8DAA8D;QAC1F,mFAAmF;QACnF,mFAAmF;QACnF,8EAA8E;QAC9E,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,sBAAsB,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,cAAc;YAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACpD,CAAC;AASD,SAAS,MAAM,CAAC,WAAmB;IACjC,OAAO,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,SAAgB,YAAY,CAAC,WAAmB;IAC9C,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QACnC,WAAW,EAAE,CAAC;QACd,qDAAqD;QACrD,mFAAmF;QACnF,mFAAmF;QACnF,6EAA6E;QAC7E,iFAAiF;QACjF,oFAAoF;QACpF,mFAAmF;QACnF,gFAAgF;QAChF,+EAA+E;QAC/E,MAAM,eAAe,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,GAAY,CAAC;QACjB,IAAI,eAAe,EAAE,CAAC;YACpB,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;iBAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,IAAA,qCAAmB,EAAC,YAAY,CAAC,CAAC;YACjD,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxD,CAAC;QACD,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC;YACnE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AACvC,CAAC;AAED,gDAAgD;AAEhD,MAAM,SAAS,GAAG,mKAAmK,CAAC;AAEtL,+GAA+G;AAC/G,SAAgB,kBAAkB,CAAC,SAAyB;IAC1D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,MAAM;YAAE,SAAS,CAAiB,wEAAwE;QAChH,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,MAAM,MAAM,GAAG,6GAA6G,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/I,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,oDAAoD;AAEpD;kFACkF;AAClF,SAAgB,YAAY,CAAC,SAAyB,EAAE,KAAe,EAAE,cAAwB,EAAE,YAAsB,EAAE,WAAmB;IAC5I,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC,CAAC,cAAc;IAC9F,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxG,0FAA0F;IAC1F,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAA,gBAAQ,EAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrG,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;QACrE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5H,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAMD,kGAAkG;AAClG,SAAgB,sBAAsB,CAAC,SAAiB,EAAE,SAAyB;IACjF,MAAM,UAAU,GAAyC,EAAE,CAAC;IAC5D,2FAA2F;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAC3E,KAAK,MAAM,GAAG,IAAI,IAAA,qBAAa,EAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,EAAE;oBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI;QAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvG,IAAI,IAAI;YAAE,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,CAAC;AACxB,CAAC;AAED,qBAAqB;AACrB,SAAgB,QAAQ,CAAC,CAAS;IAChC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"quality-gates.js","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":"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"}
@@ -85,7 +85,13 @@ The `.xlsx` leads with an **`Overview`** roll-up sheet, then splits the test cas
85
85
  - **`Auto`** — automatable test cases (`Auto` + `Not compiled`).
86
86
  - **`Manual`** — `@manual` test cases (always present, header-only when there are none).
87
87
 
88
- Multi-locale (no `SUNGEN_ENV`): `Overview` + one **`<LOCALE> Auto`** sheet per locale + a single shared **`Manual`** sheet (manual TCs are locale-invariant). The **CSV stays one file with every row** — the `Testcase type` column distinguishes Auto vs Manual. The Overview lists every detail sheet, so each locale's counts appear on its own row.
88
+ Multi-locale: `Overview` + one **`<LOCALE> Auto`** sheet per locale + a single shared **`Manual`** sheet (manual TCs are locale-invariant). The **CSV stays one file with every row** — the `Testcase type` column distinguishes Auto vs Manual. The Overview lists every detail sheet, so each locale's counts appear on its own row.
89
+
90
+ **Which result files become locale sheets — locales are DECLARED, never guessed.** A result-file suffix (`<name>-test-result.<X>.json`) is a locale ONLY when `X` is listed in `qa/capabilities.yaml` `locales:` (written by `/sungen:locale`), or — when delivering with `--env <E>` / `SUNGEN_ENV=<E>` — when `X = <E>-<locale>`. Every delivery mixes results of ONE environment:
91
+ - `sungen delivery login` → base results + bare declared locales (`ja`); `dev`/`stg` suffixes are IGNORED with a hint (`→ sungen delivery login --env dev`)
92
+ - `sungen delivery login --env dev` → `dev` results as base + `dev-ja` sheets; everything else ignored
93
+ - `--env ja` (SUNGEN_ENV=<locale> convention) → that locale's run IS the base, labeled JA
94
+ The base sheet label comes from `base_locale:` (default **EN**). Undeclared env suffixes NEVER fabricate locale sheets — a project without `locales:` always gets one clean `Auto` sheet. Mobile per-OS suffixes (`android`, `ios.ja`, …) are exempt and keep the per-OS files; their Test Data column merges the after-OS tail overlay (`ios.ja` → `<name>.ja.yaml`), matching what the runtime merged.
89
95
 
90
96
  ---
91
97
 
@@ -94,6 +94,7 @@ needs any of these, it is a **finding for QA** — surface it in the run summary
94
94
  | `SG-W007` | Browser-alert handler step written AFTER an action — listener registers too late, the dialog auto-dismisses silently | Use the compound form `click [X] button and accept [OK] alert` (preferred), or move the alert step before the trigger |
95
95
  | `SG-W008` | `@manual` scenario incomplete in either direction: (a) HAS Gherkin steps but NO `Then` — a dangling `When` is invalid Gherkin, comments can NOT substitute; (b) documentation-style (NO steps) but its comments lack numbered action lines and/or a labeled oracle line — prose paragraphs / rationale-only comments export EMPTY Steps + Expected cells | Two valid shapes only: complete the Gherkin with a `Then`, or write the FULL procedure in the `# Tester verifies:` block as NUMBERED lines — action steps first (`1. <action>`), then labeled `Observable:`/`Oracle:`/`Expected:` lines (the number is what fills Steps, the label is what fills Expected results) |
96
96
  | `SG-W009` | test-data references `${QA_<NAME>}` (a SECRET env ref) but the name is declared in neither `.env.qa` nor `.env.qa.example` — the test throws "environment variable not set" the moment the key is used. (Only the `${QA_*}` shape is checked; any other `${...}` is literal data and never flagged.) | Add `QA_<NAME>=<value>` to `.env.qa` (gitignored) and list the NAME in `.env.qa.example` (the committed checklist). See `qa/TEST-DATA-GUIDE.md` |
97
+ | `SG-W010` | A row step's `[Ref]` looks POSITIONAL (`First…`/`Last…`/`Top…`/`nth`) but has no selectors.yaml entry — the label is display-only, so the step checks existence ANYWHERE in the table; an ordering/sort-stability rule would pass even when the row moved | Declare the row in selectors.yaml (a `type: locator` value RELATIVE to the table, e.g. `first contact row:` → `value: 'tbody tr:first-child'`) — the step then asserts `toContainText` on that exact row. This is a selectors.yaml-only fix — allowed inside the run-test auto-fix loop |
97
98
 
98
99
  ### Runtime error → `Test data "<key>" references ${QA_*} but the environment variable is not set`
99
100
 
@@ -127,6 +127,14 @@ User see [Table] table match data:
127
127
 
128
128
  Row scope: `see [Ref] row in [Table] table with {{v}}` enters scope. Subsequent `see [Col] column with {{v}}` checks cell in that row. Use `table match data:` for multi-row verification.
129
129
 
130
+ **[Ref] of a row step is a display label UNLESS declared in selectors.yaml.** Without an entry the step checks the value exists in ANY row — a name like `[First Contact Row]` does NOT position the row, and an ordering rule would pass even when the row moved (SG-W010 warns on positional-looking undeclared labels). To assert a POSITION, declare the row (a `type: locator` value RELATIVE to the table):
131
+ ```yaml
132
+ first contact row:
133
+ type: locator
134
+ value: 'tbody tr:first-child'
135
+ ```
136
+ → compiles to `expect(table.locator('tbody tr:first-child')).toContainText(v)` — the exact row must hold the value — and still enters row scope for `[Col] column` checks.
137
+
130
138
  ### Database verification (optional Data Driver)
131
139
 
132
140
  Read-only DB-state checks. **Prefer named queries** — SQL lives in `qa/screens/<screen>/database/queries.yaml` (reviewed once, parameterized). Invoke with the `@query:<name>` annotation; it binds the result rows to `{{name}}`, then assert with `expect`:
@@ -34,6 +34,14 @@ Take a screen/flow whose `selectors/*.yaml` and `.feature` files were authored a
34
34
  1. `selectors/<feature>.yaml` — hardcoded `name`/`value` replaced with `{{var}}`
35
35
  2. `test-data/<feature>.yaml` — base locale, complete with all new keys
36
36
  3. `test-data/<feature>.<locale>.yaml` — overlay with only the keys that change
37
+ 4. **`qa/capabilities.yaml` — DECLARE the locale** (required since 3.2.15): append the code to `locales:` and set `base_locale:` (language of the base test-data; tool default is `en`). Delivery/dashboard treat ONLY declared codes as locales — undeclared result-file suffixes are assumed to be ENVIRONMENTS (dev/staging) and excluded from locale sheets:
38
+ ```yaml
39
+ platform: web
40
+ enabled: [web]
41
+ base_locale: en # or vi/ja — whatever the base test-data is written in
42
+ locales: [ja] # append every bootstrapped locale here
43
+ ```
44
+ Env × locale combos use the compound `SUNGEN_ENV=<env>-<locale>` (e.g. `staging-ja`, overlay `<feature>.staging-ja.yaml`) — the locale segment LAST; delivery recognizes it when the tail matches a declared locale.
37
45
  4. (Optional) `selectors/<feature>.yaml` Pages block updated when locale uses URL prefix or query param
38
46
 
39
47
  After this skill finishes, `sungen run-test <name> --env <locale>` Just Works.
@@ -62,16 +62,25 @@ export class TestDataLoader {
62
62
 
63
63
  /**
64
64
  * Resolve a key to its RAW, uncoerced value (array/object/number kept as-is) — for binding
65
- * DB query parameters, where type-strict stores (MySQL numeric columns, MongoDB) require the
66
- * native type. get() stringifies for Gherkin text; raw() must not. Throws on missing, mirroring
67
- * get()'s guard.
65
+ * DB query / API request params, where type-strict sinks (MySQL numeric columns, MongoDB,
66
+ * a JSON request body) require the native type. get() stringifies for Gherkin text; raw()
67
+ * must not. A string value still has its embedded `{{ref}}` cross-references resolved (same
68
+ * as get()), so an override like `token={{login.body.token}}` or `id={{prefix}}-001` still
69
+ * interpolates — only the final scalar/array/object type is preserved uncoerced. Arrays and
70
+ * objects are returned as-is; refs embedded inside their elements are not interpolated (unlike
71
+ * get()'s JSON-text pass), since raw() callers bind structured values directly, not text.
72
+ * Throws on missing, mirroring get()'s guard.
68
73
  */
69
74
  raw(key: string): any {
70
75
  const value = this.resolve(key);
71
76
  if (value === undefined || value === null) {
72
77
  throw new Error(`Test data key not found: ${key}`);
73
78
  }
74
- if (typeof value === 'string') assertNoUnresolvedEnvRef(key, value);
79
+ if (typeof value === 'string') {
80
+ const result = this.interpolate(value);
81
+ assertNoUnresolvedEnvRef(key, result);
82
+ return result;
83
+ }
75
84
  return value;
76
85
  }
77
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sungen",
3
- "version": "3.2.14",
3
+ "version": "3.2.15",
4
4
  "description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -12,7 +12,7 @@
12
12
  "copy-templates": "mkdir -p dist/generators/test-generator/adapters/playwright/templates/steps && mkdir -p dist/generators/test-generator/templates && mkdir -p dist/orchestrator/templates && mkdir -p dist/dashboard/templates && cp -r src/generators/test-generator/adapters/playwright/templates/*.hbs dist/generators/test-generator/adapters/playwright/templates/ 2>/dev/null || true && cp -r src/generators/test-generator/adapters/playwright/templates/steps dist/generators/test-generator/adapters/playwright/templates/ && mkdir -p dist/generators/test-generator/adapters/appium/templates/steps && cp -r src/generators/test-generator/adapters/appium/templates/*.hbs dist/generators/test-generator/adapters/appium/templates/ 2>/dev/null || true && cp -r src/generators/test-generator/adapters/appium/templates/steps dist/generators/test-generator/adapters/appium/templates/ && cp src/generators/test-generator/templates/*.hbs dist/generators/test-generator/templates/ 2>/dev/null || true && cp -r src/orchestrator/templates/* dist/orchestrator/templates/ && cp src/dashboard/templates/index.html dist/dashboard/templates/index.html && mkdir -p dist/harness/catalog && cp src/harness/catalog/*.yaml dist/harness/catalog/",
13
13
  "build:dashboard": "cd ../../dashboard && npm install --silent && npm run build && cd - && cp ../../dashboard/dist/index.html src/dashboard/templates/index.html",
14
14
  "dev": "tsx src/cli/index.ts",
15
- "test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts && tsx tests/exporter/run.ts && tsx tests/exporter/feature-parser-category.run.ts && tsx tests/exporter/api-detail-sheet.run.ts && tsx tests/exporter/overview-sheet.run.ts && tsx tests/exporter/delivery-divider-tcid.run.ts && tsx tests/exporter/note-expected-actual.run.ts && tsx tests/exporter/test-data-vars.run.ts && tsx tests/exporter/mobile-app-id.run.ts && tsx tests/exporter/api-testcase-cells.run.ts && tsx tests/exporter/delivery-cases-result.run.ts && tsx tests/exporter/precondition-auth-role.run.ts && tsx tests/exporter/report-builder-parity.run.ts && tsx tests/exporter/delivery-preflight-testdata.run.ts && tsx tests/exporter/delivery-preflight-selectors.run.ts && tsx tests/exporter/delivery-prerun-overview.run.ts && tsx tests/exporter/manual-testcase-testdata.run.ts && tsx tests/dashboard/api-flows-discovery.run.ts && tsx tests/dashboard/status-results-fallback.run.ts && tsx tests/codegen/verb-ref-masking.run.ts && tsx tests/codegen/table-aria-hidden-locators.run.ts && tsx tests/codegen/steps-base-not-compiled.run.ts && tsx tests/codegen/manual-oracle-gate.run.ts && tsx tests/codegen/locator-value-qualified-assertions.run.ts && tsx tests/api-runtime/base-path-url-join.run.ts && tsx tests/api-runtime/file-upload-multipart.run.ts && tsx tests/api-runtime/schema-assertion.run.ts && tsx tests/runtime/test-data-cross-ref.run.ts && tsx tests/runtime/test-data-array-projection.run.ts && tsx tests/runtime/env-secret-interpolation.run.ts && tsx tests/capabilities/run.ts && tsx tests/openapi/run.ts && tsx tests/api-field-coverage/run.ts && tsx tests/packaging/run.ts && tsx tests/generate-hint/run.ts && tsx tests/template-assertion/run.ts && tsx tests/journey/run.ts && tsx tests/harness/serial-cascade.run.ts && tsx tests/ai-skills/cross-assistant-orphan.run.ts && tsx tests/init/codex-mcp-config.run.ts && tsx src/orchestrator/ai-skills/golden-skills.test.ts && tsx tests/db-runtime/sql-placeholder-rewrite.run.ts && tsx tests/db-runtime/fallback-flow-codified.run.ts && tsx tests/db-runtime/cosmos-engine.run.ts && tsx tests/db-runtime/mongodb-engine.run.ts && tsx tests/db-runtime/dynamodb-engine.run.ts && tsx tests/db-runtime/mysql-integration.opt-in.run.ts && tsx tests/db-runtime/mongodb-integration.opt-in.run.ts && tsx tests/db-runtime/dynamodb-integration.opt-in.run.ts",
15
+ "test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts && tsx tests/exporter/run.ts && tsx tests/exporter/feature-parser-category.run.ts && tsx tests/exporter/api-detail-sheet.run.ts && tsx tests/exporter/overview-sheet.run.ts && tsx tests/exporter/delivery-divider-tcid.run.ts && tsx tests/exporter/note-expected-actual.run.ts && tsx tests/exporter/test-data-vars.run.ts && tsx tests/exporter/mobile-app-id.run.ts && tsx tests/exporter/api-testcase-cells.run.ts && tsx tests/exporter/delivery-cases-result.run.ts && tsx tests/exporter/precondition-auth-role.run.ts && tsx tests/exporter/report-builder-parity.run.ts && tsx tests/exporter/delivery-preflight-testdata.run.ts && tsx tests/exporter/delivery-preflight-selectors.run.ts && tsx tests/exporter/delivery-prerun-overview.run.ts && tsx tests/exporter/delivery-locale-env-discovery.run.ts && tsx tests/exporter/manual-testcase-testdata.run.ts && tsx tests/dashboard/api-flows-discovery.run.ts && tsx tests/dashboard/status-results-fallback.run.ts && tsx tests/codegen/verb-ref-masking.run.ts && tsx tests/codegen/table-aria-hidden-locators.run.ts && tsx tests/codegen/steps-base-not-compiled.run.ts && tsx tests/codegen/manual-oracle-gate.run.ts && tsx tests/codegen/locator-value-qualified-assertions.run.ts && tsx tests/codegen/table-match-data-column-mapping.run.ts && tsx tests/codegen/param-binding-native-type.run.ts && tsx tests/codegen/table-row-scope-redeclaration.run.ts && tsx tests/codegen/table-row-label-resolution.run.ts && tsx tests/api-runtime/base-path-url-join.run.ts && tsx tests/api-runtime/file-upload-multipart.run.ts && tsx tests/api-runtime/schema-assertion.run.ts && tsx tests/runtime/test-data-cross-ref.run.ts && tsx tests/runtime/test-data-array-projection.run.ts && tsx tests/runtime/env-secret-interpolation.run.ts && tsx tests/capabilities/run.ts && tsx tests/openapi/run.ts && tsx tests/api-field-coverage/run.ts && tsx tests/packaging/run.ts && tsx tests/generate-hint/run.ts && tsx tests/template-assertion/run.ts && tsx tests/journey/run.ts && tsx tests/harness/serial-cascade.run.ts && tsx tests/ai-skills/cross-assistant-orphan.run.ts && tsx tests/init/codex-mcp-config.run.ts && tsx src/orchestrator/ai-skills/golden-skills.test.ts && tsx tests/db-runtime/sql-placeholder-rewrite.run.ts && tsx tests/db-runtime/fallback-flow-codified.run.ts && tsx tests/db-runtime/cosmos-engine.run.ts && tsx tests/db-runtime/mongodb-engine.run.ts && tsx tests/db-runtime/dynamodb-engine.run.ts && tsx tests/db-runtime/mysql-integration.opt-in.run.ts && tsx tests/db-runtime/mongodb-integration.opt-in.run.ts && tsx tests/db-runtime/dynamodb-integration.opt-in.run.ts",
16
16
  "test:update": "tsx tests/golden/run.ts --update && tsx tests/audit/run.ts --update && tsx tests/ingest/run.ts --update",
17
17
  "prepublishOnly": "npm run build:dashboard && npm run build"
18
18
  },
@@ -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.14",
43
- "@sungen/driver-ui": "3.2.14",
42
+ "@sungen/driver-data-factory": "3.2.15",
43
+ "@sungen/driver-ui": "3.2.15",
44
44
  "chalk": "^5.6.2",
45
45
  "commander": "^14.0.2",
46
46
  "dotenv": "^17.2.3",
@@ -13,6 +13,7 @@ import { parseSpecFile } from '../../exporters/spec-parser';
13
13
  import { loadTestData } from '../../exporters/test-data-resolver';
14
14
  import { loadSelectorKeyMap } from '../../exporters/selector-key-resolver';
15
15
  import { loadPlaywrightReport, resolveResultsPath as resolveResultsPathShared } from '../../exporters/playwright-report-parser';
16
+ import { discoverLocaleVariants } from '../../exporters/locale-variants';
16
17
  import { mergeFeatureAndSpec } from '../../exporters/scenario-merger';
17
18
  import {
18
19
  buildTestCaseRows,
@@ -167,70 +168,11 @@ function resolveResultsPath(cwd: string, target: DeliveryTarget): string | null
167
168
  return resolveResultsPathShared(cwd, generatedDir(cwd, target), target.featureBaseName);
168
169
  }
169
170
 
170
- /**
171
- * A single locale variant of a delivery target.
172
- *
173
- * `locale === ''` denotes the base locale (file `<name>-test-result.json`,
174
- * test-data without overlay). Non-empty values come from
175
- * `<name>-test-result.<locale>.json` files found in the generated directory.
176
- *
177
- * `displayCode` is what we show in sheet names — `BASE_LOCALE.toUpperCase()`
178
- * for base, the locale code uppercased otherwise (e.g. `EN`, `JA`, `EN-US`).
179
- */
180
- interface LocaleVariant {
181
- locale: string; // '' for base, 'en' / 'ja' / 'staging-ja' for variants
182
- displayCode: string; // 'VI' / 'EN' / 'JA' — used in sheet name
183
- resultsPath: string | null;
184
- }
185
-
186
- /**
187
- * Base locale assumed when no `SUNGEN_ENV` and no explicit override.
188
- * Configurable later via `qa/.sungen-config.yaml` or similar — currently
189
- * hardcoded since every existing sungen project uses Vietnamese as the
190
- * source-of-truth `test-data/<feature>.yaml`.
191
- */
192
- const DEFAULT_BASE_LOCALE = 'vi';
193
-
194
- /**
195
- * Discover every locale variant available for a feature by scanning the
196
- * generated directory for `<featureBaseName>-test-result*.json` files.
197
- *
198
- * Result always includes the base (locale = '') as the first entry — even if
199
- * `<name>-test-result.json` doesn't exist, callers still need somewhere to
200
- * fall back to (Pending status). Variants follow alphabetically by locale
201
- * code, so the sheet order is deterministic across runs.
202
- */
203
- function discoverLocaleVariants(cwd: string, target: DeliveryTarget): LocaleVariant[] {
204
- const genDir = generatedDir(cwd, target);
205
- const prefix = `${target.featureBaseName}-test-result`;
206
- const variants: LocaleVariant[] = [];
207
-
208
- // Base variant: per-target result file if present, else fall back to the global
209
- // test-results/results.json (what playwright.config writes by default) via resolveResultsPath.
210
- variants.push({
211
- locale: '',
212
- displayCode: DEFAULT_BASE_LOCALE.toUpperCase(),
213
- resultsPath: resolveResultsPath(cwd, target),
214
- });
215
-
216
- if (fs.existsSync(genDir)) {
217
- const localeFiles = fs.readdirSync(genDir)
218
- .filter((f) => f.startsWith(`${prefix}.`) && f.endsWith('.json') && f !== `${prefix}.json`)
219
- .sort();
220
- for (const f of localeFiles) {
221
- // Strip prefix + '.' on the left, '.json' on the right → locale code.
222
- const locale = f.slice(prefix.length + 1, -'.json'.length);
223
- if (!locale) continue;
224
- variants.push({
225
- locale,
226
- displayCode: locale.toUpperCase(),
227
- resultsPath: path.join(genDir, f),
228
- });
229
- }
230
- }
231
-
232
- return variants;
233
- }
171
+ // Locale/env variant discovery is SHARED with the dashboard snapshot builder —
172
+ // see exporters/locale-variants.ts for the classification rules (declared
173
+ // locales via qa/capabilities.yaml, env pairing, mobile OS exemption). The two
174
+ // surfaces previously hand-mirrored this logic and drifted into the
175
+ // fake-locale bug (any env-suffixed result file became a "locale" sheet).
234
176
 
235
177
  function resolveTestDataPathForTarget(cwd: string, target: DeliveryTarget): string {
236
178
  return path.join(qaDir(cwd, target), 'test-data', `${target.featureBaseName}.yaml`);
@@ -522,7 +464,17 @@ async function exportTarget(
522
464
  return buildSummary(label, rows, path.relative(cwd, csvPath));
523
465
  }
524
466
 
525
- const variants = discoverLocaleVariants(cwd, target);
467
+ const { variants, ignored } = discoverLocaleVariants(
468
+ cwd, generatedDir(cwd, target), target.featureBaseName,
469
+ () => resolveResultsPath(cwd, target),
470
+ );
471
+ if (ignored.length > 0) {
472
+ const env = process.env.SUNGEN_ENV;
473
+ log(` ${COLOR.gray}Ignored result file(s) from other environments: ${ignored.join(', ')}${COLOR.reset}`);
474
+ for (const suffix of ignored) {
475
+ log(` ${COLOR.cyan}→ sungen delivery ${target.screen} --env ${suffix}${COLOR.reset}${env ? '' : ` ${COLOR.gray}(this run uses the base results only)${COLOR.reset}`}`);
476
+ }
477
+ }
526
478
 
527
479
  // Mobile: emit ONE deliverable per OS (csv + xlsx), each from its own
528
480
  // `<feature>-test-result.<os>.json`. Android/iOS are SEPARATE platform runs,
@@ -542,7 +494,11 @@ async function exportTarget(
542
494
  featureName: feature.featureName,
543
495
  featurePath: resolvePlatformAppId(featurePath, variant.locale), // OS-precise app id
544
496
  merged,
545
- testData: loadTestData(testDataFile, variant.locale || null),
497
+ // Overlay = the after-OS tail (what SUNGEN_ENV was during that run):
498
+ // `android.ja` merged <name>.ja.yaml at runtime — the old code passed the
499
+ // full `android.ja` suffix, looked up a nonexistent overlay, and silently
500
+ // showed base-language values in the Test Data column.
501
+ testData: loadTestData(testDataFile, variant.overlay ?? null),
546
502
  results: variant.resultsPath ? loadPlaywrightReport(variant.resultsPath) : null,
547
503
  env,
548
504
  selectorKeyMap,
@@ -579,9 +535,11 @@ async function exportTarget(
579
535
  const multiLocale = variants.length > 1;
580
536
 
581
537
  for (const variant of variants) {
582
- // For the base variant the overlay merge is skipped (`locale: null`);
583
- // for locale variants the matching `<feature>.<locale>.yaml` is merged.
584
- const variantTestData = loadTestData(testDataFile, variant.locale || null);
538
+ // Overlay parity with the RUNTIME: merge exactly what TestDataLoader merged
539
+ // during that run (the run's SUNGEN_ENV) the base variant under --env dev
540
+ // merges <feature>.dev.yaml, a ja variant merges <feature>.ja.yaml, plain
541
+ // base merges nothing.
542
+ const variantTestData = loadTestData(testDataFile, variant.overlay ?? null);
585
543
  const variantResults = variant.resultsPath ? loadPlaywrightReport(variant.resultsPath) : null;
586
544
  const variantRows = buildTestCaseRows({
587
545
  screen: label,
@@ -713,8 +671,12 @@ export function registerDeliveryCommand(program: Command): void {
713
671
  .argument('[names...]', 'Specific screen or flow names. Omit to process all.')
714
672
  .option('--skip-preflight', 'Skip pre-flight checks (not recommended)')
715
673
  .option('--continue-on-missing', 'Skip targets with blocking misses instead of aborting')
716
- .action(async (names: string[], options: { skipPreflight?: boolean; continueOnMissing?: boolean }) => {
674
+ .option('--env <env>', 'Environment/locale of the run to deliver (sets SUNGEN_ENV; e.g. dev, staging, ja, dev-ja)')
675
+ .action(async (names: string[], options: { skipPreflight?: boolean; continueOnMissing?: boolean; env?: string }) => {
717
676
  try {
677
+ // Same effect as running with SUNGEN_ENV=<env> — result-file resolution,
678
+ // locale pairing, and test-data overlays all key off this one string.
679
+ if (options.env) process.env.SUNGEN_ENV = options.env;
718
680
  const cwd = process.cwd();
719
681
 
720
682
  // 1. Scope detection — each positional name expands into one target
@@ -25,6 +25,7 @@ import { buildScreenSnapshot } from '../exporters/json-exporter';
25
25
  import { loadApiCatalog } from '../exporters/api-catalog-loader';
26
26
  import { buildApiDetailRows } from '../exporters/xlsx-exporter';
27
27
  import { resolvePlatformAppId } from '../exporters/mobile-app-id';
28
+ import { discoverLocaleVariants, LocaleVariant } from '../exporters/locale-variants';
28
29
  import { getPackageVersion } from '../exporters/package-info';
29
30
  import { ApiCatalogEntry, EnvironmentInfo } from '../exporters/types';
30
31
  import {
@@ -38,11 +39,10 @@ import {
38
39
  SNAPSHOT_VERSION,
39
40
  } from './types';
40
41
 
41
- /**
42
- * Locale code displayed when a screen has no overlay variants — the base
43
- * test-data file alone. Matches the delivery CLI's `DEFAULT_BASE_LOCALE`.
44
- */
45
- const DEFAULT_BASE_LOCALE = 'vi';
42
+ // Locale/env variant discovery is SHARED with the delivery CLI — see
43
+ // exporters/locale-variants.ts (declared locales, env pairing, mobile OS
44
+ // exemption). Previously a hand-mirrored copy that drifted into the
45
+ // fake-locale bug.
46
46
 
47
47
  export interface DashboardTarget {
48
48
  name: string;
@@ -217,13 +217,16 @@ function buildOneFeature(
217
217
  // Discover locale variants by scanning <feature>-test-result*.json files.
218
218
  // Always includes base ('') as the first entry, even if its results file
219
219
  // is missing — UI still needs to render the feature.
220
- const variants = discoverLocaleVariants(cwd, genBase, featureBaseName);
220
+ const { variants } = discoverLocaleVariants(
221
+ cwd, genBase, featureBaseName,
222
+ () => resolveResultsPath(cwd, genBase, featureBaseName),
223
+ );
221
224
 
222
225
  // Build one per-variant ScreenSnapshot (test-data overlay + results + OS-precise
223
226
  // env column). Reused by both the web/i18n (locale-axis) and mobile (platform-axis) paths.
224
- const buildVariant = (variant: FeatureLocaleVariant) => {
227
+ const buildVariant = (variant: LocaleVariant) => {
225
228
  const testData = fs.existsSync(testDataFile)
226
- ? loadTestData(testDataFile, variant.locale || null)
229
+ ? loadTestData(testDataFile, variant.overlay ?? null)
227
230
  : {};
228
231
  const results = variant.resultsPath ? loadPlaywrightReport(variant.resultsPath) : null;
229
232
  return buildScreenSnapshot({
@@ -341,59 +344,6 @@ function buildOneFeature(
341
344
  }];
342
345
  }
343
346
 
344
- /**
345
- * A single locale variant of a feature.
346
- * `locale === ''` denotes the base (file `<name>-test-result.json`,
347
- * test-data without overlay merge). Variants come from
348
- * `<name>-test-result.<locale>.json` filenames.
349
- */
350
- interface FeatureLocaleVariant {
351
- locale: string;
352
- displayCode: string;
353
- resultsPath: string | null;
354
- }
355
-
356
- /**
357
- * Scan the generated directory for `<basename>-test-result*.json` files
358
- * and infer locale codes. The base entry is always returned first; locale
359
- * variants follow alphabetically so sheet/tab order stays deterministic.
360
- *
361
- * Mirrors `discoverLocaleVariants` in `src/cli/commands/delivery.ts` so the
362
- * dashboard and the CSV/XLSX delivery agree on what locales exist for a
363
- * given feature.
364
- */
365
- function discoverLocaleVariants(cwd: string, genDir: string, featureBaseName: string): FeatureLocaleVariant[] {
366
- const prefix = `${featureBaseName}-test-result`;
367
- const variants: FeatureLocaleVariant[] = [];
368
-
369
- // Base variant resolves through the SHARED candidate chain (per-feature file
370
- // first, then the global test-results/results.json playwright writes by
371
- // default) — the same resolution delivery.ts uses. Without the fallback the
372
- // dashboard showed every scenario Pending on projects that only have the
373
- // global results file, while delivery correctly reported Passed.
374
- variants.push({
375
- locale: '',
376
- displayCode: DEFAULT_BASE_LOCALE.toUpperCase(),
377
- resultsPath: resolveResultsPath(cwd, genDir, featureBaseName),
378
- });
379
-
380
- if (fs.existsSync(genDir)) {
381
- const localeFiles = fs.readdirSync(genDir)
382
- .filter((f) => f.startsWith(`${prefix}.`) && f.endsWith('.json') && f !== `${prefix}.json`)
383
- .sort();
384
- for (const f of localeFiles) {
385
- const locale = f.slice(prefix.length + 1, -'.json'.length);
386
- if (!locale) continue;
387
- variants.push({
388
- locale,
389
- displayCode: locale.toUpperCase(),
390
- resultsPath: path.join(genDir, f),
391
- });
392
- }
393
- }
394
-
395
- return variants;
396
- }
397
347
 
398
348
  /**
399
349
  * Combine per-feature summaries into a single screen-level rollup.