@sun-asterisk/sungen 3.1.2-beta.119 → 3.1.2-beta.121

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 (38) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +33 -33
  3. package/dist/cli/commands/delivery.js.map +1 -1
  4. package/dist/cli/commands/ledger.d.ts.map +1 -1
  5. package/dist/cli/commands/ledger.js +13 -5
  6. package/dist/cli/commands/ledger.js.map +1 -1
  7. package/dist/cli/commands/manifest.d.ts.map +1 -1
  8. package/dist/cli/commands/manifest.js +9 -9
  9. package/dist/cli/commands/manifest.js.map +1 -1
  10. package/dist/cli/commands/script-check.d.ts.map +1 -1
  11. package/dist/cli/commands/script-check.js +10 -8
  12. package/dist/cli/commands/script-check.js.map +1 -1
  13. package/dist/cli/commands/trace.d.ts.map +1 -1
  14. package/dist/cli/commands/trace.js +6 -4
  15. package/dist/cli/commands/trace.js.map +1 -1
  16. package/dist/harness/audit.js +1 -1
  17. package/dist/harness/audit.js.map +1 -1
  18. package/dist/harness/intent.d.ts +3 -0
  19. package/dist/harness/intent.d.ts.map +1 -1
  20. package/dist/harness/intent.js +11 -2
  21. package/dist/harness/intent.js.map +1 -1
  22. package/dist/harness/script-check.d.ts +3 -1
  23. package/dist/harness/script-check.d.ts.map +1 -1
  24. package/dist/harness/script-check.js +16 -7
  25. package/dist/harness/script-check.js.map +1 -1
  26. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +1 -1
  27. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +1 -1
  28. package/package.json +2 -2
  29. package/src/cli/commands/delivery.ts +32 -33
  30. package/src/cli/commands/ledger.ts +11 -5
  31. package/src/cli/commands/manifest.ts +8 -7
  32. package/src/cli/commands/script-check.ts +9 -7
  33. package/src/cli/commands/trace.ts +6 -4
  34. package/src/harness/audit.ts +2 -2
  35. package/src/harness/intent.ts +13 -2
  36. package/src/harness/script-check.ts +20 -7
  37. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +1 -1
  38. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/harness/intent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,4DAEC;AAED,gCAoBC;AAzDD;;;;;;;;;;;;;GAaG;AACH,uCAAyB;AACzB,2CAA6B;AAW7B,MAAM,cAAc,GAAkB;IACpC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS;CAC9E,CAAC;AAEF,MAAM,IAAI,GAAkB,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AAE9E,yEAAyE;AACzE,SAAgB,wBAAwB,CAAC,SAAiB;IACxD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,SAAgB,UAAU,CAAC,WAAmB;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,cAAc,CAAC;IAC/C,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QAAC,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,cAAc,CAAC;IAAC,CAAC;IAE5F,MAAM,IAAI,GAAG,CAAC,GAAW,EAAsB,EAAE;QAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,gBAAgB,GAAG,uBAAuB,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAuB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAgB,CAAC;IACxG,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAA8B,CAAC;IACpI,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAA+B,CAAC;IAElI,MAAM,KAAK,GAAG,QAAQ,IAAI,IAAI,IAAI,KAAK,CAAC;IACxC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAClF,CAAC"}
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/harness/intent.ts"],"names":[],"mappings":"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"}
@@ -35,5 +35,7 @@ export declare function analyzeFaithfulness(specSrc: string, automatedTitles: Se
35
35
  step: string;
36
36
  }[];
37
37
  };
38
- export declare function runScriptCheck(screenDir: string, screenName: string, flowMode: boolean): Promise<ScriptCheckResult>;
38
+ /** The unit kind drives the generated-spec subdir + the qa source dir. */
39
+ export type UnitKind = 'screen' | 'flow' | 'api';
40
+ export declare function runScriptCheck(screenDir: string, screenName: string, kind: UnitKind): Promise<ScriptCheckResult>;
39
41
  //# sourceMappingURL=script-check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"script-check.d.ts","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAgBtF;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC;;;cAEpD,MAAM;cAAQ,MAAM;;EAqBhD;AA0CD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkGzH"}
1
+ {"version":3,"file":"script-check.d.ts","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAgBtF;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC;;;cAEpD,MAAM;cAAQ,MAAM;;EAqBhD;AAqBD,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AA6BjD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsGtH"}
@@ -134,9 +134,14 @@ function normalize(src) {
134
134
  .replace(/\n{3,}/g, '\n\n')
135
135
  .trim();
136
136
  }
