@sun-asterisk/sungen 3.1.2-beta.99 → 3.2.0-beta.141
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/capabilities/context.d.ts +17 -0
- package/dist/capabilities/context.d.ts.map +1 -1
- package/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +70 -9
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/capabilities/registry.d.ts +3 -1
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/capabilities/sensor.d.ts +3 -0
- package/dist/capabilities/sensor.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +17 -11
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +57 -5
- package/dist/cli/commands/capability.js.map +1 -1
- 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 +91 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +42 -30
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +28 -5
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/ledger.d.ts.map +1 -1
- package/dist/cli/commands/ledger.js +15 -5
- package/dist/cli/commands/ledger.js.map +1 -1
- package/dist/cli/commands/manifest.d.ts.map +1 -1
- package/dist/cli/commands/manifest.js +10 -9
- package/dist/cli/commands/manifest.js.map +1 -1
- package/dist/cli/commands/repair.d.ts +8 -0
- package/dist/cli/commands/repair.d.ts.map +1 -0
- package/dist/cli/commands/repair.js +97 -0
- package/dist/cli/commands/repair.js.map +1 -0
- package/dist/cli/commands/script-check.d.ts.map +1 -1
- package/dist/cli/commands/script-check.js +13 -9
- package/dist/cli/commands/script-check.js.map +1 -1
- package/dist/cli/commands/trace.d.ts.map +1 -1
- package/dist/cli/commands/trace.js +7 -4
- package/dist/cli/commands/trace.js.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/test-generator/code-generator.d.ts +7 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +112 -42
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/harness/annotation-overrides.d.ts +3 -1
- package/dist/harness/annotation-overrides.d.ts.map +1 -1
- package/dist/harness/annotation-overrides.js +3 -1
- package/dist/harness/annotation-overrides.js.map +1 -1
- package/dist/harness/audit.d.ts +9 -1
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +114 -12
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/capability-plan.d.ts +14 -0
- package/dist/harness/capability-plan.d.ts.map +1 -1
- package/dist/harness/capability-plan.js +63 -1
- package/dist/harness/capability-plan.js.map +1 -1
- package/dist/harness/data-driven-lint.d.ts.map +1 -1
- package/dist/harness/data-driven-lint.js +23 -0
- package/dist/harness/data-driven-lint.js.map +1 -1
- package/dist/harness/flow-check.d.ts +9 -0
- package/dist/harness/flow-check.d.ts.map +1 -1
- package/dist/harness/flow-check.js +13 -6
- package/dist/harness/flow-check.js.map +1 -1
- package/dist/harness/intent.d.ts +6 -0
- package/dist/harness/intent.d.ts.map +1 -1
- package/dist/harness/intent.js +20 -4
- package/dist/harness/intent.js.map +1 -1
- package/dist/harness/ledger.d.ts.map +1 -1
- package/dist/harness/ledger.js +3 -2
- package/dist/harness/ledger.js.map +1 -1
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +3 -2
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/parse.d.ts +1 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +3 -0
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/quality-gates.js +1 -1
- package/dist/harness/quality-gates.js.map +1 -1
- package/dist/harness/query-catalog.d.ts.map +1 -1
- package/dist/harness/query-catalog.js +0 -0
- package/dist/harness/query-catalog.js.map +1 -1
- package/dist/harness/repair.d.ts +20 -0
- package/dist/harness/repair.d.ts.map +1 -0
- package/dist/harness/repair.js +111 -0
- package/dist/harness/repair.js.map +1 -0
- package/dist/harness/script-check.d.ts +3 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +22 -8
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/sensors.d.ts +40 -0
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +54 -2
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/trace.d.ts.map +1 -1
- package/dist/harness/trace.js +4 -3
- package/dist/harness/trace.js.map +1 -1
- package/dist/harness/unit-paths.d.ts +3 -0
- package/dist/harness/unit-paths.d.ts.map +1 -0
- package/dist/harness/unit-paths.js +52 -0
- package/dist/harness/unit-paths.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -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 +7 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +6 -2
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +18 -1
- package/dist/orchestrator/templates/ai-instructions/claude-skill-api-design.md +62 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +2 -1
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +16 -2
- package/dist/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +14 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -2
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +11 -1
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +62 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +2 -1
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +16 -2
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +14 -0
- package/dist/orchestrator/templates/specs-api.d.ts +38 -2
- package/dist/orchestrator/templates/specs-api.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-api.js +65 -22
- package/dist/orchestrator/templates/specs-api.js.map +1 -1
- package/dist/orchestrator/templates/specs-api.ts +71 -18
- package/dist/orchestrator/templates/specs-db.d.ts +3 -0
- package/dist/orchestrator/templates/specs-db.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-db.js +78 -1
- package/dist/orchestrator/templates/specs-db.js.map +1 -1
- package/dist/orchestrator/templates/specs-db.ts +78 -1
- package/dist/orchestrator/templates/specs-test-data.ts +2 -1
- package/package.json +2 -2
- package/src/capabilities/context.ts +19 -0
- package/src/capabilities/discover.ts +27 -7
- package/src/capabilities/registry.ts +3 -1
- package/src/capabilities/sensor.ts +1 -1
- package/src/cli/commands/audit.ts +15 -9
- package/src/cli/commands/capability.ts +53 -5
- package/src/cli/commands/context.ts +52 -0
- package/src/cli/commands/delivery.ts +40 -31
- package/src/cli/commands/generate.ts +30 -5
- package/src/cli/commands/ledger.ts +13 -5
- package/src/cli/commands/manifest.ts +9 -7
- package/src/cli/commands/repair.ts +57 -0
- package/src/cli/commands/script-check.ts +12 -8
- package/src/cli/commands/trace.ts +7 -4
- package/src/cli/index.ts +4 -0
- package/src/generators/test-generator/code-generator.ts +115 -40
- package/src/harness/annotation-overrides.ts +3 -1
- package/src/harness/audit.ts +115 -15
- package/src/harness/capability-plan.ts +51 -1
- package/src/harness/data-driven-lint.ts +20 -0
- package/src/harness/flow-check.ts +15 -6
- package/src/harness/intent.ts +25 -4
- package/src/harness/ledger.ts +3 -2
- package/src/harness/manifest.ts +3 -2
- package/src/harness/parse.ts +4 -0
- package/src/harness/quality-gates.ts +1 -1
- package/src/harness/query-catalog.ts +0 -0
- package/src/harness/repair.ts +75 -0
- package/src/harness/script-check.ts +25 -8
- package/src/harness/sensors.ts +71 -2
- package/src/harness/trace.ts +4 -3
- package/src/harness/unit-paths.ts +14 -0
- package/src/index.ts +4 -2
- 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 +7 -1
- package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +6 -2
- package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +18 -1
- package/src/orchestrator/templates/ai-instructions/claude-skill-api-design.md +62 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +2 -1
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +16 -2
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +14 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -2
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +11 -1
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +62 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +2 -1
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +16 -2
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +14 -0
- package/src/orchestrator/templates/specs-api.ts +71 -18
- package/src/orchestrator/templates/specs-db.ts +78 -1
- package/src/orchestrator/templates/specs-test-data.ts +2 -1
|
@@ -21,12 +21,73 @@ const ident = (s: string): string => {
|
|
|
21
21
|
return s;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
interface SshConfig {
|
|
25
|
+
host: string; // jump host reachable from the runner
|
|
26
|
+
port?: number; // default 22
|
|
27
|
+
user: string;
|
|
28
|
+
private_key?: string; // PEM contents (from ${VAR} in .env.qa) — preferred for CI
|
|
29
|
+
private_key_path?: string; // or a filesystem path (local dev)
|
|
30
|
+
passphrase?: string; // for an encrypted key
|
|
31
|
+
known_host?: string; // base64 of the server's host key to pin (optional; else warn-and-proceed)
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
interface DataSourceConfig {
|
|
25
35
|
engine: 'postgres' | 'mysql' | 'sqlite';
|
|
26
36
|
url: string;
|
|
27
37
|
readonly?: boolean;
|
|
28
38
|
statement_timeout_ms?: number;
|
|
29
39
|
max_rows?: number;
|
|
40
|
+
// Cách B (fallback): tunnel the DB SOCKET through an SSH bastion. DB-only — the browser/E2E
|
|
41
|
+
// still run on the runner; only PG traffic crosses. See docs/spec/sungen_data_driver_ssh_tunnel_spec.md.
|
|
42
|
+
ssh?: SshConfig;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Open a local TCP forward (127.0.0.1:<ephemeral> → ssh bastion → dstHost:dstPort) for a DB socket.
|
|
47
|
+
* Sockets are unref()'d so a dangling tunnel never keeps the test process alive after the run.
|
|
48
|
+
*/
|
|
49
|
+
async function openSshTunnel(ssh: SshConfig, dstHost: string, dstPort: number): Promise<{ host: string; port: number; close: () => void }> {
|
|
50
|
+
const { Client } = require('ssh2');
|
|
51
|
+
const net = require('net');
|
|
52
|
+
const privateKey = ssh.private_key
|
|
53
|
+
? ssh.private_key
|
|
54
|
+
: ssh.private_key_path
|
|
55
|
+
? fs.readFileSync(ssh.private_key_path.replace(/^~(?=\/)/, process.env.HOME || ''), 'utf8')
|
|
56
|
+
: undefined;
|
|
57
|
+
if (!privateKey) throw new Error('Data Driver: datasource `ssh` requires `private_key` or `private_key_path`.');
|
|
58
|
+
|
|
59
|
+
const conn = new Client();
|
|
60
|
+
await new Promise<void>((resolve, reject) => {
|
|
61
|
+
conn.on('ready', resolve).on('error', reject).connect({
|
|
62
|
+
host: ssh.host,
|
|
63
|
+
port: ssh.port ?? 22,
|
|
64
|
+
username: ssh.user,
|
|
65
|
+
privateKey,
|
|
66
|
+
passphrase: ssh.passphrase,
|
|
67
|
+
hostVerifier: (key: Buffer) => {
|
|
68
|
+
const got = Buffer.isBuffer(key) ? key.toString('base64') : String(key);
|
|
69
|
+
if (ssh.known_host) {
|
|
70
|
+
if (got === ssh.known_host.trim()) return true;
|
|
71
|
+
throw new Error(`Data Driver: SSH host-key mismatch for ${ssh.host} — refused (known_host pin).`);
|
|
72
|
+
}
|
|
73
|
+
console.warn(`Data Driver: SSH host key for ${ssh.host} is not pinned (set datasource ssh.known_host to verify). Proceeding (TOFU).`);
|
|
74
|
+
return true;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const server = net.createServer((sock: any) => {
|
|
80
|
+
conn.forwardOut(sock.remoteAddress || '127.0.0.1', sock.remotePort || 0, dstHost, dstPort, (err: any, stream: any) => {
|
|
81
|
+
if (err) { sock.destroy(); return; }
|
|
82
|
+
sock.pipe(stream).pipe(sock);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
await new Promise<void>((resolve, reject) => server.on('error', reject).listen(0, '127.0.0.1', () => resolve()));
|
|
86
|
+
const addr = server.address();
|
|
87
|
+
const port = addr && typeof addr === 'object' ? addr.port : 0;
|
|
88
|
+
server.unref(); // don't keep the event loop alive after tests
|
|
89
|
+
try { (conn as any)._sock?.unref?.(); } catch { /* best-effort */ }
|
|
90
|
+
return { host: '127.0.0.1', port, close: () => { try { server.close(); } catch {} try { conn.end(); } catch {} } };
|
|
30
91
|
}
|
|
31
92
|
|
|
32
93
|
function loadEnvQa(): void {
|
|
@@ -64,6 +125,7 @@ type Engine = { query(sql: string, params: any[]): Promise<any[]>; };
|
|
|
64
125
|
class DataSource {
|
|
65
126
|
private configs: Record<string, DataSourceConfig> | null = null;
|
|
66
127
|
private engines = new Map<string, Engine>();
|
|
128
|
+
private tunnels: Array<{ close: () => void }> = [];
|
|
67
129
|
|
|
68
130
|
private cfg(name?: string): { key: string; conf: DataSourceConfig } {
|
|
69
131
|
if (!this.configs) this.configs = loadConfig();
|
|
@@ -79,10 +141,19 @@ class DataSource {
|
|
|
79
141
|
if (!conf.url) throw new Error(`Data Driver: datasource "${key}" has no url (set it in .env.qa).`);
|
|
80
142
|
let engine: Engine;
|
|
81
143
|
if (conf.engine === 'postgres') {
|
|
144
|
+
let connectionString = conf.url;
|
|
145
|
+
if (conf.ssh) { // Cách B: tunnel the DB socket through a bastion
|
|
146
|
+
const u = new URL(conf.url);
|
|
147
|
+
const t = await openSshTunnel(conf.ssh, u.hostname, Number(u.port || 5432));
|
|
148
|
+
this.tunnels.push(t);
|
|
149
|
+
u.hostname = t.host; u.port = String(t.port); // rewrite host:port → 127.0.0.1:<tunnel> (keep user/pass/db/query)
|
|
150
|
+
connectionString = u.toString();
|
|
151
|
+
}
|
|
82
152
|
const { Pool } = require('pg');
|
|
83
|
-
const pool = new Pool({ connectionString
|
|
153
|
+
const pool = new Pool({ connectionString, max: 2, statement_timeout: conf.statement_timeout_ms ?? 4000 });
|
|
84
154
|
engine = { query: async (sql, params) => (await pool.query(sql, params)).rows };
|
|
85
155
|
} else if (conf.engine === 'sqlite') {
|
|
156
|
+
if (conf.ssh) console.warn(`Data Driver: datasource "${key}" sets ssh: but engine is sqlite (file-based) — ssh ignored.`);
|
|
86
157
|
const Database = require('better-sqlite3');
|
|
87
158
|
const db = new Database(conf.url.replace(/^sqlite:/, ''), { readonly: conf.readonly !== false });
|
|
88
159
|
engine = { query: async (sql, params) => db.prepare(sql).all(...params) };
|
|
@@ -93,6 +164,12 @@ class DataSource {
|
|
|
93
164
|
return { engine, conf };
|
|
94
165
|
}
|
|
95
166
|
|
|
167
|
+
/** Close any open SSH tunnels (optional explicit teardown; tunnels are unref'd so the process exits regardless). */
|
|
168
|
+
close(): void {
|
|
169
|
+
for (const t of this.tunnels) t.close();
|
|
170
|
+
this.tunnels = [];
|
|
171
|
+
}
|
|
172
|
+
|
|
96
173
|
private build(table: string, filter: Record<string, any>): { sql: string; params: any[] } {
|
|
97
174
|
const cols = Object.keys(filter);
|
|
98
175
|
const where = cols.map((c, i) => `${ident(c)} = $${i + 1}`).join(' AND ');
|
|
@@ -23,7 +23,8 @@ export class TestDataLoader {
|
|
|
23
23
|
*/
|
|
24
24
|
static load(screenName: string, featureName: string): TestDataLoader {
|
|
25
25
|
let baseDir: string;
|
|
26
|
-
if (screenName.startsWith('flows/')) {
|
|
26
|
+
if (screenName.startsWith('flows/') || screenName.startsWith('api/')) {
|
|
27
|
+
// flows/<flow> · api/<area> · api/flows/<flow> → qa/<screenName>/test-data
|
|
27
28
|
baseDir = path.join(process.cwd(), 'qa', screenName, 'test-data');
|
|
28
29
|
} else {
|
|
29
30
|
baseDir = path.join(process.cwd(), 'qa', 'screens', screenName, 'test-data');
|