@sun-asterisk/sungen 3.1.2-beta.117 → 3.1.2-beta.119
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/dist/cli/commands/context.d.ts +9 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +90 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +2 -0
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/context-discovery.d.ts +12 -0
- package/dist/orchestrator/context-discovery.d.ts.map +1 -0
- package/dist/orchestrator/context-discovery.js +46 -0
- package/dist/orchestrator/context-discovery.js.map +1 -0
- package/dist/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +6 -0
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +5 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +16 -1
- package/dist/orchestrator/templates/ai-instructions/claude-skill-api-design.md +49 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +5 -1
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +10 -1
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +49 -0
- package/package.json +2 -2
- package/src/cli/commands/context.ts +51 -0
- package/src/cli/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/orchestrator/ai-rules-updater.ts +2 -0
- package/src/orchestrator/context-discovery.ts +50 -0
- package/src/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +6 -0
- package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +5 -1
- package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +16 -1
- package/src/orchestrator/templates/ai-instructions/claude-skill-api-design.md +49 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +5 -1
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +10 -1
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +49 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* `sungen context` — run the Discover → Contextualize phase (AO-3) for a unit and emit the
|
|
4
|
+
* normalized Context + generation-unit work-list. The `/sungen:design` loop calls this first so it
|
|
5
|
+
* knows WHAT to generate (the endpoints/screens + their modes) before authoring scenarios. Pure +
|
|
6
|
+
* deterministic; writes `.sungen/reports/<unit>-context.json`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerContextCommand(program: Command): void;
|
|
9
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuC7D"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerContextCommand = registerContextCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const context_discovery_1 = require("../../orchestrator/context-discovery");
|
|
40
|
+
/**
|
|
41
|
+
* `sungen context` — run the Discover → Contextualize phase (AO-3) for a unit and emit the
|
|
42
|
+
* normalized Context + generation-unit work-list. The `/sungen:design` loop calls this first so it
|
|
43
|
+
* knows WHAT to generate (the endpoints/screens + their modes) before authoring scenarios. Pure +
|
|
44
|
+
* deterministic; writes `.sungen/reports/<unit>-context.json`.
|
|
45
|
+
*/
|
|
46
|
+
function registerContextCommand(program) {
|
|
47
|
+
program
|
|
48
|
+
.command('context')
|
|
49
|
+
.description('Discover + contextualize a unit (screen/flow/api area) → Context + generation units')
|
|
50
|
+
.option('-s, --screen <name>', 'Screen name')
|
|
51
|
+
.option('--flow <name>', 'Flow name (resolved as flows/<name>)')
|
|
52
|
+
.option('--api <name>', 'API-first area or api flow (resolved as api/<name>)')
|
|
53
|
+
.option('--json', 'Print the raw JSON')
|
|
54
|
+
.action(async (o) => {
|
|
55
|
+
try {
|
|
56
|
+
const unitId = o.api ? `api/${o.api}` : o.flow ? `flows/${o.flow}` : o.screen;
|
|
57
|
+
if (!unitId)
|
|
58
|
+
throw new Error('Provide --screen <name>, --flow <name>, or --api <area>.');
|
|
59
|
+
const cwd = process.cwd();
|
|
60
|
+
const result = await (0, context_discovery_1.discoverUnitContext)(unitId, cwd);
|
|
61
|
+
const outDir = path.join(cwd, '.sungen', 'reports');
|
|
62
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
63
|
+
const slug = unitId.replace(/\//g, '-');
|
|
64
|
+
const outPath = path.join(outDir, `${slug}-context.json`);
|
|
65
|
+
fs.writeFileSync(outPath, JSON.stringify(result, null, 2), 'utf-8');
|
|
66
|
+
if (o.json) {
|
|
67
|
+
console.log(JSON.stringify(result, null, 2));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const L = console.log;
|
|
71
|
+
const facts = result.context.facts;
|
|
72
|
+
L(`\n━━━ Context: ${unitId} (capability: ${result.capability}) ━━━`);
|
|
73
|
+
const srcKeys = Object.keys(result.context.sources);
|
|
74
|
+
L(` Sources: ${srcKeys.length ? srcKeys.join(', ') : '(none)'}`);
|
|
75
|
+
if (facts.endpoints?.length) {
|
|
76
|
+
L(` Endpoints (${facts.endpoints.length}):`);
|
|
77
|
+
for (const e of facts.endpoints)
|
|
78
|
+
L(` • ${e.method} ${e.path} (@api:${e.name})`);
|
|
79
|
+
}
|
|
80
|
+
const byMode = result.units.reduce((m, u) => { m[u.mode] = (m[u.mode] || 0) + 1; return m; }, {});
|
|
81
|
+
L(` Generation units: ${result.units.length} — ${Object.entries(byMode).map(([m, n]) => `${m}×${n}`).join(' · ') || '(none)'}`);
|
|
82
|
+
L(`\n Report: ${path.relative(cwd, outPath)}\n`);
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
console.error('Error:', e instanceof Error ? e.message : e);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/cli/commands/context.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -27,6 +27,7 @@ const challenge_1 = require("./commands/challenge");
|
|
|
27
27
|
const blindspot_1 = require("./commands/blindspot");
|
|
28
28
|
const capability_1 = require("./commands/capability");
|
|
29
29
|
const flow_check_1 = require("./commands/flow-check");
|
|
30
|
+
const context_1 = require("./commands/context");
|
|
30
31
|
const registry_1 = require("../capabilities/registry");
|
|
31
32
|
const discover_1 = require("../capabilities/discover");
|
|
32
33
|
// Read version from package.json so `--version` never drifts from the released version.
|
|
@@ -60,6 +61,7 @@ async function main() {
|
|
|
60
61
|
(0, blindspot_1.registerBlindspotCommand)(program);
|
|
61
62
|
(0, capability_1.registerCapabilityCommand)(program);
|
|
62
63
|
(0, flow_check_1.registerFlowCheckCommand)(program);
|
|
64
|
+
(0, context_1.registerContextCommand)(program);
|
|
63
65
|
(0, ingest_1.registerIngestCommand)(program);
|
|
64
66
|
(0, eval_1.registerEvalCommand)(program);
|
|
65
67
|
// Capability-contributed CLI commands (Capability SPI): drivers own their authoring commands
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;AACA;;;GAGG;;AAEH,yCAAoC;AACpC,0CAAsD;AACtD,wCAAoD;AACpD,kDAA8D;AAC9D,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAC9D,4CAAwD;AACxD,kDAA6D;AAC7D,oDAAgE;AAChE,4CAAwD;AACxD,8CAA0D;AAC1D,0CAAsD;AACtD,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAC9D,0DAAqE;AACrE,4CAAwD;AACxD,oDAAgE;AAChE,oDAAgE;AAChE,sDAAkE;AAClE,sDAAiE;AACjE,uDAA8D;AAC9D,uDAA2E;AAE3E,wFAAwF;AACxF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEzE,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,QAAQ,CAAC;SACd,WAAW,CAAC,oEAAoE,CAAC;SACjF,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,iBAAiB;IACjB,OAAO;SACJ,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IAErD,oBAAoB;IACpB,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;IAC5B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,iCAAsB,EAAC,OAAO,CAAC,CAAC;IAChC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,yCAA0B,EAAC,OAAO,CAAC,CAAC;IACpC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,sCAAyB,EAAC,OAAO,CAAC,CAAC;IACnC,IAAA,qCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAE7B,6FAA6F;IAC7F,iFAAiF;IACjF,IAAA,0CAA+B,GAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,6BAAkB,CAAC,GAAG,EAAE,EAAE,CAAC;QAC3C,KAAK,MAAM,eAAe,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE;YAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;AACA;;;GAGG;;AAEH,yCAAoC;AACpC,0CAAsD;AACtD,wCAAoD;AACpD,kDAA8D;AAC9D,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAC9D,4CAAwD;AACxD,kDAA6D;AAC7D,oDAAgE;AAChE,4CAAwD;AACxD,8CAA0D;AAC1D,0CAAsD;AACtD,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAC9D,0DAAqE;AACrE,4CAAwD;AACxD,oDAAgE;AAChE,oDAAgE;AAChE,sDAAkE;AAClE,sDAAiE;AACjE,gDAA4D;AAC5D,uDAA8D;AAC9D,uDAA2E;AAE3E,wFAAwF;AACxF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEzE,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,QAAQ,CAAC;SACd,WAAW,CAAC,oEAAoE,CAAC;SACjF,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,iBAAiB;IACjB,OAAO;SACJ,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IAErD,oBAAoB;IACpB,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;IAC5B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,iCAAsB,EAAC,OAAO,CAAC,CAAC;IAChC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,yCAA0B,EAAC,OAAO,CAAC,CAAC;IACpC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,sCAAyB,EAAC,OAAO,CAAC,CAAC;IACnC,IAAA,qCAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;IAChC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAE7B,6FAA6F;IAC7F,iFAAiF;IACjF,IAAA,0CAA+B,GAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,6BAAkB,CAAC,GAAG,EAAE,EAAE,CAAC;QAC3C,KAAK,MAAM,eAAe,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE;YAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export { capabilityRegistry, CapabilityRegistry } from './capabilities/registry'
|
|
|
7
7
|
export type { CapabilityDescriptor } from './capabilities/registry';
|
|
8
8
|
export type { Sensor, SensorFinding, AdvisoryScanInput, GateInput } from './capabilities/sensor';
|
|
9
9
|
export type { Context, DiscoveryProvider, ContextMapper, GenerationUnit } from './capabilities/context';
|
|
10
|
+
export { discoverUnitContext } from './orchestrator/context-discovery';
|
|
11
|
+
export type { DiscoveredContext } from './orchestrator/context-discovery';
|
|
10
12
|
export type { PatternContext, StepPattern, StepTemplateData } from './generators/test-generator/patterns/types';
|
|
11
13
|
export type { MappedStep } from './generators/test-generator/step-mapper';
|
|
12
14
|
export type { ParsedStep } from './generators/gherkin-parser';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACjF,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACjG,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACjF,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACjG,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxG,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAG1E,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAChH,YAAY,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AAGhH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAClF,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAI1D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChI,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC1E,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
* imports from a driver (discovery loads them at runtime). Keep this surface small and intentional.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.depthWarnOnly = exports.depthThresholdFor = exports.dataThemesFor = exports.assertionDepth = exports.viewpointGate = exports.loadCatalog = exports.lintCatalog = exports.compileQuery = exports.resolveQuery = exports.parseQueryOverrides = exports.resolvePathVariables = exports.inferPath = exports.getPathCode = exports.CapabilityRegistry = exports.capabilityRegistry = void 0;
|
|
8
|
+
exports.depthWarnOnly = exports.depthThresholdFor = exports.dataThemesFor = exports.assertionDepth = exports.viewpointGate = exports.loadCatalog = exports.lintCatalog = exports.compileQuery = exports.resolveQuery = exports.parseQueryOverrides = exports.resolvePathVariables = exports.inferPath = exports.getPathCode = exports.discoverUnitContext = exports.CapabilityRegistry = exports.capabilityRegistry = void 0;
|
|
9
9
|
// --- Capability SPI ---
|
|
10
10
|
var registry_1 = require("./capabilities/registry");
|
|
11
11
|
Object.defineProperty(exports, "capabilityRegistry", { enumerable: true, get: function () { return registry_1.capabilityRegistry; } });
|
|
12
12
|
Object.defineProperty(exports, "CapabilityRegistry", { enumerable: true, get: function () { return registry_1.CapabilityRegistry; } });
|
|
13
|
+
var context_discovery_1 = require("./orchestrator/context-discovery");
|
|
14
|
+
Object.defineProperty(exports, "discoverUnitContext", { enumerable: true, get: function () { return context_discovery_1.discoverUnitContext; } });
|
|
13
15
|
var path_inference_1 = require("./generators/test-generator/utils/path-inference");
|
|
14
16
|
Object.defineProperty(exports, "getPathCode", { enumerable: true, get: function () { return path_inference_1.getPathCode; } });
|
|
15
17
|
Object.defineProperty(exports, "inferPath", { enumerable: true, get: function () { return path_inference_1.inferPath; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,yBAAyB;AACzB,oDAAiF;AAAxE,8GAAA,kBAAkB,OAAA;AAAE,8GAAA,kBAAkB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,yBAAyB;AACzB,oDAAiF;AAAxE,8GAAA,kBAAkB,OAAA;AAAE,8GAAA,kBAAkB,OAAA;AAI/C,sEAAuE;AAA9D,wHAAA,mBAAmB,OAAA;AAO5B,mFAAgH;AAAvG,6GAAA,WAAW,OAAA;AAAE,2GAAA,SAAS,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAErD,gGAAgG;AAChG,uEAAqE;AAA5D,2HAAA,mBAAmB,OAAA;AAE5B,mGAAmG;AACnG,yDAAkF;AAAzE,6GAAA,YAAY,OAAA;AAAE,6GAAA,YAAY,OAAA;AAAE,4GAAA,WAAW,OAAA;AAGhD,8EAA8E;AAC9E,mGAAmG;AACnG,6CAAgI;AAAvH,sGAAA,WAAW,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,yGAAA,cAAc,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,4GAAA,iBAAiB,OAAA;AAAE,wGAAA,aAAa,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-rules-updater.d.ts","sourceRoot":"","sources":["../../src/orchestrator/ai-rules-updater.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,qBAAqB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"ai-rules-updater.d.ts","sourceRoot":"","sources":["../../src/orchestrator/ai-rules-updater.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,qBAAqB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAuFnD,CAAC;AAKF,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAUxC,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,aAAa,CAAS;gBAElB,GAAG,EAAE,MAAM;IAKjB,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CA4G7C"}
|
|
@@ -78,6 +78,7 @@ exports.AI_RULES_FILE_MAPPING = [
|
|
|
78
78
|
['claude-skill-selector-fix.md', '.claude/skills/sungen-selector-fix/SKILL.md'],
|
|
79
79
|
['claude-skill-tc-review.md', '.claude/skills/sungen-tc-review/SKILL.md'],
|
|
80
80
|
['claude-skill-harness-audit.md', '.claude/skills/sungen-harness-audit/SKILL.md'],
|
|
81
|
+
['claude-skill-api-design.md', '.claude/skills/sungen-api-design/SKILL.md'],
|
|
81
82
|
['claude-skill-ingest-legacy.md', '.claude/skills/sungen-ingest-legacy/SKILL.md'],
|
|
82
83
|
['claude-skill-viewpoint.md', '.claude/skills/sungen-viewpoint/SKILL.md'],
|
|
83
84
|
['claude-skill-viewpoint-group-a-data-entry.md', '.claude/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
@@ -108,6 +109,7 @@ exports.AI_RULES_FILE_MAPPING = [
|
|
|
108
109
|
['github-skill-sungen-selector-fix.md', '.github/skills/sungen-selector-fix/SKILL.md'],
|
|
109
110
|
['github-skill-sungen-tc-review.md', '.github/skills/sungen-tc-review/SKILL.md'],
|
|
110
111
|
['github-skill-sungen-harness-audit.md', '.github/skills/sungen-harness-audit/SKILL.md'],
|
|
112
|
+
['github-skill-sungen-api-design.md', '.github/skills/sungen-api-design/SKILL.md'],
|
|
111
113
|
['github-skill-sungen-ingest-legacy.md', '.github/skills/sungen-ingest-legacy/SKILL.md'],
|
|
112
114
|
['github-skill-sungen-viewpoint.md', '.github/skills/sungen-viewpoint/SKILL.md'],
|
|
113
115
|
['github-skill-sungen-viewpoint-group-a-data-entry.md', '.github/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-rules-updater.js","sourceRoot":"","sources":["../../src/orchestrator/ai-rules-updater.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-rules-updater.js","sourceRoot":"","sources":["../../src/orchestrator/ai-rules-updater.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context, GenerationUnit } from '../capabilities/context';
|
|
2
|
+
export interface DiscoveredContext {
|
|
3
|
+
capability: string;
|
|
4
|
+
context: Context;
|
|
5
|
+
units: GenerationUnit[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Run the Discover → Contextualize phase for a unit. `unitId` is the catalog-resolution id
|
|
9
|
+
* (`<screen>` · `flows/<flow>` · `api/<area>` · `api/flows/<flow>`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function discoverUnitContext(unitId: string, cwd?: string): Promise<DiscoveredContext>;
|
|
12
|
+
//# sourceMappingURL=context-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-discovery.d.ts","sourceRoot":"","sources":["../../src/orchestrator/context-discovery.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AASD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmBjH"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.discoverUnitContext = discoverUnitContext;
|
|
4
|
+
/**
|
|
5
|
+
* Orchestration phase: Discover → Contextualize (AO-3).
|
|
6
|
+
*
|
|
7
|
+
* The capability SPI declared `discovery` (sources → Context slice) + `contextMapper` (Context →
|
|
8
|
+
* generation units) since R1, but nothing consumed them. This is the deterministic consumer the
|
|
9
|
+
* orchestration loop (`/sungen:design`) calls before generating: resolve the unit's capability,
|
|
10
|
+
* run ITS discovery + contextMapper, and hand back the normalized Context + the generation-unit
|
|
11
|
+
* work-list. Capability-agnostic — a screen, an api area, or a future `mobile/` unit all flow here.
|
|
12
|
+
*/
|
|
13
|
+
const registry_1 = require("../capabilities/registry");
|
|
14
|
+
const discover_1 = require("../capabilities/discover");
|
|
15
|
+
/** Map a unit id (relative to qa/) to a discovery target. */
|
|
16
|
+
function targetForUnit(unitId) {
|
|
17
|
+
if (unitId.startsWith('api/'))
|
|
18
|
+
return { kind: 'api', id: unitId };
|
|
19
|
+
if (unitId.startsWith('flows/'))
|
|
20
|
+
return { kind: 'flow', id: unitId };
|
|
21
|
+
return { kind: 'screen', id: unitId };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run the Discover → Contextualize phase for a unit. `unitId` is the catalog-resolution id
|
|
25
|
+
* (`<screen>` · `flows/<flow>` · `api/<area>` · `api/flows/<flow>`).
|
|
26
|
+
*/
|
|
27
|
+
async function discoverUnitContext(unitId, cwd = process.cwd()) {
|
|
28
|
+
(0, discover_1.discoverAndRegisterCapabilities)();
|
|
29
|
+
const target = targetForUnit(unitId);
|
|
30
|
+
// The discovering capability is the first whose DiscoveryProvider claims the target; else the default.
|
|
31
|
+
const cap = registry_1.capabilityRegistry.all().find((c) => c.discovery?.appliesTo?.(target))
|
|
32
|
+
?? (registry_1.capabilityRegistry.defaultCapabilityId() ? registry_1.capabilityRegistry.get(registry_1.capabilityRegistry.defaultCapabilityId()) : undefined);
|
|
33
|
+
let context = { target: { ...target, capability: cap?.id }, sources: {}, facts: {} };
|
|
34
|
+
if (cap?.discovery) {
|
|
35
|
+
const slice = await cap.discovery.discover(target, { cwd });
|
|
36
|
+
context = {
|
|
37
|
+
target: { ...target, capability: cap.id },
|
|
38
|
+
sources: { ...context.sources, ...(slice.sources ?? {}) },
|
|
39
|
+
facts: { ...context.facts, ...(slice.facts ?? {}) },
|
|
40
|
+
...(slice.connectivity ? { connectivity: slice.connectivity } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const units = cap?.contextMapper?.decompose(context) ?? [];
|
|
44
|
+
return { capability: cap?.id ?? 'ui', context, units };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=context-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-discovery.js","sourceRoot":"","sources":["../../src/orchestrator/context-discovery.ts"],"names":[],"mappings":";;AA8BA,kDAmBC;AAjDD;;;;;;;;GAQG;AACH,uDAA8D;AAC9D,uDAA2E;AAS3E,6DAA6D;AAC7D,SAAS,aAAa,CAAC,MAAc;IACnC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IAClE,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IACrE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACnF,IAAA,0CAA+B,GAAE,CAAC;IAClC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,uGAAuG;IACvG,MAAM,GAAG,GAAG,6BAAkB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;WAC7E,CAAC,6BAAkB,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,6BAAkB,CAAC,GAAG,CAAC,6BAAkB,CAAC,mBAAmB,EAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhI,IAAI,OAAO,GAAY,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAC9F,IAAI,GAAG,EAAE,SAAS,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,OAAO,GAAG;YACR,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE;YACzC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;YACzD,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;YACnD,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,EAAE,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC3D,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -19,6 +19,12 @@ You are an **independent Senior QA Reviewer**. You did **not** write these tests
|
|
|
19
19
|
3. **Business-critical depth.** For cart / product-detail / filter / list viewpoints, do steps assert **DATA** (name, price, quantity, all-items-belong) — not just page/modal visibility? Recommend the concrete deep step: `User remember [X] text as {{v}}` + `... with {{v}}`, or `User see all [X] contain {{v}}`.
|
|
20
20
|
4. **@manual justification.** Is each `@manual` genuinely unautomatable (cross-screen/external/visual) — or a cop-out to dodge the gate? Cross-screen → should be a flow.
|
|
21
21
|
5. **Meaning-level duplicates & missing criticals** the keyword gate can't see.
|
|
22
|
+
6. **API units** (`qa/api/<area>/` — `@api` scenarios, no UI). Judge what the api gate can't:
|
|
23
|
+
- **Prove the effect, not the status.** A mutating endpoint's success path asserting only `{{r.status}} is 201` proves nothing about WHAT changed — demand a **body** assertion (`{{r.body.id}}` / `{{r.body.<field>}}`), a **`@query`** DB side-effect, or (idempotency) a `{{r.ok_count}}` invariant. This is the API businessDepth bar.
|
|
24
|
+
- **Error matrix coherent.** `@cases` rows are a real failure family (validation/auth/conflict) with realistic inputs → declared statuses, not padding.
|
|
25
|
+
- **Flows self-clean.** A CRUD/auth chain deletes what it created (final `@api:delete_*`) or is `@cleanup`-tagged.
|
|
26
|
+
- **Idempotency uses the DB oracle.** A "no double-charge / exactly once" claim is proven by `@concurrent` + a `@query` count, not HTTP status alone (status can lie under a race).
|
|
27
|
+
- **Auth negatives** exist for protected mutations (401/403), not just the happy path.
|
|
22
28
|
|
|
23
29
|
## Output (do NOT edit any file)
|
|
24
30
|
Return a concise verdict:
|
|
@@ -23,7 +23,11 @@ You are a **Senior QA Engineer** specialized in test case design. You structure
|
|
|
23
23
|
|
|
24
24
|
Parse **name** from `$ARGUMENTS`. If missing, ask the user.
|
|
25
25
|
|
|
26
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists →
|
|
26
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode. Else `qa/screens/<name>/` → screen mode. This determines paths, generation strategy, and CLI commands.
|
|
27
|
+
|
|
28
|
+
## API unit mode (driver-api)
|
|
29
|
+
|
|
30
|
+
If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the design loop differs — **no visual capture, no selectors**; the contract is the named-endpoint catalog. **Follow the `sungen-api-design` skill end-to-end** instead of the screen/flow steps below: `sungen context --api <name>` (discover) → API viewpoint overview → generate `@api`/`@cases`/flow/`@concurrent`/`@query` scenarios → **`sungen audit --api <name>` gate + the `sungen-reviewer` sub-agent + repair loop to businessDepth ≥ 0.7** → record + trace. Then jump to the "Converge" next-step options (recommend `/sungen:run-test <name>`). The capture / viewpoint-group / selector steps do **not** apply.
|
|
27
31
|
|
|
28
32
|
## Steps
|
|
29
33
|
|
|
@@ -30,7 +30,22 @@ If the count is 0 → use `AskUserQuestion` to offer:
|
|
|
30
30
|
|
|
31
31
|
Skip this pre-flight when `--env` matches the base locale (no overlay needed in that case).
|
|
32
32
|
|
|
33
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
33
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
34
|
+
|
|
35
|
+
## API unit mode (driver-api) — no selectors
|
|
36
|
+
|
|
37
|
+
If the unit is **api-first**, skip every selector/capture phase (an API test has no DOM). Instead:
|
|
38
|
+
|
|
39
|
+
1. **Resolve the datasource** — ensure the `kind: api` datasource's `base_url` + auth are wired in `qa/datasources.yaml` + `.env.qa` (the `${X_URL}` key from `sungen api init`). A `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
40
|
+
2. **Compile**: `[ -x ./bin/sungen.js ] && ./bin/sungen.js generate --api <name> || npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
|
|
41
|
+
3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts` (per-spec JSON results, as below).
|
|
42
|
+
4. **Auto-fix** (no selectors — the failure classes differ): use `sungen-error-mapping`.
|
|
43
|
+
- **401/403** → wire `@hybrid` + `@auth:<role>` (reuse the UI session) or the catalog `Bearer :token` header; suggest `sungen makeauth <role>`.
|
|
44
|
+
- **datasource/base_url unresolved** → set the `${X_URL}` key in `.env.qa`.
|
|
45
|
+
- **missing/empty bound param** → trace `{{var}}` to test-data or a prior `@api` response; fill it.
|
|
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
|
+
- **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.)*
|
|
34
49
|
|
|
35
50
|
## Pre-run (phased — per `sungen-selector-fix` skill)
|
|
36
51
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-api-design
|
|
3
|
+
description: The API-first design loop for an api unit (qa/api/<area> or qa/api/flows/<flow>) — discover the catalog, lay out the API viewpoints, generate @api/@cases/flow/@concurrent scenarios, then drive the sungen audit --api gate + reviewer + repair to a high businessDepth (≥0.7). Use when create-test/run-test detects an api unit (no selectors, no visual capture).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API design loop (driver-api · Orchestration + Harness)
|
|
7
|
+
|
|
8
|
+
Use this when the unit is **api-first** — `qa/api/<area>/` or `qa/api/flows/<flow>/`. There are **no selectors and no visual capture**: the contract is the **named-endpoint catalog** (`api/apis.yaml`), referenced by `@api:<name>`. QA writes **no HTTP code**. Full annotation reference: the **API Steps** guide (`@api` / `@cases` / flows / `@concurrent` / `@hybrid`).
|
|
9
|
+
|
|
10
|
+
## The loop (mirror of /sungen:design, API-native)
|
|
11
|
+
|
|
12
|
+
### 1. Discover (no capture)
|
|
13
|
+
Run `sungen context --api <name>` — it reads the catalog and prints the **endpoints** + the **generation units** (one `matrix` unit per endpoint, an `async` unit per mutating endpoint, a `flow` unit for an api flow). Read `qa/api/<name>/requirements/spec.md` if present. No `apis.yaml` yet? → `sungen api import <openapi|csv>` or `sungen api add --area <name>` first.
|
|
14
|
+
|
|
15
|
+
### 2. API viewpoint overview (by method-profile)
|
|
16
|
+
For each endpoint, cover its viewpoints — severity-weighted by method:
|
|
17
|
+
|
|
18
|
+
| Profile | Endpoints | Must cover | Then |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| read | GET, HEAD | `contract` (status + body shape) | `pagination`/`filter` (list), `not-found` (by-id) |
|
|
21
|
+
| mutating | POST/PUT/PATCH/DELETE | `contract`, `error` (validation/4xx/auth) | `idempotency` (`@concurrent`), `side-effect` (`@query`) |
|
|
22
|
+
|
|
23
|
+
Bands: **~70%** success+failure matrix · **~20%** flows (auth/CRUD chains) · **~10%** async/idempotency.
|
|
24
|
+
|
|
25
|
+
### 3. Generate (incremental — never the whole suite in one Write)
|
|
26
|
+
- **Contract**: `@api:<name>` + `expect {{name.status}} is …` **and a body assertion** (`{{name.body.<path>}}`).
|
|
27
|
+
- **Error matrix**: `@api:<name>(p={{p}}) @cases:<dataset>` — one scenario, a dataset of `input → expected status`.
|
|
28
|
+
- **Flow**: ordered `@api` tags threading a prior response (`token={{login.body.token}}` → the catalog `Bearer :token` header; `id={{create.body.id}}` → a path param). Self-clean (delete what you create).
|
|
29
|
+
- **Idempotency**: `@api:<name> @concurrent:N` + `expect {{name.ok_count}} is 1`, cross-checked with `@query` (the DB is the oracle).
|
|
30
|
+
|
|
31
|
+
### 4. Gate + repair (always — businessDepth ≥ 0.7 is the bar)
|
|
32
|
+
Run `sungen audit --api <name>`; read `gateStatus` + `findings`. Then the **semantic reviewer** (sungen-reviewer sub-agent, API criteria). Repair **both** (budget 3 rounds), re-audit until PASS:
|
|
33
|
+
|
|
34
|
+
| Finding | Repair |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `VIEWPOINT-API-CONTRACT` | the endpoint is invoked but its response is never asserted → add `expect {{name.status}}` + a `{{name.body.…}}` check |
|
|
37
|
+
| `VIEWPOINT-API-ERROR` | a mutating endpoint has no failure scenario → add a `@cases` error matrix (or an explicit 4xx) |
|
|
38
|
+
| `VIEWPOINT-API-IDEMPOTENCY` | a mutating endpoint has no race check → add `@concurrent:N` + a `@query` DB cross-check |
|
|
39
|
+
| **`DEPTH-FAIL`** (businessDepth < 0.7) | a **mutating success** scenario asserts only `status` → make it **prove the effect**: assert a response **body** field, a **`@query`** side-effect, or a **`@concurrent` `ok_count`** invariant. (An error/`@cases` scenario proving the status is correct — it is *not* depth-required.) |
|
|
40
|
+
|
|
41
|
+
Stop when the gate PASSes + businessDepth ≥ 0.7, or the budget is exhausted → report residual gaps honestly (mark genuinely-unautomatable cases `@manual` with an oracle). Never fake a pass.
|
|
42
|
+
|
|
43
|
+
### 5. Record + converge
|
|
44
|
+
`sungen manifest --api <name>` (reuse) and ledger each phase; show the trace + the HUMAN-LOOP FOCUS. (Integrity `script-check`/`trace` for api: see run-test.)
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
- **No HTTP, no selectors** — only `.feature` + the reviewed `apis.yaml` + `test-data`.
|
|
48
|
+
- **Non-prod default** — a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
49
|
+
- **The DB is the oracle** for idempotency/side-effects — HTTP status alone can lie; pair `@api` with `@query`.
|
|
@@ -18,7 +18,11 @@ You are a **Senior QA Engineer**. You structure test cases by viewpoint categori
|
|
|
18
18
|
|
|
19
19
|
- **name** — ${input:name:screen or flow name (e.g., login, award-submission)}
|
|
20
20
|
|
|
21
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
21
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
22
|
+
|
|
23
|
+
## API unit mode (driver-api)
|
|
24
|
+
|
|
25
|
+
If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the design loop differs — **no visual capture, no selectors**; the contract is the named-endpoint catalog. **Follow the `sungen-api-design` skill end-to-end** instead of the screen/flow steps: `sungen context --api <name>` (discover) → API viewpoint overview → generate `@api`/`@cases`/flow/`@concurrent`/`@query` scenarios → **`sungen audit --api <name>` gate + reviewer + repair loop to businessDepth ≥ 0.7** → record + trace. Then recommend `/sungen-run-test <name>`. The capture / viewpoint-group / selector steps do **not** apply.
|
|
22
26
|
|
|
23
27
|
## Steps
|
|
24
28
|
|
|
@@ -30,7 +30,16 @@ Count 0 → offer the user:
|
|
|
30
30
|
|
|
31
31
|
Skip when `--env` matches the base locale.
|
|
32
32
|
|
|
33
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
33
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
34
|
+
|
|
35
|
+
## API unit mode (driver-api) — no selectors
|
|
36
|
+
|
|
37
|
+
If the unit is **api-first**, skip every selector/capture phase (an API test has no DOM):
|
|
38
|
+
1. **Resolve the datasource** — `base_url` + auth wired in `qa/datasources.yaml` + `.env.qa` (`${X_URL}` from `sungen api init`); a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
39
|
+
2. **Compile**: `npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
|
|
40
|
+
3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts`.
|
|
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.)*
|
|
34
43
|
|
|
35
44
|
## Pre-run (phased — per `sungen-selector-fix` skill)
|
|
36
45
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-api-design
|
|
3
|
+
description: The API-first design loop for an api unit (qa/api/<area> or qa/api/flows/<flow>) — discover the catalog, lay out the API viewpoints, generate @api/@cases/flow/@concurrent scenarios, then drive the sungen audit --api gate + reviewer + repair to a high businessDepth (≥0.7). Use when create-test/run-test detects an api unit (no selectors, no visual capture).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API design loop (driver-api · Orchestration + Harness)
|
|
7
|
+
|
|
8
|
+
Use this when the unit is **api-first** — `qa/api/<area>/` or `qa/api/flows/<flow>/`. There are **no selectors and no visual capture**: the contract is the **named-endpoint catalog** (`api/apis.yaml`), referenced by `@api:<name>`. QA writes **no HTTP code**. Full annotation reference: the **API Steps** guide (`@api` / `@cases` / flows / `@concurrent` / `@hybrid`).
|
|
9
|
+
|
|
10
|
+
## The loop (mirror of /sungen:design, API-native)
|
|
11
|
+
|
|
12
|
+
### 1. Discover (no capture)
|
|
13
|
+
Run `sungen context --api <name>` — it reads the catalog and prints the **endpoints** + the **generation units** (one `matrix` unit per endpoint, an `async` unit per mutating endpoint, a `flow` unit for an api flow). Read `qa/api/<name>/requirements/spec.md` if present. No `apis.yaml` yet? → `sungen api import <openapi|csv>` or `sungen api add --area <name>` first.
|
|
14
|
+
|
|
15
|
+
### 2. API viewpoint overview (by method-profile)
|
|
16
|
+
For each endpoint, cover its viewpoints — severity-weighted by method:
|
|
17
|
+
|
|
18
|
+
| Profile | Endpoints | Must cover | Then |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| read | GET, HEAD | `contract` (status + body shape) | `pagination`/`filter` (list), `not-found` (by-id) |
|
|
21
|
+
| mutating | POST/PUT/PATCH/DELETE | `contract`, `error` (validation/4xx/auth) | `idempotency` (`@concurrent`), `side-effect` (`@query`) |
|
|
22
|
+
|
|
23
|
+
Bands: **~70%** success+failure matrix · **~20%** flows (auth/CRUD chains) · **~10%** async/idempotency.
|
|
24
|
+
|
|
25
|
+
### 3. Generate (incremental — never the whole suite in one Write)
|
|
26
|
+
- **Contract**: `@api:<name>` + `expect {{name.status}} is …` **and a body assertion** (`{{name.body.<path>}}`).
|
|
27
|
+
- **Error matrix**: `@api:<name>(p={{p}}) @cases:<dataset>` — one scenario, a dataset of `input → expected status`.
|
|
28
|
+
- **Flow**: ordered `@api` tags threading a prior response (`token={{login.body.token}}` → the catalog `Bearer :token` header; `id={{create.body.id}}` → a path param). Self-clean (delete what you create).
|
|
29
|
+
- **Idempotency**: `@api:<name> @concurrent:N` + `expect {{name.ok_count}} is 1`, cross-checked with `@query` (the DB is the oracle).
|
|
30
|
+
|
|
31
|
+
### 4. Gate + repair (always — businessDepth ≥ 0.7 is the bar)
|
|
32
|
+
Run `sungen audit --api <name>`; read `gateStatus` + `findings`. Then the **semantic reviewer** (sungen-reviewer sub-agent, API criteria). Repair **both** (budget 3 rounds), re-audit until PASS:
|
|
33
|
+
|
|
34
|
+
| Finding | Repair |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `VIEWPOINT-API-CONTRACT` | the endpoint is invoked but its response is never asserted → add `expect {{name.status}}` + a `{{name.body.…}}` check |
|
|
37
|
+
| `VIEWPOINT-API-ERROR` | a mutating endpoint has no failure scenario → add a `@cases` error matrix (or an explicit 4xx) |
|
|
38
|
+
| `VIEWPOINT-API-IDEMPOTENCY` | a mutating endpoint has no race check → add `@concurrent:N` + a `@query` DB cross-check |
|
|
39
|
+
| **`DEPTH-FAIL`** (businessDepth < 0.7) | a **mutating success** scenario asserts only `status` → make it **prove the effect**: assert a response **body** field, a **`@query`** side-effect, or a **`@concurrent` `ok_count`** invariant. (An error/`@cases` scenario proving the status is correct — it is *not* depth-required.) |
|
|
40
|
+
|
|
41
|
+
Stop when the gate PASSes + businessDepth ≥ 0.7, or the budget is exhausted → report residual gaps honestly (mark genuinely-unautomatable cases `@manual` with an oracle). Never fake a pass.
|
|
42
|
+
|
|
43
|
+
### 5. Record + converge
|
|
44
|
+
`sungen manifest --api <name>` (reuse) and ledger each phase; show the trace + the HUMAN-LOOP FOCUS. (Integrity `script-check`/`trace` for api: see run-test.)
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
- **No HTTP, no selectors** — only `.feature` + the reviewed `apis.yaml` + `test-data`.
|
|
48
|
+
- **Non-prod default** — a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
49
|
+
- **The DB is the oracle** for idempotency/side-effects — HTTP status alone can lie; pair `@api` with `@query`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sun-asterisk/sungen",
|
|
3
|
-
"version": "3.1.2-beta.
|
|
3
|
+
"version": "3.1.2-beta.119",
|
|
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.
|
|
36
|
+
"@sungen/driver-ui": "3.1.2-beta.119",
|
|
37
37
|
"@anthropic-ai/sdk": "^0.71.0",
|
|
38
38
|
"@babel/parser": "^7.28.5",
|
|
39
39
|
"@babel/traverse": "^7.28.5",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { discoverUnitContext } from '../../orchestrator/context-discovery';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `sungen context` — run the Discover → Contextualize phase (AO-3) for a unit and emit the
|
|
8
|
+
* normalized Context + generation-unit work-list. The `/sungen:design` loop calls this first so it
|
|
9
|
+
* knows WHAT to generate (the endpoints/screens + their modes) before authoring scenarios. Pure +
|
|
10
|
+
* deterministic; writes `.sungen/reports/<unit>-context.json`.
|
|
11
|
+
*/
|
|
12
|
+
export function registerContextCommand(program: Command): void {
|
|
13
|
+
program
|
|
14
|
+
.command('context')
|
|
15
|
+
.description('Discover + contextualize a unit (screen/flow/api area) → Context + generation units')
|
|
16
|
+
.option('-s, --screen <name>', 'Screen name')
|
|
17
|
+
.option('--flow <name>', 'Flow name (resolved as flows/<name>)')
|
|
18
|
+
.option('--api <name>', 'API-first area or api flow (resolved as api/<name>)')
|
|
19
|
+
.option('--json', 'Print the raw JSON')
|
|
20
|
+
.action(async (o: { screen?: string; flow?: string; api?: string; json?: boolean }) => {
|
|
21
|
+
try {
|
|
22
|
+
const unitId = o.api ? `api/${o.api}` : o.flow ? `flows/${o.flow}` : o.screen;
|
|
23
|
+
if (!unitId) throw new Error('Provide --screen <name>, --flow <name>, or --api <area>.');
|
|
24
|
+
const cwd = process.cwd();
|
|
25
|
+
const result = await discoverUnitContext(unitId, cwd);
|
|
26
|
+
|
|
27
|
+
const outDir = path.join(cwd, '.sungen', 'reports');
|
|
28
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
29
|
+
const slug = unitId.replace(/\//g, '-');
|
|
30
|
+
const outPath = path.join(outDir, `${slug}-context.json`);
|
|
31
|
+
fs.writeFileSync(outPath, JSON.stringify(result, null, 2), 'utf-8');
|
|
32
|
+
if (o.json) { console.log(JSON.stringify(result, null, 2)); return; }
|
|
33
|
+
|
|
34
|
+
const L = console.log;
|
|
35
|
+
const facts = result.context.facts as { endpoints?: Array<{ name: string; method: string; path: string }> };
|
|
36
|
+
L(`\n━━━ Context: ${unitId} (capability: ${result.capability}) ━━━`);
|
|
37
|
+
const srcKeys = Object.keys(result.context.sources);
|
|
38
|
+
L(` Sources: ${srcKeys.length ? srcKeys.join(', ') : '(none)'}`);
|
|
39
|
+
if (facts.endpoints?.length) {
|
|
40
|
+
L(` Endpoints (${facts.endpoints.length}):`);
|
|
41
|
+
for (const e of facts.endpoints) L(` • ${e.method} ${e.path} (@api:${e.name})`);
|
|
42
|
+
}
|
|
43
|
+
const byMode = result.units.reduce<Record<string, number>>((m, u) => { m[u.mode] = (m[u.mode] || 0) + 1; return m; }, {});
|
|
44
|
+
L(` Generation units: ${result.units.length} — ${Object.entries(byMode).map(([m, n]) => `${m}×${n}`).join(' · ') || '(none)'}`);
|
|
45
|
+
L(`\n Report: ${path.relative(cwd, outPath)}\n`);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
console.error('Error:', e instanceof Error ? e.message : e);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { registerChallengeCommand } from './commands/challenge';
|
|
|
26
26
|
import { registerBlindspotCommand } from './commands/blindspot';
|
|
27
27
|
import { registerCapabilityCommand } from './commands/capability';
|
|
28
28
|
import { registerFlowCheckCommand } from './commands/flow-check';
|
|
29
|
+
import { registerContextCommand } from './commands/context';
|
|
29
30
|
import { capabilityRegistry } from '../capabilities/registry';
|
|
30
31
|
import { discoverAndRegisterCapabilities } from '../capabilities/discover';
|
|
31
32
|
|
|
@@ -64,6 +65,7 @@ async function main() {
|
|
|
64
65
|
registerBlindspotCommand(program);
|
|
65
66
|
registerCapabilityCommand(program);
|
|
66
67
|
registerFlowCheckCommand(program);
|
|
68
|
+
registerContextCommand(program);
|
|
67
69
|
registerIngestCommand(program);
|
|
68
70
|
registerEvalCommand(program);
|
|
69
71
|
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { capabilityRegistry, CapabilityRegistry } from './capabilities/registry'
|
|
|
9
9
|
export type { CapabilityDescriptor } from './capabilities/registry';
|
|
10
10
|
export type { Sensor, SensorFinding, AdvisoryScanInput, GateInput } from './capabilities/sensor';
|
|
11
11
|
export type { Context, DiscoveryProvider, ContextMapper, GenerationUnit } from './capabilities/context';
|
|
12
|
+
export { discoverUnitContext } from './orchestrator/context-discovery';
|
|
13
|
+
export type { DiscoveredContext } from './orchestrator/context-discovery';
|
|
12
14
|
|
|
13
15
|
// --- Step-pattern authoring (a driver contributes step patterns via its descriptor) ---
|
|
14
16
|
export type { PatternContext, StepPattern, StepTemplateData } from './generators/test-generator/patterns/types';
|
|
@@ -47,6 +47,7 @@ export const AI_RULES_FILE_MAPPING: [string, string][] = [
|
|
|
47
47
|
['claude-skill-selector-fix.md', '.claude/skills/sungen-selector-fix/SKILL.md'],
|
|
48
48
|
['claude-skill-tc-review.md', '.claude/skills/sungen-tc-review/SKILL.md'],
|
|
49
49
|
['claude-skill-harness-audit.md', '.claude/skills/sungen-harness-audit/SKILL.md'],
|
|
50
|
+
['claude-skill-api-design.md', '.claude/skills/sungen-api-design/SKILL.md'],
|
|
50
51
|
['claude-skill-ingest-legacy.md', '.claude/skills/sungen-ingest-legacy/SKILL.md'],
|
|
51
52
|
['claude-skill-viewpoint.md', '.claude/skills/sungen-viewpoint/SKILL.md'],
|
|
52
53
|
['claude-skill-viewpoint-group-a-data-entry.md', '.claude/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
@@ -79,6 +80,7 @@ export const AI_RULES_FILE_MAPPING: [string, string][] = [
|
|
|
79
80
|
['github-skill-sungen-selector-fix.md', '.github/skills/sungen-selector-fix/SKILL.md'],
|
|
80
81
|
['github-skill-sungen-tc-review.md', '.github/skills/sungen-tc-review/SKILL.md'],
|
|
81
82
|
['github-skill-sungen-harness-audit.md', '.github/skills/sungen-harness-audit/SKILL.md'],
|
|
83
|
+
['github-skill-sungen-api-design.md', '.github/skills/sungen-api-design/SKILL.md'],
|
|
82
84
|
['github-skill-sungen-ingest-legacy.md', '.github/skills/sungen-ingest-legacy/SKILL.md'],
|
|
83
85
|
['github-skill-sungen-viewpoint.md', '.github/skills/sungen-viewpoint/SKILL.md'],
|
|
84
86
|
['github-skill-sungen-viewpoint-group-a-data-entry.md', '.github/skills/sungen-viewpoint/group-a-data-entry.md'],
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestration phase: Discover → Contextualize (AO-3).
|
|
3
|
+
*
|
|
4
|
+
* The capability SPI declared `discovery` (sources → Context slice) + `contextMapper` (Context →
|
|
5
|
+
* generation units) since R1, but nothing consumed them. This is the deterministic consumer the
|
|
6
|
+
* orchestration loop (`/sungen:design`) calls before generating: resolve the unit's capability,
|
|
7
|
+
* run ITS discovery + contextMapper, and hand back the normalized Context + the generation-unit
|
|
8
|
+
* work-list. Capability-agnostic — a screen, an api area, or a future `mobile/` unit all flow here.
|
|
9
|
+
*/
|
|
10
|
+
import { capabilityRegistry } from '../capabilities/registry';
|
|
11
|
+
import { discoverAndRegisterCapabilities } from '../capabilities/discover';
|
|
12
|
+
import type { Context, GenerationUnit } from '../capabilities/context';
|
|
13
|
+
|
|
14
|
+
export interface DiscoveredContext {
|
|
15
|
+
capability: string;
|
|
16
|
+
context: Context;
|
|
17
|
+
units: GenerationUnit[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Map a unit id (relative to qa/) to a discovery target. */
|
|
21
|
+
function targetForUnit(unitId: string): Context['target'] {
|
|
22
|
+
if (unitId.startsWith('api/')) return { kind: 'api', id: unitId };
|
|
23
|
+
if (unitId.startsWith('flows/')) return { kind: 'flow', id: unitId };
|
|
24
|
+
return { kind: 'screen', id: unitId };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Run the Discover → Contextualize phase for a unit. `unitId` is the catalog-resolution id
|
|
29
|
+
* (`<screen>` · `flows/<flow>` · `api/<area>` · `api/flows/<flow>`).
|
|
30
|
+
*/
|
|
31
|
+
export async function discoverUnitContext(unitId: string, cwd: string = process.cwd()): Promise<DiscoveredContext> {
|
|
32
|
+
discoverAndRegisterCapabilities();
|
|
33
|
+
const target = targetForUnit(unitId);
|
|
34
|
+
// The discovering capability is the first whose DiscoveryProvider claims the target; else the default.
|
|
35
|
+
const cap = capabilityRegistry.all().find((c) => c.discovery?.appliesTo?.(target))
|
|
36
|
+
?? (capabilityRegistry.defaultCapabilityId() ? capabilityRegistry.get(capabilityRegistry.defaultCapabilityId()!) : undefined);
|
|
37
|
+
|
|
38
|
+
let context: Context = { target: { ...target, capability: cap?.id }, sources: {}, facts: {} };
|
|
39
|
+
if (cap?.discovery) {
|
|
40
|
+
const slice = await cap.discovery.discover(target, { cwd });
|
|
41
|
+
context = {
|
|
42
|
+
target: { ...target, capability: cap.id },
|
|
43
|
+
sources: { ...context.sources, ...(slice.sources ?? {}) },
|
|
44
|
+
facts: { ...context.facts, ...(slice.facts ?? {}) },
|
|
45
|
+
...(slice.connectivity ? { connectivity: slice.connectivity } : {}),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const units = cap?.contextMapper?.decompose(context) ?? [];
|
|
49
|
+
return { capability: cap?.id ?? 'ui', context, units };
|
|
50
|
+
}
|
|
@@ -19,6 +19,12 @@ You are an **independent Senior QA Reviewer**. You did **not** write these tests
|
|
|
19
19
|
3. **Business-critical depth.** For cart / product-detail / filter / list viewpoints, do steps assert **DATA** (name, price, quantity, all-items-belong) — not just page/modal visibility? Recommend the concrete deep step: `User remember [X] text as {{v}}` + `... with {{v}}`, or `User see all [X] contain {{v}}`.
|
|
20
20
|
4. **@manual justification.** Is each `@manual` genuinely unautomatable (cross-screen/external/visual) — or a cop-out to dodge the gate? Cross-screen → should be a flow.
|
|
21
21
|
5. **Meaning-level duplicates & missing criticals** the keyword gate can't see.
|
|
22
|
+
6. **API units** (`qa/api/<area>/` — `@api` scenarios, no UI). Judge what the api gate can't:
|
|
23
|
+
- **Prove the effect, not the status.** A mutating endpoint's success path asserting only `{{r.status}} is 201` proves nothing about WHAT changed — demand a **body** assertion (`{{r.body.id}}` / `{{r.body.<field>}}`), a **`@query`** DB side-effect, or (idempotency) a `{{r.ok_count}}` invariant. This is the API businessDepth bar.
|
|
24
|
+
- **Error matrix coherent.** `@cases` rows are a real failure family (validation/auth/conflict) with realistic inputs → declared statuses, not padding.
|
|
25
|
+
- **Flows self-clean.** A CRUD/auth chain deletes what it created (final `@api:delete_*`) or is `@cleanup`-tagged.
|
|
26
|
+
- **Idempotency uses the DB oracle.** A "no double-charge / exactly once" claim is proven by `@concurrent` + a `@query` count, not HTTP status alone (status can lie under a race).
|
|
27
|
+
- **Auth negatives** exist for protected mutations (401/403), not just the happy path.
|
|
22
28
|
|
|
23
29
|
## Output (do NOT edit any file)
|
|
24
30
|
Return a concise verdict:
|
|
@@ -23,7 +23,11 @@ You are a **Senior QA Engineer** specialized in test case design. You structure
|
|
|
23
23
|
|
|
24
24
|
Parse **name** from `$ARGUMENTS`. If missing, ask the user.
|
|
25
25
|
|
|
26
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists →
|
|
26
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode. Else `qa/screens/<name>/` → screen mode. This determines paths, generation strategy, and CLI commands.
|
|
27
|
+
|
|
28
|
+
## API unit mode (driver-api)
|
|
29
|
+
|
|
30
|
+
If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the design loop differs — **no visual capture, no selectors**; the contract is the named-endpoint catalog. **Follow the `sungen-api-design` skill end-to-end** instead of the screen/flow steps below: `sungen context --api <name>` (discover) → API viewpoint overview → generate `@api`/`@cases`/flow/`@concurrent`/`@query` scenarios → **`sungen audit --api <name>` gate + the `sungen-reviewer` sub-agent + repair loop to businessDepth ≥ 0.7** → record + trace. Then jump to the "Converge" next-step options (recommend `/sungen:run-test <name>`). The capture / viewpoint-group / selector steps do **not** apply.
|
|
27
31
|
|
|
28
32
|
## Steps
|
|
29
33
|
|
|
@@ -30,7 +30,22 @@ If the count is 0 → use `AskUserQuestion` to offer:
|
|
|
30
30
|
|
|
31
31
|
Skip this pre-flight when `--env` matches the base locale (no overlay needed in that case).
|
|
32
32
|
|
|
33
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
33
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
34
|
+
|
|
35
|
+
## API unit mode (driver-api) — no selectors
|
|
36
|
+
|
|
37
|
+
If the unit is **api-first**, skip every selector/capture phase (an API test has no DOM). Instead:
|
|
38
|
+
|
|
39
|
+
1. **Resolve the datasource** — ensure the `kind: api` datasource's `base_url` + auth are wired in `qa/datasources.yaml` + `.env.qa` (the `${X_URL}` key from `sungen api init`). A `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
40
|
+
2. **Compile**: `[ -x ./bin/sungen.js ] && ./bin/sungen.js generate --api <name> || npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
|
|
41
|
+
3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts` (per-spec JSON results, as below).
|
|
42
|
+
4. **Auto-fix** (no selectors — the failure classes differ): use `sungen-error-mapping`.
|
|
43
|
+
- **401/403** → wire `@hybrid` + `@auth:<role>` (reuse the UI session) or the catalog `Bearer :token` header; suggest `sungen makeauth <role>`.
|
|
44
|
+
- **datasource/base_url unresolved** → set the `${X_URL}` key in `.env.qa`.
|
|
45
|
+
- **missing/empty bound param** → trace `{{var}}` to test-data or a prior `@api` response; fill it.
|
|
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
|
+
- **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.)*
|
|
34
49
|
|
|
35
50
|
## Pre-run (phased — per `sungen-selector-fix` skill)
|
|
36
51
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-api-design
|
|
3
|
+
description: The API-first design loop for an api unit (qa/api/<area> or qa/api/flows/<flow>) — discover the catalog, lay out the API viewpoints, generate @api/@cases/flow/@concurrent scenarios, then drive the sungen audit --api gate + reviewer + repair to a high businessDepth (≥0.7). Use when create-test/run-test detects an api unit (no selectors, no visual capture).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API design loop (driver-api · Orchestration + Harness)
|
|
7
|
+
|
|
8
|
+
Use this when the unit is **api-first** — `qa/api/<area>/` or `qa/api/flows/<flow>/`. There are **no selectors and no visual capture**: the contract is the **named-endpoint catalog** (`api/apis.yaml`), referenced by `@api:<name>`. QA writes **no HTTP code**. Full annotation reference: the **API Steps** guide (`@api` / `@cases` / flows / `@concurrent` / `@hybrid`).
|
|
9
|
+
|
|
10
|
+
## The loop (mirror of /sungen:design, API-native)
|
|
11
|
+
|
|
12
|
+
### 1. Discover (no capture)
|
|
13
|
+
Run `sungen context --api <name>` — it reads the catalog and prints the **endpoints** + the **generation units** (one `matrix` unit per endpoint, an `async` unit per mutating endpoint, a `flow` unit for an api flow). Read `qa/api/<name>/requirements/spec.md` if present. No `apis.yaml` yet? → `sungen api import <openapi|csv>` or `sungen api add --area <name>` first.
|
|
14
|
+
|
|
15
|
+
### 2. API viewpoint overview (by method-profile)
|
|
16
|
+
For each endpoint, cover its viewpoints — severity-weighted by method:
|
|
17
|
+
|
|
18
|
+
| Profile | Endpoints | Must cover | Then |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| read | GET, HEAD | `contract` (status + body shape) | `pagination`/`filter` (list), `not-found` (by-id) |
|
|
21
|
+
| mutating | POST/PUT/PATCH/DELETE | `contract`, `error` (validation/4xx/auth) | `idempotency` (`@concurrent`), `side-effect` (`@query`) |
|
|
22
|
+
|
|
23
|
+
Bands: **~70%** success+failure matrix · **~20%** flows (auth/CRUD chains) · **~10%** async/idempotency.
|
|
24
|
+
|
|
25
|
+
### 3. Generate (incremental — never the whole suite in one Write)
|
|
26
|
+
- **Contract**: `@api:<name>` + `expect {{name.status}} is …` **and a body assertion** (`{{name.body.<path>}}`).
|
|
27
|
+
- **Error matrix**: `@api:<name>(p={{p}}) @cases:<dataset>` — one scenario, a dataset of `input → expected status`.
|
|
28
|
+
- **Flow**: ordered `@api` tags threading a prior response (`token={{login.body.token}}` → the catalog `Bearer :token` header; `id={{create.body.id}}` → a path param). Self-clean (delete what you create).
|
|
29
|
+
- **Idempotency**: `@api:<name> @concurrent:N` + `expect {{name.ok_count}} is 1`, cross-checked with `@query` (the DB is the oracle).
|
|
30
|
+
|
|
31
|
+
### 4. Gate + repair (always — businessDepth ≥ 0.7 is the bar)
|
|
32
|
+
Run `sungen audit --api <name>`; read `gateStatus` + `findings`. Then the **semantic reviewer** (sungen-reviewer sub-agent, API criteria). Repair **both** (budget 3 rounds), re-audit until PASS:
|
|
33
|
+
|
|
34
|
+
| Finding | Repair |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `VIEWPOINT-API-CONTRACT` | the endpoint is invoked but its response is never asserted → add `expect {{name.status}}` + a `{{name.body.…}}` check |
|
|
37
|
+
| `VIEWPOINT-API-ERROR` | a mutating endpoint has no failure scenario → add a `@cases` error matrix (or an explicit 4xx) |
|
|
38
|
+
| `VIEWPOINT-API-IDEMPOTENCY` | a mutating endpoint has no race check → add `@concurrent:N` + a `@query` DB cross-check |
|
|
39
|
+
| **`DEPTH-FAIL`** (businessDepth < 0.7) | a **mutating success** scenario asserts only `status` → make it **prove the effect**: assert a response **body** field, a **`@query`** side-effect, or a **`@concurrent` `ok_count`** invariant. (An error/`@cases` scenario proving the status is correct — it is *not* depth-required.) |
|
|
40
|
+
|
|
41
|
+
Stop when the gate PASSes + businessDepth ≥ 0.7, or the budget is exhausted → report residual gaps honestly (mark genuinely-unautomatable cases `@manual` with an oracle). Never fake a pass.
|
|
42
|
+
|
|
43
|
+
### 5. Record + converge
|
|
44
|
+
`sungen manifest --api <name>` (reuse) and ledger each phase; show the trace + the HUMAN-LOOP FOCUS. (Integrity `script-check`/`trace` for api: see run-test.)
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
- **No HTTP, no selectors** — only `.feature` + the reviewed `apis.yaml` + `test-data`.
|
|
48
|
+
- **Non-prod default** — a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
49
|
+
- **The DB is the oracle** for idempotency/side-effects — HTTP status alone can lie; pair `@api` with `@query`.
|
|
@@ -18,7 +18,11 @@ You are a **Senior QA Engineer**. You structure test cases by viewpoint categori
|
|
|
18
18
|
|
|
19
19
|
- **name** — ${input:name:screen or flow name (e.g., login, award-submission)}
|
|
20
20
|
|
|
21
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
21
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
22
|
+
|
|
23
|
+
## API unit mode (driver-api)
|
|
24
|
+
|
|
25
|
+
If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the design loop differs — **no visual capture, no selectors**; the contract is the named-endpoint catalog. **Follow the `sungen-api-design` skill end-to-end** instead of the screen/flow steps: `sungen context --api <name>` (discover) → API viewpoint overview → generate `@api`/`@cases`/flow/`@concurrent`/`@query` scenarios → **`sungen audit --api <name>` gate + reviewer + repair loop to businessDepth ≥ 0.7** → record + trace. Then recommend `/sungen-run-test <name>`. The capture / viewpoint-group / selector steps do **not** apply.
|
|
22
26
|
|
|
23
27
|
## Steps
|
|
24
28
|
|
|
@@ -30,7 +30,16 @@ Count 0 → offer the user:
|
|
|
30
30
|
|
|
31
31
|
Skip when `--env` matches the base locale.
|
|
32
32
|
|
|
33
|
-
**Auto-detect context**: check if `qa/flows/<name>/` exists → flow mode (base path: `qa/flows/<name>/`). Else
|
|
33
|
+
**Auto-detect context**: check if `qa/api/<name>/` or `qa/api/flows/<name>/` exists → **API unit mode** (below). Else if `qa/flows/<name>/` → flow mode (base path: `qa/flows/<name>/`). Else `qa/screens/<name>/` → screen mode (base path: `qa/screens/<name>/`).
|
|
34
|
+
|
|
35
|
+
## API unit mode (driver-api) — no selectors
|
|
36
|
+
|
|
37
|
+
If the unit is **api-first**, skip every selector/capture phase (an API test has no DOM):
|
|
38
|
+
1. **Resolve the datasource** — `base_url` + auth wired in `qa/datasources.yaml` + `.env.qa` (`${X_URL}` from `sungen api init`); a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
39
|
+
2. **Compile**: `npx sungen generate --api <name>` → `specs/generated/api/<name>/`.
|
|
40
|
+
3. **Run**: `npx playwright test specs/generated/api/<name>/<name>.spec.ts`.
|
|
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.)*
|
|
34
43
|
|
|
35
44
|
## Pre-run (phased — per `sungen-selector-fix` skill)
|
|
36
45
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-api-design
|
|
3
|
+
description: The API-first design loop for an api unit (qa/api/<area> or qa/api/flows/<flow>) — discover the catalog, lay out the API viewpoints, generate @api/@cases/flow/@concurrent scenarios, then drive the sungen audit --api gate + reviewer + repair to a high businessDepth (≥0.7). Use when create-test/run-test detects an api unit (no selectors, no visual capture).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API design loop (driver-api · Orchestration + Harness)
|
|
7
|
+
|
|
8
|
+
Use this when the unit is **api-first** — `qa/api/<area>/` or `qa/api/flows/<flow>/`. There are **no selectors and no visual capture**: the contract is the **named-endpoint catalog** (`api/apis.yaml`), referenced by `@api:<name>`. QA writes **no HTTP code**. Full annotation reference: the **API Steps** guide (`@api` / `@cases` / flows / `@concurrent` / `@hybrid`).
|
|
9
|
+
|
|
10
|
+
## The loop (mirror of /sungen:design, API-native)
|
|
11
|
+
|
|
12
|
+
### 1. Discover (no capture)
|
|
13
|
+
Run `sungen context --api <name>` — it reads the catalog and prints the **endpoints** + the **generation units** (one `matrix` unit per endpoint, an `async` unit per mutating endpoint, a `flow` unit for an api flow). Read `qa/api/<name>/requirements/spec.md` if present. No `apis.yaml` yet? → `sungen api import <openapi|csv>` or `sungen api add --area <name>` first.
|
|
14
|
+
|
|
15
|
+
### 2. API viewpoint overview (by method-profile)
|
|
16
|
+
For each endpoint, cover its viewpoints — severity-weighted by method:
|
|
17
|
+
|
|
18
|
+
| Profile | Endpoints | Must cover | Then |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| read | GET, HEAD | `contract` (status + body shape) | `pagination`/`filter` (list), `not-found` (by-id) |
|
|
21
|
+
| mutating | POST/PUT/PATCH/DELETE | `contract`, `error` (validation/4xx/auth) | `idempotency` (`@concurrent`), `side-effect` (`@query`) |
|
|
22
|
+
|
|
23
|
+
Bands: **~70%** success+failure matrix · **~20%** flows (auth/CRUD chains) · **~10%** async/idempotency.
|
|
24
|
+
|
|
25
|
+
### 3. Generate (incremental — never the whole suite in one Write)
|
|
26
|
+
- **Contract**: `@api:<name>` + `expect {{name.status}} is …` **and a body assertion** (`{{name.body.<path>}}`).
|
|
27
|
+
- **Error matrix**: `@api:<name>(p={{p}}) @cases:<dataset>` — one scenario, a dataset of `input → expected status`.
|
|
28
|
+
- **Flow**: ordered `@api` tags threading a prior response (`token={{login.body.token}}` → the catalog `Bearer :token` header; `id={{create.body.id}}` → a path param). Self-clean (delete what you create).
|
|
29
|
+
- **Idempotency**: `@api:<name> @concurrent:N` + `expect {{name.ok_count}} is 1`, cross-checked with `@query` (the DB is the oracle).
|
|
30
|
+
|
|
31
|
+
### 4. Gate + repair (always — businessDepth ≥ 0.7 is the bar)
|
|
32
|
+
Run `sungen audit --api <name>`; read `gateStatus` + `findings`. Then the **semantic reviewer** (sungen-reviewer sub-agent, API criteria). Repair **both** (budget 3 rounds), re-audit until PASS:
|
|
33
|
+
|
|
34
|
+
| Finding | Repair |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `VIEWPOINT-API-CONTRACT` | the endpoint is invoked but its response is never asserted → add `expect {{name.status}}` + a `{{name.body.…}}` check |
|
|
37
|
+
| `VIEWPOINT-API-ERROR` | a mutating endpoint has no failure scenario → add a `@cases` error matrix (or an explicit 4xx) |
|
|
38
|
+
| `VIEWPOINT-API-IDEMPOTENCY` | a mutating endpoint has no race check → add `@concurrent:N` + a `@query` DB cross-check |
|
|
39
|
+
| **`DEPTH-FAIL`** (businessDepth < 0.7) | a **mutating success** scenario asserts only `status` → make it **prove the effect**: assert a response **body** field, a **`@query`** side-effect, or a **`@concurrent` `ok_count`** invariant. (An error/`@cases` scenario proving the status is correct — it is *not* depth-required.) |
|
|
40
|
+
|
|
41
|
+
Stop when the gate PASSes + businessDepth ≥ 0.7, or the budget is exhausted → report residual gaps honestly (mark genuinely-unautomatable cases `@manual` with an oracle). Never fake a pass.
|
|
42
|
+
|
|
43
|
+
### 5. Record + converge
|
|
44
|
+
`sungen manifest --api <name>` (reuse) and ledger each phase; show the trace + the HUMAN-LOOP FOCUS. (Integrity `script-check`/`trace` for api: see run-test.)
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
- **No HTTP, no selectors** — only `.feature` + the reviewed `apis.yaml` + `test-data`.
|
|
48
|
+
- **Non-prod default** — a `production` datasource is refused unless `SUNGEN_ALLOW_PROD=1`.
|
|
49
|
+
- **The DB is the oracle** for idempotency/side-effects — HTTP status alone can lie; pair `@api` with `@query`.
|