@telora/factory 0.4.5

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 (301) hide show
  1. package/dist/audit.d.ts +69 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +376 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/builder-completion.d.ts +35 -0
  6. package/dist/builder-completion.d.ts.map +1 -0
  7. package/dist/builder-completion.js +375 -0
  8. package/dist/builder-completion.js.map +1 -0
  9. package/dist/builder-spawner.d.ts +40 -0
  10. package/dist/builder-spawner.d.ts.map +1 -0
  11. package/dist/builder-spawner.js +493 -0
  12. package/dist/builder-spawner.js.map +1 -0
  13. package/dist/completion-gate.d.ts +52 -0
  14. package/dist/completion-gate.d.ts.map +1 -0
  15. package/dist/completion-gate.js +336 -0
  16. package/dist/completion-gate.js.map +1 -0
  17. package/dist/completion-report.d.ts +36 -0
  18. package/dist/completion-report.d.ts.map +1 -0
  19. package/dist/completion-report.js +348 -0
  20. package/dist/completion-report.js.map +1 -0
  21. package/dist/completion.d.ts +58 -0
  22. package/dist/completion.d.ts.map +1 -0
  23. package/dist/completion.js +287 -0
  24. package/dist/completion.js.map +1 -0
  25. package/dist/config.d.ts +16 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/config.js +57 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/context-manager.d.ts +152 -0
  30. package/dist/context-manager.d.ts.map +1 -0
  31. package/dist/context-manager.js +421 -0
  32. package/dist/context-manager.js.map +1 -0
  33. package/dist/crash-detection.d.ts +70 -0
  34. package/dist/crash-detection.d.ts.map +1 -0
  35. package/dist/crash-detection.js +123 -0
  36. package/dist/crash-detection.js.map +1 -0
  37. package/dist/crash-recovery.d.ts +83 -0
  38. package/dist/crash-recovery.d.ts.map +1 -0
  39. package/dist/crash-recovery.js +522 -0
  40. package/dist/crash-recovery.js.map +1 -0
  41. package/dist/crash-resolution.d.ts +34 -0
  42. package/dist/crash-resolution.d.ts.map +1 -0
  43. package/dist/crash-resolution.js +382 -0
  44. package/dist/crash-resolution.js.map +1 -0
  45. package/dist/escalation.d.ts +150 -0
  46. package/dist/escalation.d.ts.map +1 -0
  47. package/dist/escalation.js +352 -0
  48. package/dist/escalation.js.map +1 -0
  49. package/dist/execution-target.d.ts +31 -0
  50. package/dist/execution-target.d.ts.map +1 -0
  51. package/dist/execution-target.js +71 -0
  52. package/dist/execution-target.js.map +1 -0
  53. package/dist/execution-unit-init.d.ts +28 -0
  54. package/dist/execution-unit-init.d.ts.map +1 -0
  55. package/dist/execution-unit-init.js +115 -0
  56. package/dist/execution-unit-init.js.map +1 -0
  57. package/dist/execution.d.ts +17 -0
  58. package/dist/execution.d.ts.map +1 -0
  59. package/dist/execution.js +20 -0
  60. package/dist/execution.js.map +1 -0
  61. package/dist/factory-engine.d.ts +100 -0
  62. package/dist/factory-engine.d.ts.map +1 -0
  63. package/dist/factory-engine.js +243 -0
  64. package/dist/factory-engine.js.map +1 -0
  65. package/dist/gap-detection.d.ts +43 -0
  66. package/dist/gap-detection.d.ts.map +1 -0
  67. package/dist/gap-detection.js +149 -0
  68. package/dist/gap-detection.js.map +1 -0
  69. package/dist/gate-context.d.ts +23 -0
  70. package/dist/gate-context.d.ts.map +1 -0
  71. package/dist/gate-context.js +63 -0
  72. package/dist/gate-context.js.map +1 -0
  73. package/dist/gate-engine.d.ts +55 -0
  74. package/dist/gate-engine.d.ts.map +1 -0
  75. package/dist/gate-engine.js +191 -0
  76. package/dist/gate-engine.js.map +1 -0
  77. package/dist/gates/adversarial.d.ts +59 -0
  78. package/dist/gates/adversarial.d.ts.map +1 -0
  79. package/dist/gates/adversarial.js +426 -0
  80. package/dist/gates/adversarial.js.map +1 -0
  81. package/dist/gates/adversary-spawner.d.ts +35 -0
  82. package/dist/gates/adversary-spawner.d.ts.map +1 -0
  83. package/dist/gates/adversary-spawner.js +286 -0
  84. package/dist/gates/adversary-spawner.js.map +1 -0
  85. package/dist/gates/adversary-test-dir.d.ts +41 -0
  86. package/dist/gates/adversary-test-dir.d.ts.map +1 -0
  87. package/dist/gates/adversary-test-dir.js +150 -0
  88. package/dist/gates/adversary-test-dir.js.map +1 -0
  89. package/dist/gates/behavioral-parser.d.ts +32 -0
  90. package/dist/gates/behavioral-parser.d.ts.map +1 -0
  91. package/dist/gates/behavioral-parser.js +190 -0
  92. package/dist/gates/behavioral-parser.js.map +1 -0
  93. package/dist/gates/behavioral-runner.d.ts +36 -0
  94. package/dist/gates/behavioral-runner.d.ts.map +1 -0
  95. package/dist/gates/behavioral-runner.js +306 -0
  96. package/dist/gates/behavioral-runner.js.map +1 -0
  97. package/dist/gates/behavioral.d.ts +37 -0
  98. package/dist/gates/behavioral.d.ts.map +1 -0
  99. package/dist/gates/behavioral.js +485 -0
  100. package/dist/gates/behavioral.js.map +1 -0
  101. package/dist/gates/deterministic.d.ts +24 -0
  102. package/dist/gates/deterministic.d.ts.map +1 -0
  103. package/dist/gates/deterministic.js +186 -0
  104. package/dist/gates/deterministic.js.map +1 -0
  105. package/dist/git-factory.d.ts +59 -0
  106. package/dist/git-factory.d.ts.map +1 -0
  107. package/dist/git-factory.js +102 -0
  108. package/dist/git-factory.js.map +1 -0
  109. package/dist/guard-evaluation.d.ts +48 -0
  110. package/dist/guard-evaluation.d.ts.map +1 -0
  111. package/dist/guard-evaluation.js +416 -0
  112. package/dist/guard-evaluation.js.map +1 -0
  113. package/dist/index.d.ts +30 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +39 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/instance-completion.d.ts +34 -0
  118. package/dist/instance-completion.d.ts.map +1 -0
  119. package/dist/instance-completion.js +366 -0
  120. package/dist/instance-completion.js.map +1 -0
  121. package/dist/instance-lifecycle.d.ts +15 -0
  122. package/dist/instance-lifecycle.d.ts.map +1 -0
  123. package/dist/instance-lifecycle.js +18 -0
  124. package/dist/instance-lifecycle.js.map +1 -0
  125. package/dist/instance-phase-dispatch.d.ts +75 -0
  126. package/dist/instance-phase-dispatch.d.ts.map +1 -0
  127. package/dist/instance-phase-dispatch.js +674 -0
  128. package/dist/instance-phase-dispatch.js.map +1 -0
  129. package/dist/instance-poll-loop.d.ts +43 -0
  130. package/dist/instance-poll-loop.d.ts.map +1 -0
  131. package/dist/instance-poll-loop.js +360 -0
  132. package/dist/instance-poll-loop.js.map +1 -0
  133. package/dist/instance-state-machine.d.ts +52 -0
  134. package/dist/instance-state-machine.d.ts.map +1 -0
  135. package/dist/instance-state-machine.js +235 -0
  136. package/dist/instance-state-machine.js.map +1 -0
  137. package/dist/log-manager.d.ts +28 -0
  138. package/dist/log-manager.d.ts.map +1 -0
  139. package/dist/log-manager.js +71 -0
  140. package/dist/log-manager.js.map +1 -0
  141. package/dist/pipeline-evaluator.d.ts +61 -0
  142. package/dist/pipeline-evaluator.d.ts.map +1 -0
  143. package/dist/pipeline-evaluator.js +107 -0
  144. package/dist/pipeline-evaluator.js.map +1 -0
  145. package/dist/pipeline-metrics.d.ts +52 -0
  146. package/dist/pipeline-metrics.d.ts.map +1 -0
  147. package/dist/pipeline-metrics.js +40 -0
  148. package/dist/pipeline-metrics.js.map +1 -0
  149. package/dist/pipeline-traversal.d.ts +43 -0
  150. package/dist/pipeline-traversal.d.ts.map +1 -0
  151. package/dist/pipeline-traversal.js +68 -0
  152. package/dist/pipeline-traversal.js.map +1 -0
  153. package/dist/plan-parser.d.ts +76 -0
  154. package/dist/plan-parser.d.ts.map +1 -0
  155. package/dist/plan-parser.js +223 -0
  156. package/dist/plan-parser.js.map +1 -0
  157. package/dist/planning-phase.d.ts +52 -0
  158. package/dist/planning-phase.d.ts.map +1 -0
  159. package/dist/planning-phase.js +444 -0
  160. package/dist/planning-phase.js.map +1 -0
  161. package/dist/planning-prompt.d.ts +64 -0
  162. package/dist/planning-prompt.d.ts.map +1 -0
  163. package/dist/planning-prompt.js +251 -0
  164. package/dist/planning-prompt.js.map +1 -0
  165. package/dist/planning.d.ts +16 -0
  166. package/dist/planning.d.ts.map +1 -0
  167. package/dist/planning.js +17 -0
  168. package/dist/planning.js.map +1 -0
  169. package/dist/process-runner.d.ts +41 -0
  170. package/dist/process-runner.d.ts.map +1 -0
  171. package/dist/process-runner.js +81 -0
  172. package/dist/process-runner.js.map +1 -0
  173. package/dist/product-config.d.ts +34 -0
  174. package/dist/product-config.d.ts.map +1 -0
  175. package/dist/product-config.js +43 -0
  176. package/dist/product-config.js.map +1 -0
  177. package/dist/queries/cycle-evaluations.d.ts +23 -0
  178. package/dist/queries/cycle-evaluations.d.ts.map +1 -0
  179. package/dist/queries/cycle-evaluations.js +37 -0
  180. package/dist/queries/cycle-evaluations.js.map +1 -0
  181. package/dist/queries/escalations.d.ts +30 -0
  182. package/dist/queries/escalations.d.ts.map +1 -0
  183. package/dist/queries/escalations.js +42 -0
  184. package/dist/queries/escalations.js.map +1 -0
  185. package/dist/queries/execution-units.d.ts +76 -0
  186. package/dist/queries/execution-units.d.ts.map +1 -0
  187. package/dist/queries/execution-units.js +109 -0
  188. package/dist/queries/execution-units.js.map +1 -0
  189. package/dist/queries/gate-results.d.ts +32 -0
  190. package/dist/queries/gate-results.d.ts.map +1 -0
  191. package/dist/queries/gate-results.js +44 -0
  192. package/dist/queries/gate-results.js.map +1 -0
  193. package/dist/queries/instances.d.ts +51 -0
  194. package/dist/queries/instances.d.ts.map +1 -0
  195. package/dist/queries/instances.js +77 -0
  196. package/dist/queries/instances.js.map +1 -0
  197. package/dist/queries/sessions.d.ts +50 -0
  198. package/dist/queries/sessions.d.ts.map +1 -0
  199. package/dist/queries/sessions.js +81 -0
  200. package/dist/queries/sessions.js.map +1 -0
  201. package/dist/queries/shared.d.ts +38 -0
  202. package/dist/queries/shared.d.ts.map +1 -0
  203. package/dist/queries/shared.js +119 -0
  204. package/dist/queries/shared.js.map +1 -0
  205. package/dist/queries/specs.d.ts +12 -0
  206. package/dist/queries/specs.d.ts.map +1 -0
  207. package/dist/queries/specs.js +21 -0
  208. package/dist/queries/specs.js.map +1 -0
  209. package/dist/queries/strategies.d.ts +14 -0
  210. package/dist/queries/strategies.d.ts.map +1 -0
  211. package/dist/queries/strategies.js +18 -0
  212. package/dist/queries/strategies.js.map +1 -0
  213. package/dist/queries/work-units.d.ts +42 -0
  214. package/dist/queries/work-units.d.ts.map +1 -0
  215. package/dist/queries/work-units.js +57 -0
  216. package/dist/queries/work-units.js.map +1 -0
  217. package/dist/queries/workflows.d.ts +29 -0
  218. package/dist/queries/workflows.d.ts.map +1 -0
  219. package/dist/queries/workflows.js +103 -0
  220. package/dist/queries/workflows.js.map +1 -0
  221. package/dist/remediation-units.d.ts +40 -0
  222. package/dist/remediation-units.d.ts.map +1 -0
  223. package/dist/remediation-units.js +263 -0
  224. package/dist/remediation-units.js.map +1 -0
  225. package/dist/replanning.d.ts +72 -0
  226. package/dist/replanning.d.ts.map +1 -0
  227. package/dist/replanning.js +403 -0
  228. package/dist/replanning.js.map +1 -0
  229. package/dist/resource-limits.d.ts +62 -0
  230. package/dist/resource-limits.d.ts.map +1 -0
  231. package/dist/resource-limits.js +322 -0
  232. package/dist/resource-limits.js.map +1 -0
  233. package/dist/scheduler.d.ts +98 -0
  234. package/dist/scheduler.d.ts.map +1 -0
  235. package/dist/scheduler.js +203 -0
  236. package/dist/scheduler.js.map +1 -0
  237. package/dist/session-adapter.d.ts +89 -0
  238. package/dist/session-adapter.d.ts.map +1 -0
  239. package/dist/session-adapter.js +108 -0
  240. package/dist/session-adapter.js.map +1 -0
  241. package/dist/sop-generator.d.ts +29 -0
  242. package/dist/sop-generator.d.ts.map +1 -0
  243. package/dist/sop-generator.js +235 -0
  244. package/dist/sop-generator.js.map +1 -0
  245. package/dist/spec-profiles.d.ts +41 -0
  246. package/dist/spec-profiles.d.ts.map +1 -0
  247. package/dist/spec-profiles.js +131 -0
  248. package/dist/spec-profiles.js.map +1 -0
  249. package/dist/strategy-design-graph.d.ts +23 -0
  250. package/dist/strategy-design-graph.d.ts.map +1 -0
  251. package/dist/strategy-design-graph.js +205 -0
  252. package/dist/strategy-design-graph.js.map +1 -0
  253. package/dist/strategy-design-prompt.d.ts +28 -0
  254. package/dist/strategy-design-prompt.d.ts.map +1 -0
  255. package/dist/strategy-design-prompt.js +108 -0
  256. package/dist/strategy-design-prompt.js.map +1 -0
  257. package/dist/strategy-design-schema.d.ts +767 -0
  258. package/dist/strategy-design-schema.d.ts.map +1 -0
  259. package/dist/strategy-design-schema.js +126 -0
  260. package/dist/strategy-design-schema.js.map +1 -0
  261. package/dist/strategy-design.d.ts +69 -0
  262. package/dist/strategy-design.d.ts.map +1 -0
  263. package/dist/strategy-design.js +411 -0
  264. package/dist/strategy-design.js.map +1 -0
  265. package/dist/strategy-gating.d.ts +31 -0
  266. package/dist/strategy-gating.d.ts.map +1 -0
  267. package/dist/strategy-gating.js +276 -0
  268. package/dist/strategy-gating.js.map +1 -0
  269. package/dist/team-prompt-builder.d.ts +47 -0
  270. package/dist/team-prompt-builder.d.ts.map +1 -0
  271. package/dist/team-prompt-builder.js +362 -0
  272. package/dist/team-prompt-builder.js.map +1 -0
  273. package/dist/trace-engine.d.ts +40 -0
  274. package/dist/trace-engine.d.ts.map +1 -0
  275. package/dist/trace-engine.js +344 -0
  276. package/dist/trace-engine.js.map +1 -0
  277. package/dist/types.d.ts +612 -0
  278. package/dist/types.d.ts.map +1 -0
  279. package/dist/types.js +9 -0
  280. package/dist/types.js.map +1 -0
  281. package/dist/unit-session-lifecycle.d.ts +78 -0
  282. package/dist/unit-session-lifecycle.d.ts.map +1 -0
  283. package/dist/unit-session-lifecycle.js +141 -0
  284. package/dist/unit-session-lifecycle.js.map +1 -0
  285. package/dist/unit-session.d.ts +30 -0
  286. package/dist/unit-session.d.ts.map +1 -0
  287. package/dist/unit-session.js +370 -0
  288. package/dist/unit-session.js.map +1 -0
  289. package/dist/watchdogs.d.ts +33 -0
  290. package/dist/watchdogs.d.ts.map +1 -0
  291. package/dist/watchdogs.js +170 -0
  292. package/dist/watchdogs.js.map +1 -0
  293. package/dist/work-unit-scheduler.d.ts +34 -0
  294. package/dist/work-unit-scheduler.d.ts.map +1 -0
  295. package/dist/work-unit-scheduler.js +91 -0
  296. package/dist/work-unit-scheduler.js.map +1 -0
  297. package/dist/workflow-transition.d.ts +90 -0
  298. package/dist/workflow-transition.d.ts.map +1 -0
  299. package/dist/workflow-transition.js +340 -0
  300. package/dist/workflow-transition.js.map +1 -0
  301. package/package.json +65 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Playwright JSON report parsing and result extraction.
