@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.
Files changed (192) hide show
  1. package/dist/capabilities/context.d.ts +17 -0
  2. package/dist/capabilities/context.d.ts.map +1 -1
  3. package/dist/capabilities/discover.d.ts.map +1 -1
  4. package/dist/capabilities/discover.js +70 -9
  5. package/dist/capabilities/discover.js.map +1 -1
  6. package/dist/capabilities/registry.d.ts +3 -1
  7. package/dist/capabilities/registry.d.ts.map +1 -1
  8. package/dist/capabilities/registry.js.map +1 -1
  9. package/dist/capabilities/sensor.d.ts +3 -0
  10. package/dist/capabilities/sensor.d.ts.map +1 -1
  11. package/dist/cli/commands/audit.d.ts.map +1 -1
  12. package/dist/cli/commands/audit.js +17 -11
  13. package/dist/cli/commands/audit.js.map +1 -1
  14. package/dist/cli/commands/capability.d.ts.map +1 -1
  15. package/dist/cli/commands/capability.js +57 -5
  16. package/dist/cli/commands/capability.js.map +1 -1
  17. package/dist/cli/commands/context.d.ts +9 -0
  18. package/dist/cli/commands/context.d.ts.map +1 -0
  19. package/dist/cli/commands/context.js +91 -0
  20. package/dist/cli/commands/context.js.map +1 -0
  21. package/dist/cli/commands/delivery.d.ts.map +1 -1
  22. package/dist/cli/commands/delivery.js +42 -30
  23. package/dist/cli/commands/delivery.js.map +1 -1
  24. package/dist/cli/commands/generate.d.ts.map +1 -1
  25. package/dist/cli/commands/generate.js +28 -5
  26. package/dist/cli/commands/generate.js.map +1 -1
  27. package/dist/cli/commands/ledger.d.ts.map +1 -1
  28. package/dist/cli/commands/ledger.js +15 -5
  29. package/dist/cli/commands/ledger.js.map +1 -1
  30. package/dist/cli/commands/manifest.d.ts.map +1 -1
  31. package/dist/cli/commands/manifest.js +10 -9
  32. package/dist/cli/commands/manifest.js.map +1 -1
  33. package/dist/cli/commands/repair.d.ts +8 -0
  34. package/dist/cli/commands/repair.d.ts.map +1 -0
  35. package/dist/cli/commands/repair.js +97 -0
  36. package/dist/cli/commands/repair.js.map +1 -0
  37. package/dist/cli/commands/script-check.d.ts.map +1 -1
  38. package/dist/cli/commands/script-check.js +13 -9
  39. package/dist/cli/commands/script-check.js.map +1 -1
  40. package/dist/cli/commands/trace.d.ts.map +1 -1
  41. package/dist/cli/commands/trace.js +7 -4
  42. package/dist/cli/commands/trace.js.map +1 -1
  43. package/dist/cli/index.js +4 -0
  44. package/dist/cli/index.js.map +1 -1
  45. package/dist/generators/test-generator/code-generator.d.ts +7 -0
  46. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  47. package/dist/generators/test-generator/code-generator.js +112 -42
  48. package/dist/generators/test-generator/code-generator.js.map +1 -1
  49. package/dist/harness/annotation-overrides.d.ts +3 -1
  50. package/dist/harness/annotation-overrides.d.ts.map +1 -1
  51. package/dist/harness/annotation-overrides.js +3 -1
  52. package/dist/harness/annotation-overrides.js.map +1 -1
  53. package/dist/harness/audit.d.ts +9 -1
  54. package/dist/harness/audit.d.ts.map +1 -1
  55. package/dist/harness/audit.js +114 -12
  56. package/dist/harness/audit.js.map +1 -1
  57. package/dist/harness/capability-plan.d.ts +14 -0
  58. package/dist/harness/capability-plan.d.ts.map +1 -1
  59. package/dist/harness/capability-plan.js +63 -1
  60. package/dist/harness/capability-plan.js.map +1 -1
  61. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  62. package/dist/harness/data-driven-lint.js +23 -0
  63. package/dist/harness/data-driven-lint.js.map +1 -1
  64. package/dist/harness/flow-check.d.ts +9 -0
  65. package/dist/harness/flow-check.d.ts.map +1 -1
  66. package/dist/harness/flow-check.js +13 -6
  67. package/dist/harness/flow-check.js.map +1 -1
  68. package/dist/harness/intent.d.ts +6 -0
  69. package/dist/harness/intent.d.ts.map +1 -1
  70. package/dist/harness/intent.js +20 -4
  71. package/dist/harness/intent.js.map +1 -1
  72. package/dist/harness/ledger.d.ts.map +1 -1
  73. package/dist/harness/ledger.js +3 -2
  74. package/dist/harness/ledger.js.map +1 -1
  75. package/dist/harness/manifest.d.ts.map +1 -1
  76. package/dist/harness/manifest.js +3 -2
  77. package/dist/harness/manifest.js.map +1 -1
  78. package/dist/harness/parse.d.ts +1 -0
  79. package/dist/harness/parse.d.ts.map +1 -1
  80. package/dist/harness/parse.js +3 -0
  81. package/dist/harness/parse.js.map +1 -1
  82. package/dist/harness/quality-gates.js +1 -1
  83. package/dist/harness/quality-gates.js.map +1 -1
  84. package/dist/harness/query-catalog.d.ts.map +1 -1
  85. package/dist/harness/query-catalog.js +0 -0
  86. package/dist/harness/query-catalog.js.map +1 -1
  87. package/dist/harness/repair.d.ts +20 -0
  88. package/dist/harness/repair.d.ts.map +1 -0
  89. package/dist/harness/repair.js +111 -0
  90. package/dist/harness/repair.js.map +1 -0
  91. package/dist/harness/script-check.d.ts +3 -1
  92. package/dist/harness/script-check.d.ts.map +1 -1
  93. package/dist/harness/script-check.js +22 -8
  94. package/dist/harness/script-check.js.map +1 -1
  95. package/dist/harness/sensors.d.ts +40 -0
  96. package/dist/harness/sensors.d.ts.map +1 -1
  97. package/dist/harness/sensors.js +54 -2
  98. package/dist/harness/sensors.js.map +1 -1
  99. package/dist/harness/trace.d.ts.map +1 -1
  100. package/dist/harness/trace.js +4 -3
  101. package/dist/harness/trace.js.map +1 -1
  102. package/dist/harness/unit-paths.d.ts +3 -0
  103. package/dist/harness/unit-paths.d.ts.map +1 -0
  104. package/dist/harness/unit-paths.js +52 -0
  105. package/dist/harness/unit-paths.js.map +1 -0
  106. package/dist/index.d.ts +4 -2
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +5 -1
  109. package/dist/index.js.map +1 -1
  110. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  111. package/dist/orchestrator/ai-rules-updater.js +2 -0
  112. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  113. package/dist/orchestrator/context-discovery.d.ts +12 -0
  114. package/dist/orchestrator/context-discovery.d.ts.map +1 -0
  115. package/dist/orchestrator/context-discovery.js +46 -0
  116. package/dist/orchestrator/context-discovery.js.map +1 -0
  117. package/dist/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +7 -1
  118. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +6 -2
  119. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +18 -1
  120. package/dist/orchestrator/templates/ai-instructions/claude-skill-api-design.md +62 -0
  121. package/dist/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +2 -1
  122. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +16 -2
  123. package/dist/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +14 -0
  124. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -2
  125. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +11 -1
  126. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +62 -0
  127. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +2 -1
  128. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +16 -2
  129. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +14 -0
  130. package/dist/orchestrator/templates/specs-api.d.ts +38 -2
  131. package/dist/orchestrator/templates/specs-api.d.ts.map +1 -1
  132. package/dist/orchestrator/templates/specs-api.js +65 -22
  133. package/dist/orchestrator/templates/specs-api.js.map +1 -1
  134. package/dist/orchestrator/templates/specs-api.ts +71 -18
  135. package/dist/orchestrator/templates/specs-db.d.ts +3 -0
  136. package/dist/orchestrator/templates/specs-db.d.ts.map +1 -1
  137. package/dist/orchestrator/templates/specs-db.js +78 -1
  138. package/dist/orchestrator/templates/specs-db.js.map +1 -1
  139. package/dist/orchestrator/templates/specs-db.ts +78 -1
  140. package/dist/orchestrator/templates/specs-test-data.ts +2 -1
  141. package/package.json +2 -2
  142. package/src/capabilities/context.ts +19 -0
  143. package/src/capabilities/discover.ts +27 -7
  144. package/src/capabilities/registry.ts +3 -1
  145. package/src/capabilities/sensor.ts +1 -1
  146. package/src/cli/commands/audit.ts +15 -9
  147. package/src/cli/commands/capability.ts +53 -5
  148. package/src/cli/commands/context.ts +52 -0
  149. package/src/cli/commands/delivery.ts +40 -31
  150. package/src/cli/commands/generate.ts +30 -5
  151. package/src/cli/commands/ledger.ts +13 -5
  152. package/src/cli/commands/manifest.ts +9 -7
  153. package/src/cli/commands/repair.ts +57 -0
  154. package/src/cli/commands/script-check.ts +12 -8
  155. package/src/cli/commands/trace.ts +7 -4
  156. package/src/cli/index.ts +4 -0
  157. package/src/generators/test-generator/code-generator.ts +115 -40
  158. package/src/harness/annotation-overrides.ts +3 -1
  159. package/src/harness/audit.ts +115 -15
  160. package/src/harness/capability-plan.ts +51 -1
  161. package/src/harness/data-driven-lint.ts +20 -0
  162. package/src/harness/flow-check.ts +15 -6
  163. package/src/harness/intent.ts +25 -4
  164. package/src/harness/ledger.ts +3 -2
  165. package/src/harness/manifest.ts +3 -2
  166. package/src/harness/parse.ts +4 -0
  167. package/src/harness/quality-gates.ts +1 -1
  168. package/src/harness/query-catalog.ts +0 -0
  169. package/src/harness/repair.ts +75 -0
  170. package/src/harness/script-check.ts +25 -8
  171. package/src/harness/sensors.ts +71 -2
  172. package/src/harness/trace.ts +4 -3
  173. package/src/harness/unit-paths.ts +14 -0
  174. package/src/index.ts +4 -2
  175. package/src/orchestrator/ai-rules-updater.ts +2 -0
  176. package/src/orchestrator/context-discovery.ts +50 -0
  177. package/src/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +7 -1
  178. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +6 -2
  179. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +18 -1
  180. package/src/orchestrator/templates/ai-instructions/claude-skill-api-design.md +62 -0
  181. package/src/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +2 -1
  182. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +16 -2
  183. package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +14 -0
  184. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -2
  185. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +11 -1
  186. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-api-design.md +62 -0
  187. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +2 -1
  188. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +16 -2
  189. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +14 -0
  190. package/src/orchestrator/templates/specs-api.ts +71 -18
  191. package/src/orchestrator/templates/specs-db.ts +78 -1
  192. 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: conf.url, max: 2, statement_timeout: conf.statement_timeout_ms ?? 4000 });
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');