137
- function findSpec(dir, name, flowMode) {
137
+ /** Generated-spec subdir for a unit: screen → <name>, flow → flows/<name>, api → api/<name>. */
138
+ function specSubdir(dir, name, kind) {
139
+ return kind === 'flow' ? path.join(dir, 'flows', name) : kind === 'api' ? path.join(dir, 'api', name) : path.join(dir, name);
140
+ }
141
+ function findSpec(dir, name, kind) {
138
142
  // Screens compile to <dir>/<name>/<feature>.spec.ts
139
143
  // Flows compile to <dir>/flows/<name>/<feature>.spec.ts
144
+ // Api compile to <dir>/api/<name>/<feature>.spec.ts
140
145
  // Scope the search to THIS target's own subdir — otherwise the first spec of
141
146
  // ANY other screen/flow is returned, which (for an uncompiled flow) falsely
142
147
  // reports the wrong screen's tests as drift.
@@ -152,18 +157,18 @@ function findSpec(dir, name, flowMode) {
152
157
  hits.push(p);
153
158
  }
154
159
  };
155
- const scoped = flowMode ? path.join(dir, 'flows', name) : path.join(dir, name);
160
+ const scoped = specSubdir(dir, name, kind);
156
161
  if (!fs.existsSync(scoped))
157
162
  return null; // no spec for this target (e.g. not compiled yet)
158
163
  walk(scoped);
159
164
  return hits[0] ?? null;
160
165
  }
