@sungen/driver-api 3.1.2-beta.124 → 3.1.2-beta.126

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sungen/driver-api",
3
- "version": "3.1.2-beta.124",
3
+ "version": "3.1.2-beta.126",
4
4
  "description": "Sungen API capability — the @api annotation, API catalog, OpenAPI import + `sungen api import`, and the specs/api.ts runtime template. Plugs into @sun-asterisk/sungen via the capability SPI.",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -13,7 +13,7 @@
13
13
  "author": "eqe team (engineer & quality) — Sun Asterisk",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@sun-asterisk/sungen": "3.1.2-beta.124",
16
+ "@sun-asterisk/sungen": "3.1.2-beta.126",
17
17
  "commander": "^14.0.2",
18
18
  "yaml": "^2.8.2"
19
19
  },
@@ -22,6 +22,7 @@ interface ApiScenario {
22
22
  queryRefs?: string[];
23
23
  casesDataset?: string;
24
24
  stepsText?: string; // lowercase steps text
25
+ manual?: boolean; // @manual — not automated, so excluded from automation businessDepth
25
26
  }
26
27
 
27
28
  interface ApiGateInput {
@@ -112,7 +113,10 @@ export function apiGateProvider(input: ApiGateInput): { gate: GateResult; depth:
112
113
  // An error scenario (a @cases matrix, or one asserting a 4xx/5xx) proves the failure CONTRACT —
113
114
  // the status IS its correct assertion (the API analog of UI NAV), so it is not depth-required.
114
115
  const errorLike = (s: ApiScenario) => !!s.casesDataset || /\bis\s+["']?[45]\d\d\b/.test(s.stepsText ?? '');
115
- const depthRequired = apiScenarios.filter((s) => (s.apiRefs ?? []).some(isMutating) && !errorLike(s));
116
+ // businessDepth measures AUTOMATED proof a @manual scenario isn't automated, so it can't count
117
+ // toward depth (else deferring an automatable mutation to @manual inflates the score). The
118
+ // api-viewpoints sensor separately flags @manual scenarios whose endpoint resolves (automatable).
119
+ const depthRequired = apiScenarios.filter((s) => !s.manual && (s.apiRefs ?? []).some(isMutating) && !errorLike(s));
116
120
  const isDeep = (s: ApiScenario): boolean => {
117
121
  const t = s.stepsText ?? '';
118
122
  return /\b[a-z_][a-z0-9_]*\.body\b/.test(t) // asserts a response body field
package/src/api-repair.ts CHANGED
@@ -21,6 +21,8 @@ export const apiRepair: RepairProvider = {
21
21
  fix: 'A mutating success scenario only asserts the status — make it PROVE THE EFFECT: assert a response body field, a `@query` DB side-effect, or a `@concurrent` `ok_count` invariant.' },
22
22
  { id: 'api-verification', match: /VERIFICATION-FAIL|does not resolve|not found in/i,
23
23
  fix: 'An `@api:<name>` does not resolve in the catalog — fix the name, or add/import the endpoint into `api/apis.yaml` (`sungen api import`).' },
24
+ { id: 'api-manual-automatable', match: /VIEWPOINT-API-MANUAL-AUTOMATABLE/i,
25
+ fix: 'A @manual scenario is automatable (its endpoint resolves) — drop @manual and use @api (+ @cases for error rows / @concurrent for idempotency). Reserve @manual for genuine judgment cases.' },
24
26
 
25
27
  // ── Runtime failures (from the Playwright test-result) ────────────────────────────────────
26
28
  { id: 'api-auth', match: /\b40[13]\b|unauthor|forbidden/i,
package/src/index.ts CHANGED
@@ -159,6 +159,16 @@ const apiViewpointSensor: Sensor<GateInput> = {
159
159
  }
160
160
  }
161
161
 
162
+ // api-manual-automatable — a @manual scenario whose @api endpoint RESOLVES is automatable; flag it
163
+ // so automatable work isn't deferred to manual (a common run-test reflex when the call failed).
164
+ for (const s of apiScenarios) {
165
+ if (!s.manual) continue;
166
+ const automatable = (s.apiRefs ?? []).filter((r) => { try { resolveApi(r, screenName, cwd); return true; } catch { return false; } });
167
+ if (automatable.length) {
168
+ add('warn', `VIEWPOINT-API-MANUAL-AUTOMATABLE: "${s.name}" is @manual but its endpoint(s) ${automatable.join(', ')} resolve in the catalog — automate with @api (+ @cases for error rows); don't defer an automatable API check to manual.`);
169
+ }
170
+ }
171
+
162
172
  // Method-aware: error + idempotency only apply when a referenced endpoint MUTATES.
163
173
  const mutating: string[] = [];
164
174
  for (const name of refs) {