@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.
- package/dist/audit.d.ts +69 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +376 -0
- package/dist/audit.js.map +1 -0
- package/dist/builder-completion.d.ts +35 -0
- package/dist/builder-completion.d.ts.map +1 -0
- package/dist/builder-completion.js +375 -0
- package/dist/builder-completion.js.map +1 -0
- package/dist/builder-spawner.d.ts +40 -0
- package/dist/builder-spawner.d.ts.map +1 -0
- package/dist/builder-spawner.js +493 -0
- package/dist/builder-spawner.js.map +1 -0
- package/dist/completion-gate.d.ts +52 -0
- package/dist/completion-gate.d.ts.map +1 -0
- package/dist/completion-gate.js +336 -0
- package/dist/completion-gate.js.map +1 -0
- package/dist/completion-report.d.ts +36 -0
- package/dist/completion-report.d.ts.map +1 -0
- package/dist/completion-report.js +348 -0
- package/dist/completion-report.js.map +1 -0
- package/dist/completion.d.ts +58 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +287 -0
- package/dist/completion.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/context-manager.d.ts +152 -0
- package/dist/context-manager.d.ts.map +1 -0
- package/dist/context-manager.js +421 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/crash-detection.d.ts +70 -0
- package/dist/crash-detection.d.ts.map +1 -0
- package/dist/crash-detection.js +123 -0
- package/dist/crash-detection.js.map +1 -0
- package/dist/crash-recovery.d.ts +83 -0
- package/dist/crash-recovery.d.ts.map +1 -0
- package/dist/crash-recovery.js +522 -0
- package/dist/crash-recovery.js.map +1 -0
- package/dist/crash-resolution.d.ts +34 -0
- package/dist/crash-resolution.d.ts.map +1 -0
- package/dist/crash-resolution.js +382 -0
- package/dist/crash-resolution.js.map +1 -0
- package/dist/escalation.d.ts +150 -0
- package/dist/escalation.d.ts.map +1 -0
- package/dist/escalation.js +352 -0
- package/dist/escalation.js.map +1 -0
- package/dist/execution-target.d.ts +31 -0
- package/dist/execution-target.d.ts.map +1 -0
- package/dist/execution-target.js +71 -0
- package/dist/execution-target.js.map +1 -0
- package/dist/execution-unit-init.d.ts +28 -0
- package/dist/execution-unit-init.d.ts.map +1 -0
- package/dist/execution-unit-init.js +115 -0
- package/dist/execution-unit-init.js.map +1 -0
- package/dist/execution.d.ts +17 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +20 -0
- package/dist/execution.js.map +1 -0
- package/dist/factory-engine.d.ts +100 -0
- package/dist/factory-engine.d.ts.map +1 -0
- package/dist/factory-engine.js +243 -0
- package/dist/factory-engine.js.map +1 -0
- package/dist/gap-detection.d.ts +43 -0
- package/dist/gap-detection.d.ts.map +1 -0
- package/dist/gap-detection.js +149 -0
- package/dist/gap-detection.js.map +1 -0
- package/dist/gate-context.d.ts +23 -0
- package/dist/gate-context.d.ts.map +1 -0
- package/dist/gate-context.js +63 -0
- package/dist/gate-context.js.map +1 -0
- package/dist/gate-engine.d.ts +55 -0
- package/dist/gate-engine.d.ts.map +1 -0
- package/dist/gate-engine.js +191 -0
- package/dist/gate-engine.js.map +1 -0
- package/dist/gates/adversarial.d.ts +59 -0
- package/dist/gates/adversarial.d.ts.map +1 -0
- package/dist/gates/adversarial.js +426 -0
- package/dist/gates/adversarial.js.map +1 -0
- package/dist/gates/adversary-spawner.d.ts +35 -0
- package/dist/gates/adversary-spawner.d.ts.map +1 -0
- package/dist/gates/adversary-spawner.js +286 -0
- package/dist/gates/adversary-spawner.js.map +1 -0
- package/dist/gates/adversary-test-dir.d.ts +41 -0
- package/dist/gates/adversary-test-dir.d.ts.map +1 -0
- package/dist/gates/adversary-test-dir.js +150 -0
- package/dist/gates/adversary-test-dir.js.map +1 -0
- package/dist/gates/behavioral-parser.d.ts +32 -0
- package/dist/gates/behavioral-parser.d.ts.map +1 -0
- package/dist/gates/behavioral-parser.js +190 -0
- package/dist/gates/behavioral-parser.js.map +1 -0
- package/dist/gates/behavioral-runner.d.ts +36 -0
- package/dist/gates/behavioral-runner.d.ts.map +1 -0
- package/dist/gates/behavioral-runner.js +306 -0
- package/dist/gates/behavioral-runner.js.map +1 -0
- package/dist/gates/behavioral.d.ts +37 -0
- package/dist/gates/behavioral.d.ts.map +1 -0
- package/dist/gates/behavioral.js +485 -0
- package/dist/gates/behavioral.js.map +1 -0
- package/dist/gates/deterministic.d.ts +24 -0
- package/dist/gates/deterministic.d.ts.map +1 -0
- package/dist/gates/deterministic.js +186 -0
- package/dist/gates/deterministic.js.map +1 -0
- package/dist/git-factory.d.ts +59 -0
- package/dist/git-factory.d.ts.map +1 -0
- package/dist/git-factory.js +102 -0
- package/dist/git-factory.js.map +1 -0
- package/dist/guard-evaluation.d.ts +48 -0
- package/dist/guard-evaluation.d.ts.map +1 -0
- package/dist/guard-evaluation.js +416 -0
- package/dist/guard-evaluation.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-completion.d.ts +34 -0
- package/dist/instance-completion.d.ts.map +1 -0
- package/dist/instance-completion.js +366 -0
- package/dist/instance-completion.js.map +1 -0
- package/dist/instance-lifecycle.d.ts +15 -0
- package/dist/instance-lifecycle.d.ts.map +1 -0
- package/dist/instance-lifecycle.js +18 -0
- package/dist/instance-lifecycle.js.map +1 -0
- package/dist/instance-phase-dispatch.d.ts +75 -0
- package/dist/instance-phase-dispatch.d.ts.map +1 -0
- package/dist/instance-phase-dispatch.js +674 -0
- package/dist/instance-phase-dispatch.js.map +1 -0
- package/dist/instance-poll-loop.d.ts +43 -0
- package/dist/instance-poll-loop.d.ts.map +1 -0
- package/dist/instance-poll-loop.js +360 -0
- package/dist/instance-poll-loop.js.map +1 -0
- package/dist/instance-state-machine.d.ts +52 -0
- package/dist/instance-state-machine.d.ts.map +1 -0
- package/dist/instance-state-machine.js +235 -0
- package/dist/instance-state-machine.js.map +1 -0
- package/dist/log-manager.d.ts +28 -0
- package/dist/log-manager.d.ts.map +1 -0
- package/dist/log-manager.js +71 -0
- package/dist/log-manager.js.map +1 -0
- package/dist/pipeline-evaluator.d.ts +61 -0
- package/dist/pipeline-evaluator.d.ts.map +1 -0
- package/dist/pipeline-evaluator.js +107 -0
- package/dist/pipeline-evaluator.js.map +1 -0
- package/dist/pipeline-metrics.d.ts +52 -0
- package/dist/pipeline-metrics.d.ts.map +1 -0
- package/dist/pipeline-metrics.js +40 -0
- package/dist/pipeline-metrics.js.map +1 -0
- package/dist/pipeline-traversal.d.ts +43 -0
- package/dist/pipeline-traversal.d.ts.map +1 -0
- package/dist/pipeline-traversal.js +68 -0
- package/dist/pipeline-traversal.js.map +1 -0
- package/dist/plan-parser.d.ts +76 -0
- package/dist/plan-parser.d.ts.map +1 -0
- package/dist/plan-parser.js +223 -0
- package/dist/plan-parser.js.map +1 -0
- package/dist/planning-phase.d.ts +52 -0
- package/dist/planning-phase.d.ts.map +1 -0
- package/dist/planning-phase.js +444 -0
- package/dist/planning-phase.js.map +1 -0
- package/dist/planning-prompt.d.ts +64 -0
- package/dist/planning-prompt.d.ts.map +1 -0
- package/dist/planning-prompt.js +251 -0
- package/dist/planning-prompt.js.map +1 -0
- package/dist/planning.d.ts +16 -0
- package/dist/planning.d.ts.map +1 -0
- package/dist/planning.js +17 -0
- package/dist/planning.js.map +1 -0
- package/dist/process-runner.d.ts +41 -0
- package/dist/process-runner.d.ts.map +1 -0
- package/dist/process-runner.js +81 -0
- package/dist/process-runner.js.map +1 -0
- package/dist/product-config.d.ts +34 -0
- package/dist/product-config.d.ts.map +1 -0
- package/dist/product-config.js +43 -0
- package/dist/product-config.js.map +1 -0
- package/dist/queries/cycle-evaluations.d.ts +23 -0
- package/dist/queries/cycle-evaluations.d.ts.map +1 -0
- package/dist/queries/cycle-evaluations.js +37 -0
- package/dist/queries/cycle-evaluations.js.map +1 -0
- package/dist/queries/escalations.d.ts +30 -0
- package/dist/queries/escalations.d.ts.map +1 -0
- package/dist/queries/escalations.js +42 -0
- package/dist/queries/escalations.js.map +1 -0
- package/dist/queries/execution-units.d.ts +76 -0
- package/dist/queries/execution-units.d.ts.map +1 -0
- package/dist/queries/execution-units.js +109 -0
- package/dist/queries/execution-units.js.map +1 -0
- package/dist/queries/gate-results.d.ts +32 -0
- package/dist/queries/gate-results.d.ts.map +1 -0
- package/dist/queries/gate-results.js +44 -0
- package/dist/queries/gate-results.js.map +1 -0
- package/dist/queries/instances.d.ts +51 -0
- package/dist/queries/instances.d.ts.map +1 -0
- package/dist/queries/instances.js +77 -0
- package/dist/queries/instances.js.map +1 -0
- package/dist/queries/sessions.d.ts +50 -0
- package/dist/queries/sessions.d.ts.map +1 -0
- package/dist/queries/sessions.js +81 -0
- package/dist/queries/sessions.js.map +1 -0
- package/dist/queries/shared.d.ts +38 -0
- package/dist/queries/shared.d.ts.map +1 -0
- package/dist/queries/shared.js +119 -0
- package/dist/queries/shared.js.map +1 -0
- package/dist/queries/specs.d.ts +12 -0
- package/dist/queries/specs.d.ts.map +1 -0
- package/dist/queries/specs.js +21 -0
- package/dist/queries/specs.js.map +1 -0
- package/dist/queries/strategies.d.ts +14 -0
- package/dist/queries/strategies.d.ts.map +1 -0
- package/dist/queries/strategies.js +18 -0
- package/dist/queries/strategies.js.map +1 -0
- package/dist/queries/work-units.d.ts +42 -0
- package/dist/queries/work-units.d.ts.map +1 -0
- package/dist/queries/work-units.js +57 -0
- package/dist/queries/work-units.js.map +1 -0
- package/dist/queries/workflows.d.ts +29 -0
- package/dist/queries/workflows.d.ts.map +1 -0
- package/dist/queries/workflows.js +103 -0
- package/dist/queries/workflows.js.map +1 -0
- package/dist/remediation-units.d.ts +40 -0
- package/dist/remediation-units.d.ts.map +1 -0
- package/dist/remediation-units.js +263 -0
- package/dist/remediation-units.js.map +1 -0
- package/dist/replanning.d.ts +72 -0
- package/dist/replanning.d.ts.map +1 -0
- package/dist/replanning.js +403 -0
- package/dist/replanning.js.map +1 -0
- package/dist/resource-limits.d.ts +62 -0
- package/dist/resource-limits.d.ts.map +1 -0
- package/dist/resource-limits.js +322 -0
- package/dist/resource-limits.js.map +1 -0
- package/dist/scheduler.d.ts +98 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +203 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/session-adapter.d.ts +89 -0
- package/dist/session-adapter.d.ts.map +1 -0
- package/dist/session-adapter.js +108 -0
- package/dist/session-adapter.js.map +1 -0
- package/dist/sop-generator.d.ts +29 -0
- package/dist/sop-generator.d.ts.map +1 -0
- package/dist/sop-generator.js +235 -0
- package/dist/sop-generator.js.map +1 -0
- package/dist/spec-profiles.d.ts +41 -0
- package/dist/spec-profiles.d.ts.map +1 -0
- package/dist/spec-profiles.js +131 -0
- package/dist/spec-profiles.js.map +1 -0
- package/dist/strategy-design-graph.d.ts +23 -0
- package/dist/strategy-design-graph.d.ts.map +1 -0
- package/dist/strategy-design-graph.js +205 -0
- package/dist/strategy-design-graph.js.map +1 -0
- package/dist/strategy-design-prompt.d.ts +28 -0
- package/dist/strategy-design-prompt.d.ts.map +1 -0
- package/dist/strategy-design-prompt.js +108 -0
- package/dist/strategy-design-prompt.js.map +1 -0
- package/dist/strategy-design-schema.d.ts +767 -0
- package/dist/strategy-design-schema.d.ts.map +1 -0
- package/dist/strategy-design-schema.js +126 -0
- package/dist/strategy-design-schema.js.map +1 -0
- package/dist/strategy-design.d.ts +69 -0
- package/dist/strategy-design.d.ts.map +1 -0
- package/dist/strategy-design.js +411 -0
- package/dist/strategy-design.js.map +1 -0
- package/dist/strategy-gating.d.ts +31 -0
- package/dist/strategy-gating.d.ts.map +1 -0
- package/dist/strategy-gating.js +276 -0
- package/dist/strategy-gating.js.map +1 -0
- package/dist/team-prompt-builder.d.ts +47 -0
- package/dist/team-prompt-builder.d.ts.map +1 -0
- package/dist/team-prompt-builder.js +362 -0
- package/dist/team-prompt-builder.js.map +1 -0
- package/dist/trace-engine.d.ts +40 -0
- package/dist/trace-engine.d.ts.map +1 -0
- package/dist/trace-engine.js +344 -0
- package/dist/trace-engine.js.map +1 -0
- package/dist/types.d.ts +612 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/unit-session-lifecycle.d.ts +78 -0
- package/dist/unit-session-lifecycle.d.ts.map +1 -0
- package/dist/unit-session-lifecycle.js +141 -0
- package/dist/unit-session-lifecycle.js.map +1 -0
- package/dist/unit-session.d.ts +30 -0
- package/dist/unit-session.d.ts.map +1 -0
- package/dist/unit-session.js +370 -0
- package/dist/unit-session.js.map +1 -0
- package/dist/watchdogs.d.ts +33 -0
- package/dist/watchdogs.d.ts.map +1 -0
- package/dist/watchdogs.js +170 -0
- package/dist/watchdogs.js.map +1 -0
- package/dist/work-unit-scheduler.d.ts +34 -0
- package/dist/work-unit-scheduler.d.ts.map +1 -0
- package/dist/work-unit-scheduler.js +91 -0
- package/dist/work-unit-scheduler.js.map +1 -0
- package/dist/workflow-transition.d.ts +90 -0
- package/dist/workflow-transition.d.ts.map +1 -0
- package/dist/workflow-transition.js +340 -0
- package/dist/workflow-transition.js.map +1 -0
- 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"}
|