161
- async function runScriptCheck(screenDir, screenName, flowMode) {
166
+ async function runScriptCheck(screenDir, screenName, kind) {
162
167
  const featurePath = path.join(screenDir, 'features', `${screenName}.feature`);
163
168
  const scenarios = (0, parse_1.loadScenarios)(featurePath);
164
169
  const automated = scenarios.filter((s) => !s.manual);
165
170
  const manual = scenarios.filter((s) => s.manual);
166
- const committedSpec = findSpec(path.join(process.cwd(), 'specs', 'generated'), screenName, flowMode);
171
+ const committedSpec = findSpec(path.join(process.cwd(), 'specs', 'generated'), screenName, kind);
167
172
  const findings = [];
168
173
  let specTitles = [];
169
174
  let specSrc = '';
@@ -197,10 +202,14 @@ async function runScriptCheck(screenDir, screenName, flowMode) {
197
202
  try {
198
203
  const { CodeGenerator } = require('../generators/test-generator/code-generator');
199
204
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sungen-scriptcheck-'));
200
- const qaSourceDir = path.join(process.cwd(), 'qa', flowMode ? 'flows' : 'screens');
201
- const gen = new CodeGenerator({ framework: 'playwright', screenName, runtimeData: true, flowMode });
205
+ const qaSourceDir = path.join(process.cwd(), 'qa', kind === 'flow' ? 'flows' : kind === 'api' ? 'api' : 'screens');
206
+ // api units derive their unit id (api/<area>) from the feature path like `generate --api`;
207
+ // screen/flow pass screenName + flowMode explicitly (unchanged → byte-identical regenerate).
208
+ const gen = kind === 'api'
209
+ ? new CodeGenerator({ framework: 'playwright', runtimeData: true })
210
+ : new CodeGenerator({ framework: 'playwright', screenName, runtimeData: true, flowMode: kind === 'flow' });
202
211
  await gen.generateAllTests(qaSourceDir, tmp, [featurePath]);
203
- const fresh = findSpec(tmp, screenName, flowMode);
212
+ const fresh = findSpec(tmp, screenName, kind);
204
213
  if (fresh) {
205
214
  const a = normalize(specSrc);
206
215
  const b = normalize(fs.readFileSync(fresh, 'utf-8'));
@@ -1 +1 @@
1
- {"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"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"}
@@ -45,7 +45,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
45
45
  - **missing/empty bound param** → trace `{{var}}` to test-data or a prior `@api` response; fill it.
46
46
  - **`expect.status` mismatch** → reconcile against `apis.yaml`/spec (the catalog is the oracle); **never hand-edit the generated spec** (re-`generate --api` instead).
47
47
  - **flaky** → enforce self-cleaning flows, per-row isolation (`@cases`), `@concurrent` caps.
48
- 5. **Report** results + the HUMAN-LOOP FOCUS, then offer next steps. *(1:1 `script-check` + `trace` for api units land in a follow-up; for now confirm the run + re-`sungen audit --api <name>` if scenarios changed.)*
48
+ 5. **Integrity + trace** `sungen script-check --api <name>` (verify the spec is a 1:1 of the Gherkin; on DRIFT re-`generate --api`, never hand-edit) and `sungen trace --api <name>` (process map + HUMAN-LOOP FOCUS). Then report + offer next steps.
49
49
 
50
50
  ## Pre-run (phased — per `sungen-selector-fix` skill)
51
51
 
@@ -39,7 +39,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
39
39
  2. **Compile**: `npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
40
40
  3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts`.
41
41
  4. **Auto-fix** (use `sungen-error-mapping`): 401/403 → `@hybrid`+`@auth` or `Bearer :token` header (`sungen makeauth`); base_url unresolved → set `${X_URL}`; missing param → trace `{{var}}` to test-data/a prior `@api` response; `expect.status` mismatch → reconcile against `apis.yaml` (re-`generate --api`, never hand-edit the spec); flaky → self-clean + `@concurrent` caps.
42
- 5. **Report** results + the HUMAN-LOOP FOCUS. *(1:1 `script-check`/`trace` for api units land in a follow-up.)*
42
+ 5. **Integrity + trace** `sungen script-check --api <name>` (1:1; on DRIFT re-`generate --api`, never hand-edit the spec) + `sungen trace --api <name>` (process map + HUMAN-LOOP FOCUS). Report + offer next steps.
43
43
 
44
44
  ## Pre-run (phased — per `sungen-selector-fix` skill)
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sungen",
3
- "version": "3.1.2-beta.119",
3
+ "version": "3.1.2-beta.121",
4
4
  "description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -33,7 +33,7 @@
33
33
  "node": ">=18.0.0"
34
34
  },
35
35
  "dependencies": {
36
- "@sungen/driver-ui": "3.1.2-beta.119",
36
+ "@sungen/driver-ui": "3.1.2-beta.121",
37
37
  "@anthropic-ai/sdk": "^0.71.0",
38
38
  "@babel/parser": "^7.28.5",
39
39
  "@babel/traverse": "^7.28.5",
@@ -52,47 +52,49 @@ function log(msg: string): void {
52
52
  * `name` is kept as an alias of `featureBaseName` so existing callers/labels
53
53
  * (preflight table, summary) read naturally — every visible row is per-feature.
54
54
  */
55
+ type UnitKind = 'screen' | 'flow' | 'api';
56
+ /** qa/ subfolder for a unit kind. */
57
+ const qaParent = (kind: UnitKind): string => (kind === 'flow' ? 'flows' : kind === 'api' ? 'api' : 'screens');
58
+
55
59
  interface DeliveryTarget {
56
60
  screen: string;
57
61
  featureBaseName: string;
58
62
  /** Alias of `featureBaseName` — preserves the old `target.name` call sites. */
59
63
  name: string;
64
+ kind: UnitKind;
65
+ /** Back-compat: flows kept distinct labels/paths before api was added. */
60
66
  isFlow: boolean;
61
67
  }
62
68
 
63
- function makeTarget(screen: string, featureBaseName: string, isFlow: boolean): DeliveryTarget {
64
- return { screen, featureBaseName, name: featureBaseName, isFlow };
69
+ function makeTarget(screen: string, featureBaseName: string, kind: UnitKind): DeliveryTarget {
70
+ return { screen, featureBaseName, name: featureBaseName, kind, isFlow: kind === 'flow' };
65
71
  }
66
72
 
67
73
  /**
68
- * List all `.feature` files inside a screen/flow as separate targets.
74
+ * List all `.feature` files inside a screen/flow/api unit as separate targets.
69
75
  * Returns empty array when the directory has no features yet.
70
76
  */
71
- function listFeatureTargets(cwd: string, screen: string, isFlow: boolean): DeliveryTarget[] {
72
- const featuresDir = path.join(cwd, 'qa', isFlow ? 'flows' : 'screens', screen, 'features');
77
+ function listFeatureTargets(cwd: string, screen: string, kind: UnitKind): DeliveryTarget[] {
78
+ const featuresDir = path.join(cwd, 'qa', qaParent(kind), screen, 'features');
73
79
  if (!fs.existsSync(featuresDir)) return [];
74
80
  return fs.readdirSync(featuresDir)
75
81
  .filter((f) => f.endsWith('.feature'))
76
- .map((f) => makeTarget(screen, f.slice(0, -'.feature'.length), isFlow))
82
+ .map((f) => makeTarget(screen, f.slice(0, -'.feature'.length), kind))
77
83
  .sort((a, b) => a.featureBaseName.localeCompare(b.featureBaseName));
78
84
  }
79
85
 
80
86
  function listAllTargets(cwd: string): DeliveryTarget[] {
81
87
  const targets: DeliveryTarget[] = [];
82
-
83
- const screensDir = path.join(cwd, 'qa', 'screens');
84
- if (fs.existsSync(screensDir)) {
85
- for (const d of fs.readdirSync(screensDir, { withFileTypes: true })) {
86
- if (d.isDirectory()) targets.push(...listFeatureTargets(cwd, d.name, false));
87
- }
88
- }
89
-
90
- const flowsDir = path.join(cwd, 'qa', 'flows');
91
- if (fs.existsSync(flowsDir)) {
92
- for (const d of fs.readdirSync(flowsDir, { withFileTypes: true })) {
93
- if (d.isDirectory()) targets.push(...listFeatureTargets(cwd, d.name, true));
88
+ const scan = (kind: UnitKind, skip: (n: string) => boolean = () => false) => {
89
+ const root = path.join(cwd, 'qa', qaParent(kind));
90
+ if (!fs.existsSync(root)) return;
91
+ for (const d of fs.readdirSync(root, { withFileTypes: true })) {
92
+ if (d.isDirectory() && !skip(d.name)) targets.push(...listFeatureTargets(cwd, d.name, kind));
94
93
  }
95
- }
94
+ };
95
+ scan('screen');
96
+ scan('flow');
97
+ scan('api', (n) => n === 'flows'); // qa/api/<area> (api flows live under qa/api/flows — a follow-up)
96
98
 
97
99
  return targets.sort((a, b) => a.featureBaseName.localeCompare(b.featureBaseName));
98
100
  }
@@ -108,28 +110,24 @@ function listAllTargets(cwd: string): DeliveryTarget[] {
108
110
  * feature file with the basename across all screens & flows.
109
111
  */
110
112
  function resolveTargetsFromArg(cwd: string, name: string): DeliveryTarget[] {
111
- if (fs.existsSync(path.join(cwd, 'qa', 'flows', name))) {
112
- return listFeatureTargets(cwd, name, true);
113
- }
114
- if (fs.existsSync(path.join(cwd, 'qa', 'screens', name))) {
115
- return listFeatureTargets(cwd, name, false);
116
- }
117
- // Treat as feature basename — find the parent screen/flow that hosts it.
113
+ if (fs.existsSync(path.join(cwd, 'qa', 'flows', name))) return listFeatureTargets(cwd, name, 'flow');
114
+ if (fs.existsSync(path.join(cwd, 'qa', 'screens', name))) return listFeatureTargets(cwd, name, 'screen');
115
+ if (fs.existsSync(path.join(cwd, 'qa', 'api', name))) return listFeatureTargets(cwd, name, 'api');
116
+ // Treat as feature basename — find the parent unit that hosts it.
118
117
  const candidates = listAllTargets(cwd).filter((t) => t.featureBaseName === name);
119
118
  if (candidates.length > 0) return candidates;
120
119
  // Fallback: treat as screen name even if directory missing (lets preflight
121
120
  // surface the "feature file missing" error with the right path).
122
- return [makeTarget(name, name, false)];
121
+ return [makeTarget(name, name, 'screen')];
123
122
  }
124
123
 
125
124
  function qaDir(cwd: string, target: DeliveryTarget): string {
126
- return path.join(cwd, 'qa', target.isFlow ? 'flows' : 'screens', target.screen);
125
+ return path.join(cwd, 'qa', qaParent(target.kind), target.screen);
127
126
  }
128
127
 
129
128
  function generatedDir(cwd: string, target: DeliveryTarget): string {
130
- return target.isFlow
131
- ? path.join(cwd, 'specs', 'generated', 'flows', target.screen)
132
- : path.join(cwd, 'specs', 'generated', target.screen);
129
+ const sub = target.kind === 'flow' ? path.join('flows', target.screen) : target.kind === 'api' ? path.join('api', target.screen) : target.screen;
130
+ return path.join(cwd, 'specs', 'generated', sub);
133
131
  }
134
132
 
135
133
  // ----------------------------------------------------------------------------
@@ -262,7 +260,8 @@ function runPreflight(cwd: string, target: DeliveryTarget): PreflightCheck {
262
260
 
263
261
  const featureOk = checkFeatureReal(featureFile);
264
262
  const testDataOk = checkTestDataHasVars(testDataFile);
265
- const selectorsOk = checkSelectorsHasEntries(selectorsFile, target.featureBaseName);
263
+ // API units have no DOM → no selectors; the catalog (apis.yaml) is the contract. N/A, not missing.
264
+ const selectorsOk = target.kind === 'api' ? true : checkSelectorsHasEntries(selectorsFile, target.featureBaseName);
266
265
  const specOk = fs.existsSync(specFile);
267
266
  const resultsOk = resultsFile !== null;
268
267
 
@@ -284,7 +283,7 @@ function runPreflight(cwd: string, target: DeliveryTarget): PreflightCheck {
284
283
  }
285
284
  if (!specOk) {
286
285
  missing.push(`compiled .spec.ts missing: ${path.relative(cwd, specFile)}`);
287
- suggestions.push(target.isFlow ? `sungen generate --flow ${target.screen}` : `sungen generate --screen ${target.screen}`);
286
+ suggestions.push(`sungen generate --${target.kind === 'flow' ? 'flow' : target.kind === 'api' ? 'api' : 'screen'} ${target.screen}`);
288
287
  }
289
288
  if (!resultsOk) {
290
289
  const env = process.env.SUNGEN_ENV;
@@ -9,7 +9,8 @@ export function registerLedgerCommand(program: Command): void {
9
9
  ledger
10
10
  .command('record')
11
11
  .description('Append a step event to the ledger')
12
- .requiredOption('-s, --screen <name>', 'Screen or flow name')
12
+ .option('-s, --screen <name>', 'Screen or flow name')
13
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
13
14
  .requiredOption('--step <name>', 'Step name (discovery | viewpoint | gherkin | audit | repair:1 ...)')
14
15
  .option('--run <id>', 'Run id — groups all phases of one create-test invocation (else auto-segmented by time gap)')
15
16
  .option('--model <id>', 'Model id')
@@ -19,10 +20,12 @@ export function registerLedgerCommand(program: Command): void {
19
20
  .option('--note <text>', 'Free note')
20
21
  .action((o) => {
21
22
  try {
22
- recordEvent(o.screen, {
23
+ const name = o.screen || o.api;
24
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
25
+ recordEvent(name, {
23
26
  step: o.step, runId: o.run, model: o.model, tokensIn: o.tokensIn, tokensOut: o.tokensOut, ms: o.ms, note: o.note,
24
27
  });
25
- console.log(`✓ ledger: ${o.screen} · ${o.step}`);
28
+ console.log(`✓ ledger: ${name} · ${o.step}`);
26
29
  } catch (e) {
27
30
  console.error('Error:', e instanceof Error ? e.message : e);
28
31
  process.exit(1);
@@ -32,12 +35,15 @@ export function registerLedgerCommand(program: Command): void {
32
35
  ledger
33
36
  .command('report')
34
37
  .description('Summarise ledger + efficiency verdicts (pulls audit score if present)')
35
- .requiredOption('-s, --screen <name>', 'Screen or flow name')
38
+ .option('-s, --screen <name>', 'Screen or flow name')
39
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
36
40
  .option('--all-runs', 'Aggregate ALL runs (default: latest run only)')
37
41
  .option('--json', 'Output raw JSON')
38
42
  .action((o) => {
39
43
  try {
40
- const r = buildReport(o.screen, { allRuns: o.allRuns });
44
+ const name = o.screen || o.api;
45
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
46
+ const r = buildReport(name, { allRuns: o.allRuns });
41
47
  if (o.json) { console.log(JSON.stringify(r, null, 2)); return; }
42
48
  const scope = r.runScope === 'all' ? `all ${r.runs} runs` : `latest run${r.runs > 1 ? ` of ${r.runs}` : ''}`;
43
49
  console.log(`\n━━━ Usage Ledger: ${r.screen} (${r.events} events · ${scope}) ━━━`);
@@ -4,10 +4,10 @@ import * as fs from 'fs';
4
4
  import { buildManifest, diffManifest, loadManifest, saveManifest } from '../../harness/manifest';
5
5
 
6
6
  function findScreenDir(name: string): string | null {
7
- const screen = path.join(process.cwd(), 'qa', 'screens', name);
8
- if (fs.existsSync(screen)) return screen;
9
- const flow = path.join(process.cwd(), 'qa', 'flows', name);
10
- if (fs.existsSync(flow)) return flow;
7
+ for (const p of ['screens', 'flows', 'api']) {
8
+ const d = path.join(process.cwd(), 'qa', p, name);
9
+ if (fs.existsSync(d)) return d;
10
+ }
11
11
  return null;
12
12
  }
13
13
 
@@ -16,14 +16,15 @@ export function registerManifestCommand(program: Command): void {
16
16
  .command('manifest')
17
17
  .description('Spec-fingerprint manifest: build a scenario↔spec-section map, or diff to plan keep/regenerate/retire')
18
18
  .option('-s, --screen <name>', 'Screen or flow name')
19
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
19
20
  .option('--diff', 'Compare current spec vs stored manifest → change plan')
20
21
  .option('--json', 'Output raw JSON')
21
22
  .action((options) => {
22
23
  try {
23
- const name = options.screen;
24
- if (!name) throw new Error('Provide --screen <name>');
24
+ const name = options.screen || options.api;
25
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
25
26
  const dir = findScreenDir(name);
26
- if (!dir) throw new Error(`Screen/flow not found: ${name}`);
27
+ if (!dir) throw new Error(`Not found: qa/screens|flows|api/${name}`);
27
28
 
28
29
  if (options.diff) {
29
30
  const manifest = loadManifest(name);
@@ -8,18 +8,20 @@ export function registerScriptCheckCommand(program: Command): void {
8
8
  .command('script-check')
9
9
  .description('Verify the generated Playwright spec is a faithful 1:1 of the Gherkin feature (no hand-edit / stale drift)')
10
10
  .option('-s, --screen <name>', 'Screen or flow name')
11
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
11
12
  .option('--json', 'Output raw JSON')
12
13
  .action(async (options) => {
13
14
  try {
14
- const name = options.screen;
15
- if (!name) throw new Error('Provide --screen <name>');
15
+ const name = options.screen || options.api;
16
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
16
17
  const screen = path.join(process.cwd(), 'qa', 'screens', name);
17
18
  const flow = path.join(process.cwd(), 'qa', 'flows', name);
18
- const flowMode = !fs.existsSync(screen) && fs.existsSync(flow);
19
- const dir = fs.existsSync(screen) ? screen : (fs.existsSync(flow) ? flow : null);
20
- if (!dir) throw new Error(`Screen/flow not found: ${name}`);
19
+ const api = path.join(process.cwd(), 'qa', 'api', name);
20
+ const kind = fs.existsSync(screen) ? 'screen' : fs.existsSync(flow) ? 'flow' : fs.existsSync(api) ? 'api' : null;
21
+ const dir = kind === 'screen' ? screen : kind === 'flow' ? flow : kind === 'api' ? api : null;
22
+ if (!dir || !kind) throw new Error(`Not found: qa/screens|flows|api/${name}`);
21
23
 
22
- const r = await runScriptCheck(dir, name, flowMode);
24
+ const r = await runScriptCheck(dir, name, kind);
23
25
 
24
26
  const outDir = path.join(process.cwd(), '.sungen', 'reports');
25
27
  fs.mkdirSync(outDir, { recursive: true });
@@ -39,7 +41,7 @@ export function registerScriptCheckCommand(program: Command): void {
39
41
  if (r.findings.length) { L(' findings:'); for (const f of r.findings) L(` • ${f}`); }
40
42
  else L(' ✓ The test code faithfully reflects the Gherkin (1:1).');
41
43
  L('');
42
- if (r.drift === 'drift') L(' → Fix: re-run `sungen generate --screen ' + name + '` (or /sungen:run-test) so the spec matches the feature. Never hand-edit generated specs.');
44
+ if (r.drift === 'drift') L(` → Fix: re-run \`sungen generate --${kind === 'api' ? 'api' : kind === 'flow' ? 'flow' : 'screen'} ${name}\` (or /sungen:run-test) so the spec matches the feature. Never hand-edit generated specs.`);
43
45
  L('');
44
46
  process.exit(r.status === 'OK' ? 0 : 2);
45
47
  } catch (error) {
@@ -8,16 +8,18 @@ export function registerTraceCommand(program: Command): void {
8
8
  .command('trace')
9
9
  .description('Visualise the executed test-design process (workflow/skill steps, repair loops), find bottlenecks, and show where to focus human review')
10
10
  .option('-s, --screen <name>', 'Screen or flow name')
11
+ .option('--api <name>', 'API-first area or api flow (qa/api/<name>)')
11
12
  .option('--json', 'Output raw JSON')
12
13
  .option('--mermaid', 'Print only the Mermaid flowchart')
13
14
  .action((options) => {
14
15
  try {
15
- const name = options.screen;
16
- if (!name) throw new Error('Provide --screen <name>');
16
+ const name = options.screen || options.api;
17
+ if (!name) throw new Error('Provide --screen <name> (or --api <area>)');
17
18
  const screen = path.join(process.cwd(), 'qa', 'screens', name);
18
19
  const flow = path.join(process.cwd(), 'qa', 'flows', name);
19
- const dir = fs.existsSync(screen) ? screen : (fs.existsSync(flow) ? flow : null);
20
- if (!dir) throw new Error(`Screen/flow not found: ${name}`);
20
+ const api = path.join(process.cwd(), 'qa', 'api', name);
21
+ const dir = fs.existsSync(screen) ? screen : fs.existsSync(flow) ? flow : fs.existsSync(api) ? api : null;
22
+ if (!dir) throw new Error(`Not found: qa/screens|flows|api/${name}`);
21
23
 
22
24
  const r = buildTrace(dir, name);
23
25
  if (options.json) { console.log(JSON.stringify(r, null, 2)); return; }
@@ -112,8 +112,8 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
112
112
  // A capability gate may need project context (the API gate resolves endpoint methods from the
113
113
  // catalog) + the focus depth threshold (so it scores depth with the SAME bar as the UI gate).
114
114
  const capGate = scoringCap?.gateProvider as
115
- ((i: { scenarios: ScenarioInfo[]; viewpoints: ViewpointEntry[]; catalog: Catalog; focus: typeof intent.focus; cwd: string; screenName: string; threshold: number }) => { gate: GateResult; depth: DepthResult }) | undefined;
116
- const provided = capGate?.({ scenarios, viewpoints, catalog, focus: intent.focus, cwd: projectRootFromScreenDir(screenDir), screenName: catalogScreenName, threshold: depthThresholdFor(intent.focus) });
115
+ ((i: { scenarios: ScenarioInfo[]; viewpoints: ViewpointEntry[]; catalog: Catalog; focus: typeof intent.focus; cwd: string; screenName: string; threshold: number; businessCriticalMethods?: string[] }) => { gate: GateResult; depth: DepthResult }) | undefined;
116
+ const provided = capGate?.({ scenarios, viewpoints, catalog, focus: intent.focus, cwd: projectRootFromScreenDir(screenDir), screenName: catalogScreenName, threshold: depthThresholdFor(intent.focus), businessCriticalMethods: intent.businessCriticalMethods });
117
117
  const gate = provided?.gate ?? viewpointGate(scenarios, viewpoints, catalog);
118
118
  const depth = provided?.depth ?? assertionDepth(scenarios, dataThemesFor(catalog, gate.pageType), intent.focus);
119
119
  const claim = claimProof(scenarios, intent.focus);
@@ -21,6 +21,9 @@ export interface IntentProfile {
21
21
  focus: IntentFocus;
22
22
  riskTier: 'high' | 'normal' | 'low';
23
23
  tierScope: 'tier-1' | 'full';
24
+ /** End-user override (AO-6): HTTP methods the API gate treats as business-critical (depth-required).
25
+ * Default (undefined → the gate's POST/PUT/PATCH/DELETE) lets a project mark e.g. GET as critical. */
26
+ businessCriticalMethods?: string[];
24
27
  source: 'context.md' | 'default';
25
28
  }
26
29
 
@@ -45,6 +48,13 @@ export function readIntent(projectRoot: string): IntentProfile {
45
48
  const m = text.match(new RegExp(`(?:^|\\n)\\s*${key}\\s*:\\s*([a-z0-9-]+)`));
46
49
  return m?.[1];
47
50
  };
51
+ // A comma/space/slash list (e.g. `business_critical_methods: post, put, patch, delete, get`).
52
+ const grabList = (key: string): string[] | undefined => {
53
+ const m = text.match(new RegExp(`(?:^|\\n)\\s*${key}\\s*:\\s*([a-z0-9,\\s/-]+)`));
54
+ if (!m) return undefined;
55
+ const items = m[1].split(/[,\s/]+/).map((s) => s.trim().toUpperCase()).filter(Boolean);
56
+ return items.length ? items : undefined;
57
+ };
48
58
 
49
59
  const focusRaw = grab('focus');
50
60
  const focus = (FOCI.includes(focusRaw as IntentFocus) ? focusRaw : DEFAULT_INTENT.focus) as IntentFocus;
@@ -53,6 +63,7 @@ export function readIntent(projectRoot: string): IntentProfile {
53
63
  const scope = grab('tier_scope');
54
64
  const tierScope = (['tier-1', 'full'].includes(scope as string) ? scope : DEFAULT_INTENT.tierScope) as IntentProfile['tierScope'];
55
65
 
56
- const found = focusRaw || risk || scope;
57
- return { focus, riskTier, tierScope, source: found ? 'context.md' : 'default' };
66
+ const businessCriticalMethods = grabList('business_critical_methods');
67
+ const found = focusRaw || risk || scope || businessCriticalMethods;
68
+ return { focus, riskTier, tierScope, businessCriticalMethods, source: found ? 'context.md' : 'default' };
58
69
  }
@@ -106,9 +106,18 @@ function normalize(src: string): string {
106
106
  .trim();
107
107
  }
108
108
 
109
- function findSpec(dir: string, name: string, flowMode: boolean): string | null {
109
+ /** The unit kind drives the generated-spec subdir + the qa source dir. */
110
+ export type UnitKind = 'screen' | 'flow' | 'api';
111
+
112
+ /** Generated-spec subdir for a unit: screen → <name>, flow → flows/<name>, api → api/<name>. */
113
+ function specSubdir(dir: string, name: string, kind: UnitKind): string {
114
+ return kind === 'flow' ? path.join(dir, 'flows', name) : kind === 'api' ? path.join(dir, 'api', name) : path.join(dir, name);
115
+ }
116
+
117
+ function findSpec(dir: string, name: string, kind: UnitKind): string | null {
110
118
  // Screens compile to <dir>/<name>/<feature>.spec.ts
111
119
  // Flows compile to <dir>/flows/<name>/<feature>.spec.ts
120
+ // Api compile to <dir>/api/<name>/<feature>.spec.ts
112
121
  // Scope the search to THIS target's own subdir — otherwise the first spec of
113
122
  // ANY other screen/flow is returned, which (for an uncompiled flow) falsely
114
123
  // reports the wrong screen's tests as drift.
@@ -121,19 +130,19 @@ function findSpec(dir: string, name: string, flowMode: boolean): string | null {
121
130
  else if (e.name.endsWith('.spec.ts')) hits.push(p);
122
131
  }
123
132
  };
124
- const scoped = flowMode ? path.join(dir, 'flows', name) : path.join(dir, name);
133
+ const scoped = specSubdir(dir, name, kind);
125
134
  if (!fs.existsSync(scoped)) return null; // no spec for this target (e.g. not compiled yet)
126
135
  walk(scoped);
127
136
  return hits[0] ?? null;
128
137
  }
129
138
 
130
- export async function runScriptCheck(screenDir: string, screenName: string, flowMode: boolean): Promise<ScriptCheckResult> {
139
+ export async function runScriptCheck(screenDir: string, screenName: string, kind: UnitKind): Promise<ScriptCheckResult> {
131
140
  const featurePath = path.join(screenDir, 'features', `${screenName}.feature`);
132
141
  const scenarios = loadScenarios(featurePath);
133
142
  const automated = scenarios.filter((s) => !s.manual);
134
143
  const manual = scenarios.filter((s) => s.manual);
135
144
 
136
- const committedSpec = findSpec(path.join(process.cwd(), 'specs', 'generated'), screenName, flowMode);
145
+ const committedSpec = findSpec(path.join(process.cwd(), 'specs', 'generated'), screenName, kind);
137
146
 
138
147
  const findings: string[] = [];
139
148
  let specTitles: string[] = [];
@@ -167,10 +176,14 @@ export async function runScriptCheck(screenDir: string, screenName: string, flow
167
176
  try {
168
177
  const { CodeGenerator } = require('../generators/test-generator/code-generator');
169
178
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sungen-scriptcheck-'));
170
- const qaSourceDir = path.join(process.cwd(), 'qa', flowMode ? 'flows' : 'screens');
171
- const gen = new CodeGenerator({ framework: 'playwright', screenName, runtimeData: true, flowMode });
179
+ const qaSourceDir = path.join(process.cwd(), 'qa', kind === 'flow' ? 'flows' : kind === 'api' ? 'api' : 'screens');
180
+ // api units derive their unit id (api/<area>) from the feature path like `generate --api`;
181
+ // screen/flow pass screenName + flowMode explicitly (unchanged → byte-identical regenerate).
182
+ const gen = kind === 'api'
183
+ ? new CodeGenerator({ framework: 'playwright', runtimeData: true })
184
+ : new CodeGenerator({ framework: 'playwright', screenName, runtimeData: true, flowMode: kind === 'flow' });
172
185
  await gen.generateAllTests(qaSourceDir, tmp, [featurePath]);
173
- const fresh = findSpec(tmp, screenName, flowMode);
186
+ const fresh = findSpec(tmp, screenName, kind);
174
187
  if (fresh) {
175
188
  const a = normalize(specSrc);
176
189
  const b = normalize(fs.readFileSync(fresh, 'utf-8'));
@@ -45,7 +45,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
45
45
  - **missing/empty bound param** → trace `{{var}}` to test-data or a prior `@api` response; fill it.
46
46
  - **`expect.status` mismatch** → reconcile against `apis.yaml`/spec (the catalog is the oracle); **never hand-edit the generated spec** (re-`generate --api` instead).
47
47
  - **flaky** → enforce self-cleaning flows, per-row isolation (`@cases`), `@concurrent` caps.
48
- 5. **Report** results + the HUMAN-LOOP FOCUS, then offer next steps. *(1:1 `script-check` + `trace` for api units land in a follow-up; for now confirm the run + re-`sungen audit --api <name>` if scenarios changed.)*
48
+ 5. **Integrity + trace** `sungen script-check --api <name>` (verify the spec is a 1:1 of the Gherkin; on DRIFT re-`generate --api`, never hand-edit) and `sungen trace --api <name>` (process map + HUMAN-LOOP FOCUS). Then report + offer next steps.
49
49
 
50
50
  ## Pre-run (phased — per `sungen-selector-fix` skill)
51
51
 
@@ -39,7 +39,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
39
39
  2. **Compile**: `npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
40
40
  3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts`.
41
41
  4. **Auto-fix** (use `sungen-error-mapping`): 401/403 → `@hybrid`+`@auth` or `Bearer :token` header (`sungen makeauth`); base_url unresolved → set `${X_URL}`; missing param → trace `{{var}}` to test-data/a prior `@api` response; `expect.status` mismatch → reconcile against `apis.yaml` (re-`generate --api`, never hand-edit the spec); flaky → self-clean + `@concurrent` caps.
42
- 5. **Report** results + the HUMAN-LOOP FOCUS. *(1:1 `script-check`/`trace` for api units land in a follow-up.)*
42
+ 5. **Integrity + trace** `sungen script-check --api <name>` (1:1; on DRIFT re-`generate --api`, never hand-edit the spec) + `sungen trace --api <name>` (process map + HUMAN-LOOP FOCUS). Report + offer next steps.
43
43
 
44
44
  ## Pre-run (phased — per `sungen-selector-fix` skill)
45
45