3
+ *
4
+ * Parses Playwright JSON reporter output into structured GateCheckResult
5
+ * items. Extracts individual test results from the nested suite/spec/test
6
+ * hierarchy, determines pass/fail status, and builds error output.
7
+ */
8
+ // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ /** Maximum output length per check result (10 KB). */
12
+ const MAX_OUTPUT_LENGTH = 10_000;
13
+ // ============================================================================
14
+ // Playwright JSON report parsing
15
+ // ============================================================================
16
+ /**
17
+ * Parse Playwright JSON reporter output into GateCheckResult items.
18
+ *
19
+ * Extracts individual test results from the nested suite/spec/test
20
+ * hierarchy. Each test becomes a separate GateCheckResult entry.
21
+ *
22
+ * If the JSON cannot be parsed, returns a single failed result with
23
+ * the raw output.
24
+ */
25
+ export function parsePlaywrightResults(jsonOutput, stderrOutput, exitCode, durationMs) {
26
+ let report;
27
+ try {
28
+ report = JSON.parse(jsonOutput);
29
+ }
30
+ catch {
31
+ // JSON parse failed -- return a single check with raw output
32
+ return [{
33
+ checkName: 'playwright-test-run',
34
+ passed: false,
35
+ output: truncateOutput(`Failed to parse Playwright JSON output.\n\n` +
36
+ `Exit code: ${exitCode}\n\n` +
37
+ `stdout:\n${jsonOutput}\n\n` +
38
+ `stderr:\n${stderrOutput}`),
39
+ durationMs,
40
+ isAdversaryGenerated: false,
41
+ }];
42
+ }
43
+ const results = [];
44
+ // Handle top-level errors (e.g. config errors, no tests found)
45
+ if (report.errors && report.errors.length > 0) {
46
+ const errorMessages = report.errors
47
+ .map((e) => e.message ?? 'Unknown error')
48
+ .join('\n');
49
+ results.push({
50
+ checkName: 'playwright-setup',
51
+ passed: false,
52
+ output: truncateOutput(`Playwright reported errors:\n${errorMessages}`),
53
+ durationMs,
54
+ isAdversaryGenerated: false,
55
+ });
56
+ }
57
+ // Recursively extract test results from suites
58
+ if (report.suites) {
59
+ for (const suite of report.suites) {
60
+ extractSuiteResults(suite, [], results);
61
+ }
62
+ }
63
+ // If no results were extracted but exit code was non-zero, add a summary
64
+ if (results.length === 0) {
65
+ results.push({
66
+ checkName: 'playwright-test-run',
67
+ passed: exitCode === 0,
68
+ output: truncateOutput(exitCode === 0
69
+ ? 'All Playwright tests passed (no individual results extracted).'
70
+ : `Playwright exited with code ${exitCode}.\n\nstderr:\n${stderrOutput}`),
71
+ durationMs,
72
+ isAdversaryGenerated: false,
73
+ });
74
+ }
75
+ return results;
76
+ }
77
+ /**
78
+ * Recursively extract test results from a Playwright suite.
79
+ *
80
+ * Builds a fully qualified test name from the suite path and spec/test
81
+ * titles. Each test result becomes a GateCheckResult.
82
+ */
83
+ function extractSuiteResults(suite, parentPath, results) {
84
+ const currentPath = suite.title
85
+ ? [...parentPath, suite.title]
86
+ : parentPath;
87
+ // Process specs in this suite
88
+ if (suite.specs) {
89
+ for (const spec of suite.specs) {
90
+ extractSpecResults(spec, currentPath, results);
91
+ }
92
+ }
93
+ // Recurse into nested suites
94
+ if (suite.suites) {
95
+ for (const nested of suite.suites) {
96
+ extractSuiteResults(nested, currentPath, results);
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Extract results from a Playwright spec (describe/test block).
102
+ */
103
+ function extractSpecResults(spec, suitePath, results) {
104
+ if (!spec.tests || spec.tests.length === 0) {
105
+ // Spec without tests -- use the spec's own ok status
106
+ const checkName = [...suitePath, spec.title ?? 'unknown'].join(' > ');
107
+ results.push({
108
+ checkName,
109
+ passed: spec.ok === true,
110
+ output: truncateOutput(spec.ok ? 'Passed' : 'Failed'),
111
+ durationMs: 0,
112
+ isAdversaryGenerated: false,
113
+ });
114
+ return;
115
+ }
116
+ for (const test of spec.tests) {
117
+ const testTitle = test.title ?? spec.title ?? 'unknown';
118
+ const checkName = [...suitePath, testTitle].join(' > ');
119
+ // Determine pass/fail from test results
120
+ const testResults = test.results ?? [];
121
+ const lastResult = testResults[testResults.length - 1];
122
+ const passed = test.status === 'expected'
123
+ || lastResult?.status === 'passed'
124
+ || (test.expectedStatus === test.status);
125
+ const totalDuration = testResults.reduce((sum, r) => sum + (r.duration ?? 0), 0);
126
+ // Build output from error information
127
+ let output = '';
128
+ if (passed) {
129
+ output = `Passed (${totalDuration}ms)`;
130
+ }
131
+ else {
132
+ const errorParts = [];
133
+ for (const result of testResults) {
134
+ if (result.error) {
135
+ if (result.error.message)
136
+ errorParts.push(result.error.message);
137
+ if (result.error.snippet)
138
+ errorParts.push(result.error.snippet);
139
+ }
140
+ if (result.errors) {
141
+ for (const err of result.errors) {
142
+ if (err.message)
143
+ errorParts.push(err.message);
144
+ if (err.snippet)
145
+ errorParts.push(err.snippet);
146
+ }
147
+ }
148
+ }
149
+ output = errorParts.length > 0
150
+ ? errorParts.join('\n---\n')
151
+ : `Failed with status: ${lastResult?.status ?? test.status ?? 'unknown'}`;
152
+ }
153
+ results.push({
154
+ checkName,
155
+ passed,
156
+ output: truncateOutput(output),
157
+ durationMs: totalDuration,
158
+ isAdversaryGenerated: false,
159
+ });
160
+ }
161
+ }
162
+ // ============================================================================
163
+ // Utility helpers
164
+ // ============================================================================
165
+ /**
166
+ * Truncate output to the maximum allowed length.
167
+ * Appends a truncation notice if the output was shortened.
168
+ */
169
+ export function truncateOutput(output) {
170
+ if (output.length <= MAX_OUTPUT_LENGTH) {
171
+ return output;
172
+ }
173
+ const truncationNotice = '\n\n... [truncated at 10000 chars]';
174
+ return output.slice(0, MAX_OUTPUT_LENGTH - truncationNotice.length) + truncationNotice;
175
+ }
176
+ /**
177
+ * Parse a shell command string into the command and its arguments.
178
+ *
179
+ * Handles simple cases like "npm run dev" or "node server.js".
180
+ * For complex commands with pipes or redirects, the shell: true
181
+ * option on spawn handles those.
182
+ */
183
+ export function parseCommand(command) {
184
+ const parts = command.trim().split(/\s+/);
185
+ if (parts.length === 0 || parts[0] === '') {
186
+ return ['npm', 'run', 'dev'];
187
+ }
188
+ return parts;
189
+ }
190
+ //# sourceMappingURL=behavioral-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral-parser.js","sourceRoot":"","sources":["../../src/gates/behavioral-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Behavioral gate test execution.
3
+ *
4
+ * Manages the dev server lifecycle and Playwright test execution within
5
+ * a factory worktree. The flow is:
6
+ * 1. Start the dev server (blueprint config or "npm run dev")
7
+ * 2. Wait for the server to be ready (stdout detection or timeout)
8
+ * 3. Run `npx playwright test --reporter=json {testGlob}` in the worktree
9
+ * 4. Kill the dev server process tree on completion or timeout
10
+ * 5. Return raw test output for parsing
11
+ *
12
+ * Dev server readiness detection looks for common patterns in stdout:
13
+ * - "ready" (generic)
14
+ * - "localhost" (generic server bind)
15
+ * - "Local:" (Vite dev server)
16
+ *
17
+ * The dev server process is killed using negative PID (process group kill)
18
+ * to ensure all child processes are terminated.
19
+ */
20
+ import type { BehavioralGateConfig, GateCheckResult } from '../types.js';
21
+ /**
22
+ * Run behavioral gates for a factory work unit.
23
+ *
24
+ * Starts the dev server, waits for readiness, runs Playwright tests,
25
+ * parses results, and cleans up. Returns structured results suitable
26
+ * for persisting as gate check results.
27
+ *
28
+ * @param worktreePath Absolute path to the factory worktree.
29
+ * @param config Behavioral gate config from the blueprint, or null for defaults.
30
+ * @returns Overall pass/fail and individual check results.
31
+ */
32
+ export declare function runBehavioralGates(worktreePath: string, config: BehavioralGateConfig | null): Promise<{
33
+ passed: boolean;
34
+ results: GateCheckResult[];
35
+ }>;
36
+ //# sourceMappingURL=behavioral-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral-runner.d.ts","sourceRoot":"","sources":["../../src/gates/behavioral-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAkPzE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,oBAAoB,GAAG,IAAI,GAClC,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CAqG1D"}
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Behavioral gate test execution.
3
+ *
4
+ * Manages the dev server lifecycle and Playwright test execution within
5
+ * a factory worktree. The flow is:
6
+ * 1. Start the dev server (blueprint config or "npm run dev")
7
+ * 2. Wait for the server to be ready (stdout detection or timeout)
8
+ * 3. Run `npx playwright test --reporter=json {testGlob}` in the worktree
9
+ * 4. Kill the dev server process tree on completion or timeout
10
+ * 5. Return raw test output for parsing
11
+ *
12
+ * Dev server readiness detection looks for common patterns in stdout:
13
+ * - "ready" (generic)
14
+ * - "localhost" (generic server bind)
15
+ * - "Local:" (Vite dev server)
16
+ *
17
+ * The dev server process is killed using negative PID (process group kill)
18
+ * to ensure all child processes are terminated.
19
+ */
20
+ import { spawn } from 'node:child_process';
21
+ import { parsePlaywrightResults, truncateOutput, parseCommand } from './behavioral-parser.js';
22
+ // ============================================================================
23
+ // Constants
24
+ // ============================================================================
25
+ /** Log prefix for behavioral gate messages. */
26
+ const LOG_PREFIX = '[gate:behavioral]';
27
+ /** Default test glob if not specified in config. */
28
+ const DEFAULT_TEST_GLOB = 'tests/**/*.spec.ts';
29
+ /** Default dev server command if not specified in config. */
30
+ const DEFAULT_DEV_SERVER_COMMAND = 'npm run dev';
31
+ /** Default timeout for dev server readiness and test execution (30s). */
32
+ const DEFAULT_TIMEOUT_MS = 30_000;
33
+ /** Patterns in stdout that indicate the dev server is ready. */
34
+ const READY_PATTERNS = [
35
+ 'ready',
36
+ 'localhost',
37
+ 'Local:',
38
+ ];
39
+ /** Grace period for dev server process tree kill (ms). */
40
+ const KILL_GRACE_MS = 3_000;
41
+ // ============================================================================
42
+ // Dev server management
43
+ // ============================================================================
44
+ /**
45
+ * Start the dev server and wait for it to be ready.
46
+ *
47
+ * Spawns the dev server command in the worktree directory with a new
48
+ * process group (detached: true) so we can kill the entire tree later.
49
+ * Listens on stdout for readiness patterns or times out.
50
+ *
51
+ * @returns The dev server child process, or null if it failed to start.
52
+ */
53
+ function startDevServer(command, worktreePath) {
54
+ const [cmd, ...args] = parseCommand(command);
55
+ const proc = spawn(cmd, args, {
56
+ cwd: worktreePath,
57
+ stdio: ['ignore', 'pipe', 'pipe'],
58
+ detached: true,
59
+ shell: true,
60
+ env: { ...process.env, CI: 'true' },
61
+ });
62
+ return proc;
63
+ }
64
+ /**
65
+ * Wait for the dev server to emit a readiness signal on stdout.
66
+ *
67
+ * Resolves when any of the READY_PATTERNS are detected in stdout,
68
+ * or rejects on timeout.
69
+ */
70
+ function waitForServerReady(proc, timeoutMs) {
71
+ return new Promise((resolve, reject) => {
72
+ let resolved = false;
73
+ let stdoutBuffer = '';
74
+ const timer = setTimeout(() => {
75
+ if (!resolved) {
76
+ resolved = true;
77
+ reject(new Error(`Dev server did not become ready within ${timeoutMs}ms. ` +
78
+ `Captured stdout: ${truncateOutput(stdoutBuffer)}`));
79
+ }
80
+ }, timeoutMs);
81
+ const onData = (chunk) => {
82
+ if (resolved)
83
+ return;
84
+ const text = chunk.toString();
85
+ stdoutBuffer += text;
86
+ const lowerText = stdoutBuffer.toLowerCase();
87
+ const isReady = READY_PATTERNS.some((pattern) => lowerText.includes(pattern.toLowerCase()));
88
+ if (isReady) {
89
+ resolved = true;
90
+ clearTimeout(timer);
91
+ // Detach the listener but keep the process running
92
+ proc.stdout?.removeListener('data', onData);
93
+ resolve();
94
+ }
95
+ };
96
+ proc.stdout?.on('data', onData);
97
+ proc.on('error', (err) => {
98
+ if (!resolved) {
99
+ resolved = true;
100
+ clearTimeout(timer);
101
+ reject(new Error(`Dev server failed to start: ${err.message}`));
102
+ }
103
+ });
104
+ proc.on('close', (code) => {
105
+ if (!resolved) {
106
+ resolved = true;
107
+ clearTimeout(timer);
108
+ reject(new Error(`Dev server exited prematurely with code ${code ?? 'unknown'}. ` +
109
+ `Captured stdout: ${truncateOutput(stdoutBuffer)}`));
110
+ }
111
+ });
112
+ });
113
+ }
114
+ /**
115
+ * Kill the dev server process tree.
116
+ *
117
+ * Uses negative PID to send SIGTERM to the entire process group.
118
+ * Falls back to killing just the process if group kill fails.
119
+ * Waits up to KILL_GRACE_MS, then sends SIGKILL.
120
+ */
121
+ async function killDevServer(proc) {
122
+ const pid = proc.pid;
123
+ if (pid === undefined)
124
+ return;
125
+ // Try process group kill first (negative PID)
126
+ try {
127
+ process.kill(-pid, 'SIGTERM');
128
+ }
129
+ catch {
130
+ // Process group kill failed -- try direct kill
131
+ try {
132
+ proc.kill('SIGTERM');
133
+ }
134
+ catch {
135
+ // Already dead
136
+ return;
137
+ }
138
+ }
139
+ // Wait for graceful shutdown, then force kill if still alive
140
+ await new Promise((resolve) => {
141
+ const forceKillTimer = setTimeout(() => {
142
+ try {
143
+ process.kill(-pid, 'SIGKILL');
144
+ }
145
+ catch {
146
+ try {
147
+ proc.kill('SIGKILL');
148
+ }
149
+ catch {
150
+ // Already dead
151
+ }
152
+ }
153
+ resolve();
154
+ }, KILL_GRACE_MS);
155
+ proc.on('close', () => {
156
+ clearTimeout(forceKillTimer);
157
+ resolve();
158
+ });
159
+ });
160
+ }
161
+ // ============================================================================
162
+ // Playwright test execution
163
+ // ============================================================================
164
+ /**
165
+ * Run Playwright tests in the worktree and capture JSON output.
166
+ *
167
+ * Executes `npx playwright test --reporter=json {testGlob}` and collects
168
+ * the full stdout as the JSON report.
169
+ */
170
+ function runPlaywrightTests(worktreePath, testGlob, timeoutMs) {
171
+ return new Promise((resolve) => {
172
+ const proc = spawn('npx', ['playwright', 'test', '--reporter=json', testGlob], {
173
+ cwd: worktreePath,
174
+ stdio: ['ignore', 'pipe', 'pipe'],
175
+ shell: true,
176
+ env: { ...process.env, CI: 'true' },
177
+ });
178
+ let stdout = '';
179
+ let stderr = '';
180
+ proc.stdout?.on('data', (chunk) => {
181
+ stdout += chunk.toString();
182
+ });
183
+ proc.stderr?.on('data', (chunk) => {
184
+ stderr += chunk.toString();
185
+ });
186
+ const timer = setTimeout(() => {
187
+ try {
188
+ proc.kill('SIGTERM');
189
+ }
190
+ catch {
191
+ // Already dead
192
+ }
193
+ // Give it a moment to clean up, then force kill
194
+ setTimeout(() => {
195
+ try {
196
+ proc.kill('SIGKILL');
197
+ }
198
+ catch {
199
+ // Already dead
200
+ }
201
+ }, KILL_GRACE_MS);
202
+ }, timeoutMs);
203
+ proc.on('close', (code) => {
204
+ clearTimeout(timer);
205
+ resolve({ stdout, stderr, exitCode: code ?? 1 });
206
+ });
207
+ proc.on('error', (err) => {
208
+ clearTimeout(timer);
209
+ resolve({ stdout, stderr: stderr + '\n' + err.message, exitCode: 1 });
210
+ });
211
+ });
212
+ }
213
+ // ============================================================================
214
+ // Main exported function
215
+ // ============================================================================
216
+ /**
217
+ * Run behavioral gates for a factory work unit.
218
+ *
219
+ * Starts the dev server, waits for readiness, runs Playwright tests,
220
+ * parses results, and cleans up. Returns structured results suitable
221
+ * for persisting as gate check results.
222
+ *
223
+ * @param worktreePath Absolute path to the factory worktree.
224
+ * @param config Behavioral gate config from the blueprint, or null for defaults.
225
+ * @returns Overall pass/fail and individual check results.
226
+ */
227
+ export async function runBehavioralGates(worktreePath, config) {
228
+ const testGlob = config?.testGlob ?? DEFAULT_TEST_GLOB;
229
+ const devServerCommand = config?.devServerCommand ?? DEFAULT_DEV_SERVER_COMMAND;
230
+ const timeoutMs = config?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
231
+ const overallStart = Date.now();
232
+ console.log(`${LOG_PREFIX} Starting behavioral gates in ${worktreePath} ` +
233
+ `(devServer: "${devServerCommand}", glob: "${testGlob}", timeout: ${timeoutMs}ms)`);
234
+ // -- Step 1: Start the dev server ------------------------------------------
235
+ let devServer = null;
236
+ try {
237
+ devServer = startDevServer(devServerCommand, worktreePath);
238
+ if (devServer.pid === undefined) {
239
+ return {
240
+ passed: false,
241
+ results: [{
242
+ checkName: 'dev-server-start',
243
+ passed: false,
244
+ output: 'Failed to start dev server: process pid is undefined.',
245
+ durationMs: Date.now() - overallStart,
246
+ isAdversaryGenerated: false,
247
+ }],
248
+ };
249
+ }
250
+ console.log(`${LOG_PREFIX} Dev server started (pid: ${devServer.pid})`);
251
+ // -- Step 2: Wait for server readiness ------------------------------------
252
+ try {
253
+ await waitForServerReady(devServer, timeoutMs);
254
+ console.log(`${LOG_PREFIX} Dev server is ready`);
255
+ }
256
+ catch (readyErr) {
257
+ const error = readyErr instanceof Error ? readyErr.message : String(readyErr);
258
+ console.error(`${LOG_PREFIX} Dev server readiness check failed: ${error}`);
259
+ return {
260
+ passed: false,
261
+ results: [{
262
+ checkName: 'dev-server-ready',
263
+ passed: false,
264
+ output: truncateOutput(`Dev server failed readiness check.\n\n${error}`),
265
+ durationMs: Date.now() - overallStart,
266
+ isAdversaryGenerated: false,
267
+ }],
268
+ };
269
+ }
270
+ // -- Step 3: Run Playwright tests -----------------------------------------
271
+ const testStart = Date.now();
272
+ const { stdout, stderr, exitCode } = await runPlaywrightTests(worktreePath, testGlob, timeoutMs);
273
+ const testDuration = Date.now() - testStart;
274
+ console.log(`${LOG_PREFIX} Playwright tests completed ` +
275
+ `(exitCode: ${exitCode}, duration: ${testDuration}ms)`);
276
+ // -- Step 4: Parse results ------------------------------------------------
277
+ const results = parsePlaywrightResults(stdout, stderr, exitCode, testDuration);
278
+ const passed = results.every((r) => r.passed);
279
+ console.log(`${LOG_PREFIX} Behavioral gates ${passed ? 'PASSED' : 'FAILED'} ` +
280
+ `(${results.filter((r) => r.passed).length}/${results.length} checks passed)`);
281
+ return { passed, results };
282
+ }
283
+ catch (err) {
284
+ const error = err instanceof Error ? err.message : String(err);
285
+ console.error(`${LOG_PREFIX} Unexpected error during behavioral gates: ${error}`);
286
+ return {
287
+ passed: false,
288
+ results: [{
289
+ checkName: 'behavioral-gate-error',
290
+ passed: false,
291
+ output: truncateOutput(`Unexpected error: ${error}`),
292
+ durationMs: Date.now() - overallStart,
293
+ isAdversaryGenerated: false,
294
+ }],
295
+ };
296
+ }
297
+ finally {
298
+ // -- Step 5: Kill dev server on completion or error ------------------------
299
+ if (devServer) {
300
+ console.log(`${LOG_PREFIX} Killing dev server...`);
301
+ await killDevServer(devServer);
302
+ console.log(`${LOG_PREFIX} Dev server terminated`);
303
+ }
304
+ }
305
+ }
306
+ //# sourceMappingURL=behavioral-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral-runner.js","sourceRoot":"","sources":["../../src/gates/behavioral-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Behavioral gate evaluation for the factory orchestrator.
3
+ *
4
+ * Manages the dev server lifecycle and Playwright test execution within
5
+ * a factory worktree. The flow is:
6
+ * 1. Start the dev server (blueprint config or "npm run dev")
7
+ * 2. Wait for the server to be ready (stdout detection or timeout)
8
+ * 3. Run `npx playwright test --reporter=json {testGlob}` in the worktree
9
+ * 4. Parse Playwright JSON reporter output for structured results
10
+ * 5. Kill the dev server process tree on completion or timeout
11
+ * 6. Return structured gate check results
12
+ *
13
+ * Dev server readiness detection looks for common patterns in stdout:
14
+ * - "ready" (generic)
15
+ * - "localhost" (generic server bind)
16
+ * - "Local:" (Vite dev server)
17
+ *
18
+ * The dev server process is killed using negative PID (process group kill)
19
+ * to ensure all child processes are terminated.
20
+ */
21
+ import type { BehavioralGateConfig, GateCheckResult } from '../types.js';
22
+ /**
23
+ * Run behavioral gates for a factory work unit.
24
+ *
25
+ * Starts the dev server, waits for readiness, runs Playwright tests,
26
+ * parses results, and cleans up. Returns structured results suitable
27
+ * for persisting as gate check results.
28
+ *
29
+ * @param worktreePath Absolute path to the factory worktree.
30
+ * @param config Behavioral gate config from the blueprint, or null for defaults.
31
+ * @returns Overall pass/fail and individual check results.
32
+ */
33
+ export declare function runBehavioralGates(worktreePath: string, config: BehavioralGateConfig | null): Promise<{
34
+ passed: boolean;
35
+ results: GateCheckResult[];
36
+ }>;
37
+ //# sourceMappingURL=behavioral.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral.d.ts","sourceRoot":"","sources":["../../src/gates/behavioral.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAiezE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,oBAAoB,GAAG,IAAI,GAClC,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CAqG1D"}