@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,426 @@
1
+ /**
2
+ * Adversarial gate evaluation.
3
+ *
4
+ * Spawns a separate Claude Code session (the "adversary") that tries to
5
+ * break the builder's implementation by writing Playwright tests. Tests
6
+ * accumulate in an external directory OUTSIDE the worktree so builder
7
+ * agents never see adversary-generated test files.
8
+ *
9
+ * External test directory: `{worktreePath}-adversary/` (sibling to the
10
+ * factory worktree). This directory is created on first adversary run
11
+ * and cleaned up when the instance completes.
12
+ *
13
+ * The adversary prompt contains ONLY:
14
+ * 1. The factory specification text
15
+ * 2. The current source file contents from the worktree
16
+ *
17
+ * Builder reasoning, logs, and stream.jsonl are NEVER included.
18
+ *
19
+ * After each adversary session, ALL accumulated adversary tests are run
20
+ * (not just the new ones). Results are marked with isAdversaryGenerated=true.
21
+ */
22
+ import { spawnAsync } from '../process-runner.js';
23
+ import { readdirSync, readFileSync, existsSync, mkdirSync, rmSync } from 'node:fs';
24
+ import { join, relative } from 'node:path';
25
+ import { createFactorySession, updateFactorySession } from '../queries/sessions.js';
26
+ // ============================================================================
27
+ // Constants
28
+ // ============================================================================
29
+ /** Timeout for each adversary Claude Code session (5 minutes). */
30
+ const ADVERSARY_SESSION_TIMEOUT_MS = 300_000;
31
+ /** Timeout for running Playwright tests (3 minutes). */
32
+ const PLAYWRIGHT_TIMEOUT_MS = 180_000;
33
+ /** Maximum characters per check output. */
34
+ const MAX_OUTPUT_CHARS = 10_000;
35
+ /** Default max adversary sessions when config is not provided. */
36
+ const DEFAULT_MAX_SESSIONS = 3;
37
+ /** Glob patterns for source files to include in the adversary prompt. */
38
+ const SOURCE_GLOBS = ['src'];
39
+ /** File extensions considered source code. */
40
+ const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
41
+ /** Log prefix for this module. */
42
+ const LOG_PREFIX = '[adversarial]';
43
+ // ============================================================================
44
+ // External test directory
45
+ // ============================================================================
46
+ /**
47
+ * Derive the external adversary test directory path from a worktree path.
48
+ *
49
+ * Returns `{worktreePath}-adversary/` -- a sibling directory that lives
50
+ * outside the git worktree so builder agents never see adversary tests.
51
+ */
52
+ export function getAdversaryTestDir(worktreePath) {
53
+ return `${worktreePath}-adversary`;
54
+ }
55
+ /**
56
+ * Remove the external adversary test directory for a completed instance.
57
+ *
58
+ * Safe to call even if the directory does not exist. Callers should invoke
59
+ * this alongside worktree removal when an instance reaches a terminal state.
60
+ */
61
+ export function cleanupAdversaryTestDir(worktreePath) {
62
+ const testDir = getAdversaryTestDir(worktreePath);
63
+ if (!existsSync(testDir))
64
+ return;
65
+ try {
66
+ rmSync(testDir, { recursive: true, force: true });
67
+ console.log(`${LOG_PREFIX} Cleaned up external adversary test directory: ${testDir}`);
68
+ }
69
+ catch (err) {
70
+ console.warn(`${LOG_PREFIX} Failed to clean up adversary test directory ${testDir}: ` +
71
+ `${err instanceof Error ? err.message : String(err)}`);
72
+ }
73
+ }
74
+ // ============================================================================
75
+ // Environment builder
76
+ // ============================================================================
77
+ /**
78
+ * Build a clean environment for the adversary Claude Code session.
79
+ *
80
+ * Strips inherited CLAUDE_CODE_* and CLAUDECODE* env vars to prevent
81
+ * the child from detecting a parent session and hanging.
82
+ */
83
+ function buildAdversaryEnv() {
84
+ const env = { ...process.env };
85
+ for (const key of Object.keys(env)) {
86
+ if (key === 'CLAUDECODE' || key.startsWith('CLAUDE_CODE_') || key.startsWith('CLAUDECODE')) {
87
+ delete env[key];
88
+ }
89
+ }
90
+ env.CI = 'true';
91
+ return env;
92
+ }
93
+ // ============================================================================
94
+ // Source file collection
95
+ // ============================================================================
96
+ /**
97
+ * Recursively collect source files from a directory.
98
+ *
99
+ * Returns an array of { relativePath, content } objects for files matching
100
+ * the configured source extensions. Skips node_modules, dist, .git, and
101
+ * other common non-source directories.
102
+ */
103
+ function collectSourceFiles(worktreePath) {
104
+ const results = [];
105
+ const skipDirs = new Set(['node_modules', 'dist', '.git', '.telora', 'coverage', '.next', 'build']);
106
+ function walk(dir) {
107
+ let entries;
108
+ try {
109
+ entries = readdirSync(dir, { withFileTypes: true });
110
+ }
111
+ catch {
112
+ // Directory may not be readable -- skip silently
113
+ return;
114
+ }
115
+ for (const entry of entries) {
116
+ const name = String(entry.name);
117
+ if (entry.isDirectory()) {
118
+ if (!skipDirs.has(name)) {
119
+ walk(join(dir, name));
120
+ }
121
+ }
122
+ else if (entry.isFile()) {
123
+ const ext = name.slice(name.lastIndexOf('.'));
124
+ if (SOURCE_EXTENSIONS.has(ext)) {
125
+ const fullPath = join(dir, name);
126
+ try {
127
+ const content = readFileSync(fullPath, 'utf-8');
128
+ const relPath = relative(worktreePath, fullPath);
129
+ results.push({ relativePath: relPath, content });
130
+ }
131
+ catch {
132
+ // Skip unreadable files
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ for (const srcDir of SOURCE_GLOBS) {
139
+ const fullSrcDir = join(worktreePath, srcDir);
140
+ if (existsSync(fullSrcDir)) {
141
+ walk(fullSrcDir);
142
+ }
143
+ }
144
+ return results;
145
+ }
146
+ // ============================================================================
147
+ // Prompt builder
148
+ // ============================================================================
149
+ /**
150
+ * Build the adversary prompt.
151
+ *
152
+ * Contains ONLY:
153
+ * 1. The factory specification text
154
+ * 2. Current source file contents from the worktree
155
+ *
156
+ * NEVER includes builder reasoning, logs, or stream.jsonl.
157
+ */
158
+ function buildAdversaryPrompt(specification, sourceFiles, sessionNumber, adversaryTestDir) {
159
+ const parts = [
160
+ 'You are an adversarial tester. Your goal is to find bugs, edge cases,',
161
+ 'and weaknesses in the implementation below by writing Playwright tests.',
162
+ '',
163
+ '## Specification',
164
+ '',
165
+ specification,
166
+ '',
167
+ '## Source Files',
168
+ '',
169
+ ];
170
+ for (const file of sourceFiles) {
171
+ parts.push(`### ${file.relativePath}`);
172
+ parts.push('```');
173
+ parts.push(file.content);
174
+ parts.push('```');
175
+ parts.push('');
176
+ }
177
+ parts.push('## Instructions', '', `This is adversary session ${sessionNumber}. Write Playwright tests that try to break the implementation.`, '', 'Rules:', `- Write test files to the EXTERNAL test directory: \`${adversaryTestDir}/\``, `- Name files descriptively, e.g. \`${adversaryTestDir}/edge-cases-validation.spec.ts\``, '- Each test file must be a valid Playwright test using `@playwright/test`', '- Focus on edge cases, boundary conditions, error handling, and unexpected inputs', '- Try to find real bugs -- tests should expose actual implementation issues', '- Do NOT write tests that pass trivially -- every test should probe a potential weakness', `- Create the \`${adversaryTestDir}/\` directory if it does not exist`, '- Do NOT modify any source files -- only create test files', '- Do NOT write tests inside the project worktree -- use the external directory above', '- Commit is not needed for external test files', '', 'Write aggressive, thorough tests that exercise the code in ways the original', 'developer might not have anticipated.');
178
+ return parts.join('\n');
179
+ }
180
+ // ============================================================================
181
+ // Adversary session runner
182
+ // ============================================================================
183
+ /**
184
+ * Spawn a single adversary Claude Code session.
185
+ *
186
+ * Uses --print mode (one-shot, not stream-json). The adversary writes
187
+ * Playwright test files to the external adversary test directory.
188
+ *
189
+ * @returns The raw stdout output from Claude Code.
190
+ */
191
+ async function spawnAdversarySession(worktreePath, prompt, claudeCodePath) {
192
+ const env = buildAdversaryEnv();
193
+ return spawnAsync(claudeCodePath, ['--print', '--verbose'], {
194
+ input: prompt,
195
+ encoding: 'utf-8',
196
+ timeout: ADVERSARY_SESSION_TIMEOUT_MS,
197
+ cwd: worktreePath,
198
+ env,
199
+ });
200
+ }
201
+ // ============================================================================
202
+ // Test runner
203
+ // ============================================================================
204
+ /**
205
+ * Run all accumulated adversary tests using Playwright.
206
+ *
207
+ * Runs `npx playwright test {externalTestDir}` from the worktree directory.
208
+ * The test files live outside the worktree in the external adversary test
209
+ * directory so builder agents never see them.
210
+ *
211
+ * @param worktreePath CWD for the Playwright process (project root).
212
+ * @param adversaryTestDir Absolute path to the external test directory.
213
+ */
214
+ async function runAdversaryTests(worktreePath, adversaryTestDir) {
215
+ const startMs = Date.now();
216
+ // If no test directory exists, skip gracefully
217
+ if (!existsSync(adversaryTestDir)) {
218
+ return {
219
+ checkName: 'adversary-tests',
220
+ passed: true,
221
+ output: `No adversary tests found (${adversaryTestDir} does not exist)`,
222
+ durationMs: Date.now() - startMs,
223
+ isAdversaryGenerated: true,
224
+ };
225
+ }
226
+ // Check if there are any test files
227
+ let hasTestFiles = false;
228
+ try {
229
+ const entries = readdirSync(adversaryTestDir);
230
+ hasTestFiles = entries.some((e) => e.endsWith('.spec.ts') || e.endsWith('.spec.js') || e.endsWith('.test.ts') || e.endsWith('.test.js'));
231
+ }
232
+ catch {
233
+ // Directory read failed -- treat as no tests
234
+ }
235
+ if (!hasTestFiles) {
236
+ return {
237
+ checkName: 'adversary-tests',
238
+ passed: true,
239
+ output: `No adversary test files found in ${adversaryTestDir}`,
240
+ durationMs: Date.now() - startMs,
241
+ isAdversaryGenerated: true,
242
+ };
243
+ }
244
+ try {
245
+ const output = await spawnAsync('npx', ['playwright', 'test', adversaryTestDir], {
246
+ input: '',
247
+ encoding: 'utf-8',
248
+ timeout: PLAYWRIGHT_TIMEOUT_MS,
249
+ cwd: worktreePath,
250
+ env: { ...process.env, CI: 'true' },
251
+ });
252
+ const durationMs = Date.now() - startMs;
253
+ return {
254
+ checkName: 'adversary-tests',
255
+ passed: true,
256
+ output: truncateOutput(output),
257
+ durationMs,
258
+ isAdversaryGenerated: true,
259
+ };
260
+ }
261
+ catch (err) {
262
+ const durationMs = Date.now() - startMs;
263
+ const execErr = err;
264
+ if (execErr.killed || execErr.signal === 'SIGTERM') {
265
+ return {
266
+ checkName: 'adversary-tests',
267
+ passed: false,
268
+ output: truncateOutput(`Playwright timed out after ${PLAYWRIGHT_TIMEOUT_MS / 1000}s`),
269
+ durationMs,
270
+ isAdversaryGenerated: true,
271
+ };
272
+ }
273
+ // Playwright returns non-zero exit when tests fail
274
+ const stdout = execErr.stdout ?? '';
275
+ const stderr = execErr.stderr ?? '';
276
+ const combined = [stdout, stderr].filter(Boolean).join('\n---\n');
277
+ return {
278
+ checkName: 'adversary-tests',
279
+ passed: false,
280
+ output: truncateOutput(combined || execErr.message || `Playwright exited with code ${execErr.status ?? 'unknown'}`),
281
+ durationMs,
282
+ isAdversaryGenerated: true,
283
+ };
284
+ }
285
+ }
286
+ // ============================================================================
287
+ // Output truncation
288
+ // ============================================================================
289
+ /**
290
+ * Truncate output to the maximum allowed characters.
291
+ */
292
+ function truncateOutput(output) {
293
+ if (output.length <= MAX_OUTPUT_CHARS) {
294
+ return output;
295
+ }
296
+ return output.slice(0, MAX_OUTPUT_CHARS - 30) + '\n...[truncated to 10000 chars]';
297
+ }
298
+ // ============================================================================
299
+ // Exported gate runner
300
+ // ============================================================================
301
+ /**
302
+ * Run adversarial gates for a work unit's implementation.
303
+ *
304
+ * Spawns up to `config.maxSessions` adversary Claude Code sessions, each
305
+ * writing Playwright tests to an external directory outside the worktree.
306
+ * After all sessions complete, runs ALL accumulated adversary tests and
307
+ * returns the results.
308
+ *
309
+ * Each adversary session is tracked with session_type='adversary'.
310
+ *
311
+ * @param worktreePath Absolute path to the factory worktree.
312
+ * @param specification The factory specification text.
313
+ * @param config Adversarial gate config from the blueprint (nullable).
314
+ * @param instanceId Factory instance ID (for session tracking).
315
+ * @param claudeCodePath Path to the Claude Code CLI executable.
316
+ * @returns Overall pass/fail and individual check results.
317
+ */
318
+ export async function runAdversarialGates(worktreePath, specification, config, instanceId, claudeCodePath, governor) {
319
+ const maxSessions = config?.maxSessions ?? DEFAULT_MAX_SESSIONS;
320
+ const results = [];
321
+ // External test directory -- sibling to the worktree, invisible to builder
322
+ const adversaryTestDir = getAdversaryTestDir(worktreePath);
323
+ console.log(`${LOG_PREFIX} Starting adversarial gates (max sessions: ${maxSessions}, ` +
324
+ `worktree: ${worktreePath}, testDir: ${adversaryTestDir})`);
325
+ // Ensure external adversary test directory exists
326
+ if (!existsSync(adversaryTestDir)) {
327
+ mkdirSync(adversaryTestDir, { recursive: true });
328
+ }
329
+ // Collect source files once (shared across all sessions)
330
+ const sourceFiles = collectSourceFiles(worktreePath);
331
+ console.log(`${LOG_PREFIX} Collected ${sourceFiles.length} source file(s) for adversary context`);
332
+ // ── Spawn adversary sessions ──────────────────────────────────────
333
+ for (let sessionNum = 1; sessionNum <= maxSessions; sessionNum++) {
334
+ const sessionStartMs = Date.now();
335
+ console.log(`${LOG_PREFIX} Spawning adversary session ${sessionNum}/${maxSessions}`);
336
+ // Create a tracked session record
337
+ let sessionId;
338
+ try {
339
+ const session = await createFactorySession({
340
+ instanceId,
341
+ sessionType: 'adversary',
342
+ });
343
+ sessionId = session.id;
344
+ await updateFactorySession(sessionId, {
345
+ status: 'running',
346
+ startedAt: new Date().toISOString(),
347
+ });
348
+ }
349
+ catch (err) {
350
+ const errMsg = err instanceof Error ? err.message : String(err);
351
+ console.error(`${LOG_PREFIX} Failed to create adversary session record: ${errMsg}`);
352
+ results.push({
353
+ checkName: `adversary-session-${sessionNum}`,
354
+ passed: false,
355
+ output: truncateOutput(`Failed to create session record: ${errMsg}`),
356
+ durationMs: Date.now() - sessionStartMs,
357
+ isAdversaryGenerated: true,
358
+ });
359
+ continue;
360
+ }
361
+ // Build the prompt and spawn the adversary
362
+ const prompt = buildAdversaryPrompt(specification, sourceFiles, sessionNum, adversaryTestDir);
363
+ if (governor)
364
+ await governor.acquireSlot('factory');
365
+ try {
366
+ const rawOutput = await spawnAdversarySession(worktreePath, prompt, claudeCodePath);
367
+ const durationMs = Date.now() - sessionStartMs;
368
+ await updateFactorySession(sessionId, {
369
+ status: 'completed',
370
+ endedAt: new Date().toISOString(),
371
+ });
372
+ results.push({
373
+ checkName: `adversary-session-${sessionNum}`,
374
+ passed: true,
375
+ output: truncateOutput(rawOutput || '(no output)'),
376
+ durationMs,
377
+ isAdversaryGenerated: true,
378
+ });
379
+ console.log(`${LOG_PREFIX} Adversary session ${sessionNum} completed (${durationMs}ms)`);
380
+ }
381
+ catch (err) {
382
+ const durationMs = Date.now() - sessionStartMs;
383
+ const execErr = err;
384
+ const timedOut = execErr.killed === true || execErr.signal === 'SIGTERM';
385
+ const errDetail = timedOut
386
+ ? `Adversary session timed out after ${ADVERSARY_SESSION_TIMEOUT_MS / 1000}s`
387
+ : `Adversary session failed (exit ${execErr.status ?? 'unknown'}): ${execErr.message ?? 'unknown error'}`;
388
+ await updateFactorySession(sessionId, {
389
+ status: 'failed',
390
+ endedAt: new Date().toISOString(),
391
+ }).catch((updateErr) => {
392
+ console.error(`${LOG_PREFIX} Failed to update session ${sessionId} status: `, updateErr.message);
393
+ });
394
+ // Include any stdout the adversary produced before failing --
395
+ // it may have written test files despite the non-zero exit
396
+ const partialOutput = execErr.stdout ?? '';
397
+ results.push({
398
+ checkName: `adversary-session-${sessionNum}`,
399
+ passed: false,
400
+ output: truncateOutput(partialOutput
401
+ ? `${errDetail}\n---\nPartial output:\n${partialOutput}`
402
+ : errDetail),
403
+ durationMs,
404
+ isAdversaryGenerated: true,
405
+ });
406
+ console.warn(`${LOG_PREFIX} ${errDetail}`);
407
+ // Continue to next session -- a failed adversary session does not
408
+ // mean the implementation failed, it means the adversary failed.
409
+ // We still want to run accumulated tests.
410
+ }
411
+ finally {
412
+ if (governor)
413
+ governor.releaseSlot('factory');
414
+ }
415
+ }
416
+ // ── Run ALL accumulated adversary tests ─────────────────────────
417
+ console.log(`${LOG_PREFIX} Running all accumulated adversary tests from ${adversaryTestDir}`);
418
+ const testResult = await runAdversaryTests(worktreePath, adversaryTestDir);
419
+ results.push(testResult);
420
+ // Overall pass/fail is determined by the test run result
421
+ const passed = testResult.passed;
422
+ console.log(`${LOG_PREFIX} Adversarial gates ${passed ? 'PASSED' : 'FAILED'} ` +
423
+ `(${results.length} check(s))`);
424
+ return { passed, results };
425
+ }
426
+ //# sourceMappingURL=adversarial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adversarial.js","sourceRoot":"","sources":["../../src/gates/adversarial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Adversary process spawning and prompt construction.
3
+ *
4
+ * Spawns a separate Claude Code session (the "adversary") that tries to
5
+ * break the builder's implementation by writing Playwright tests. The
6
+ * adversary prompt contains ONLY:
7
+ * 1. The factory specification text
8
+ * 2. The current source file contents from the worktree
9
+ *
10
+ * Builder reasoning, logs, and stream.jsonl are NEVER included.
11
+ */
12
+ import type { ResourceGovernor } from '@telora/daemon-core';
13
+ import type { AdversarialGateConfig, GateCheckResult } from '../types.js';
14
+ /**
15
+ * Run adversarial gates for a work unit's implementation.
16
+ *
17
+ * Spawns up to `config.maxSessions` adversary Claude Code sessions, each
18
+ * writing Playwright tests to an external directory outside the worktree.
19
+ * After all sessions complete, runs ALL accumulated adversary tests and
20
+ * returns the results.
21
+ *
22
+ * Each adversary session is tracked with session_type='adversary'.
23
+ *
24
+ * @param worktreePath Absolute path to the factory worktree.
25
+ * @param specification The factory specification text.
26
+ * @param config Adversarial gate config from the blueprint (nullable).
27
+ * @param instanceId Factory instance ID (for session tracking).
28
+ * @param claudeCodePath Path to the Claude Code CLI executable.
29
+ * @returns Overall pass/fail and individual check results.
30
+ */
31
+ export declare function runAdversarialGates(worktreePath: string, specification: string, config: AdversarialGateConfig | null, instanceId: string, claudeCodePath: string, governor?: ResourceGovernor | null): Promise<{
32
+ passed: boolean;
33
+ results: GateCheckResult[];
34
+ }>;
35
+ //# sourceMappingURL=adversary-spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adversary-spawner.d.ts","sourceRoot":"","sources":["../../src/gates/adversary-spawner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAuM1E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,qBAAqB,GAAG,IAAI,EACpC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,gBAAgB,GAAG,IAAI,GACjC,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CAiJ1D"}