@devflow-tools/workflow-engine 0.16.22 → 0.16.24
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/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workers/context-session.d.ts +52 -0
- package/dist/workers/context-session.d.ts.map +1 -0
- package/dist/workers/context-session.js +70 -0
- package/dist/workers/context-session.js.map +1 -0
- package/dist/workers/file-ownership.d.ts +13 -0
- package/dist/workers/file-ownership.d.ts.map +1 -0
- package/dist/workers/file-ownership.js +87 -0
- package/dist/workers/file-ownership.js.map +1 -0
- package/dist/workers/git-worktree.d.ts +33 -0
- package/dist/workers/git-worktree.d.ts.map +1 -0
- package/dist/workers/git-worktree.js +121 -0
- package/dist/workers/git-worktree.js.map +1 -0
- package/dist/workers/handoff.d.ts +11 -0
- package/dist/workers/handoff.d.ts.map +1 -0
- package/dist/workers/handoff.js +64 -0
- package/dist/workers/handoff.js.map +1 -0
- package/dist/workers/host-launcher.d.ts +21 -0
- package/dist/workers/host-launcher.d.ts.map +1 -0
- package/dist/workers/host-launcher.js +99 -0
- package/dist/workers/host-launcher.js.map +1 -0
- package/dist/workers/index.d.ts +11 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +11 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/merge-queue.d.ts +55 -0
- package/dist/workers/merge-queue.d.ts.map +1 -0
- package/dist/workers/merge-queue.js +76 -0
- package/dist/workers/merge-queue.js.map +1 -0
- package/dist/workers/paths.d.ts +8 -0
- package/dist/workers/paths.d.ts.map +1 -0
- package/dist/workers/paths.js +63 -0
- package/dist/workers/paths.js.map +1 -0
- package/dist/workers/scheduler.d.ts +19 -0
- package/dist/workers/scheduler.d.ts.map +1 -0
- package/dist/workers/scheduler.js +37 -0
- package/dist/workers/scheduler.js.map +1 -0
- package/dist/workers/types.d.ts +78 -0
- package/dist/workers/types.d.ts.map +1 -0
- package/dist/workers/types.js +2 -0
- package/dist/workers/types.js.map +1 -0
- package/dist/workers/verifier.d.ts +66 -0
- package/dist/workers/verifier.d.ts.map +1 -0
- package/dist/workers/verifier.js +123 -0
- package/dist/workers/verifier.js.map +1 -0
- package/dist/workflow-engine.d.ts +2 -0
- package/dist/workflow-engine.d.ts.map +1 -1
- package/dist/workflow-engine.js +101 -3
- package/dist/workflow-engine.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
import type { HostAdapter, HostWorkerLaunchProjection } from '@devflow-tools/sdk';
|
|
3
|
+
import type { WorkerCoordinationPaths, WorkerHandoff, WorkerLaunchRequest, WorkerTaskEnvelope } from './types.js';
|
|
4
|
+
export interface WorkerProcessResult {
|
|
5
|
+
exitCode: number | null;
|
|
6
|
+
signal: NodeJS.Signals | null;
|
|
7
|
+
timedOut: boolean;
|
|
8
|
+
cancelled: boolean;
|
|
9
|
+
handoff?: WorkerHandoff;
|
|
10
|
+
}
|
|
11
|
+
export declare function createWorkerArtifacts(paths: WorkerCoordinationPaths, envelope: WorkerTaskEnvelope): void;
|
|
12
|
+
export declare function projectWorkerLaunch(adapter: HostAdapter, request: WorkerLaunchRequest): HostWorkerLaunchProjection;
|
|
13
|
+
export declare function launchWorker(adapter: HostAdapter, request: WorkerLaunchRequest, paths: WorkerCoordinationPaths, options?: {
|
|
14
|
+
parentEnv?: NodeJS.ProcessEnv;
|
|
15
|
+
onHeartbeat?: () => void;
|
|
16
|
+
}): {
|
|
17
|
+
child: ChildProcess;
|
|
18
|
+
completion: Promise<WorkerProcessResult>;
|
|
19
|
+
cancel: () => void;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=host-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-launcher.d.ts","sourceRoot":"","sources":["../../src/workers/host-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,kBAAkB,GAC3B,IAAI,CAQN;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,GAC3B,0BAA0B,CAgB5B;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACxE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CA4DvF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { closeSync, mkdirSync, openSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { readWorkerHandoff, writeJsonAtomic, writeWorkerTask } from './handoff.js';
|
|
5
|
+
const ALLOWED_ENV_KEYS = new Set([
|
|
6
|
+
'PATH', 'HOME', 'USER', 'SHELL', 'TMPDIR', 'LANG', 'LC_ALL',
|
|
7
|
+
'CODEX_HOME', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY',
|
|
8
|
+
]);
|
|
9
|
+
export function createWorkerArtifacts(paths, envelope) {
|
|
10
|
+
mkdirSync(paths.root, { recursive: true, mode: 0o700 });
|
|
11
|
+
writeWorkerTask(paths.taskFile, envelope);
|
|
12
|
+
writeJsonAtomic(paths.statusFile, {
|
|
13
|
+
workerId: envelope.workerId,
|
|
14
|
+
state: 'planned',
|
|
15
|
+
updatedAt: Date.now(),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function projectWorkerLaunch(adapter, request) {
|
|
19
|
+
if (!adapter.workers) {
|
|
20
|
+
return {
|
|
21
|
+
status: 'unavailable', args: [], env: {}, detached: false,
|
|
22
|
+
completionFormat: 'handoff-file', reason: `Host ${adapter.id} does not support isolated workers.`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const projection = adapter.workers.project(request);
|
|
26
|
+
if (projection.command?.includes('\0') || projection.args.some(arg => arg.includes('\0'))) {
|
|
27
|
+
throw new Error('WORKER_LAUNCH_INVALID_ARGUMENT');
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
...projection,
|
|
31
|
+
env: Object.fromEntries(Object.entries(projection.env)
|
|
32
|
+
.filter(([key, value]) => key.startsWith('DEVFLOW_') && typeof value === 'string')),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function launchWorker(adapter, request, paths, options = {}) {
|
|
36
|
+
const projection = projectWorkerLaunch(adapter, request);
|
|
37
|
+
if (projection.status !== 'supported' || !projection.command) {
|
|
38
|
+
throw new Error(`WORKER_HOST_UNAVAILABLE:${projection.reason ?? adapter.id}`);
|
|
39
|
+
}
|
|
40
|
+
mkdirSync(dirname(paths.stdoutFile), { recursive: true });
|
|
41
|
+
const stdoutFd = openSync(paths.stdoutFile, 'a', 0o600);
|
|
42
|
+
const stderrFd = openSync(paths.stderrFile, 'a', 0o600);
|
|
43
|
+
const parentEnv = Object.fromEntries(Object.entries(options.parentEnv ?? process.env)
|
|
44
|
+
.filter(([key, value]) => ALLOWED_ENV_KEYS.has(key) && typeof value === 'string'));
|
|
45
|
+
const child = spawn(projection.command, projection.args, {
|
|
46
|
+
cwd: request.worktreePath,
|
|
47
|
+
shell: false,
|
|
48
|
+
detached: projection.detached,
|
|
49
|
+
stdio: ['ignore', stdoutFd, stderrFd],
|
|
50
|
+
env: { ...parentEnv, ...projection.env },
|
|
51
|
+
});
|
|
52
|
+
if (projection.detached)
|
|
53
|
+
child.unref();
|
|
54
|
+
closeSync(stdoutFd);
|
|
55
|
+
closeSync(stderrFd);
|
|
56
|
+
let timedOut = false;
|
|
57
|
+
let cancelled = false;
|
|
58
|
+
const terminate = () => {
|
|
59
|
+
if (child.exitCode !== null)
|
|
60
|
+
return;
|
|
61
|
+
child.kill('SIGTERM');
|
|
62
|
+
setTimeout(() => child.kill('SIGKILL'), 2_000).unref();
|
|
63
|
+
};
|
|
64
|
+
const timer = setTimeout(() => { timedOut = true; terminate(); }, request.timeoutMs);
|
|
65
|
+
timer.unref();
|
|
66
|
+
const heartbeat = setInterval(() => options.onHeartbeat?.(), 10_000);
|
|
67
|
+
heartbeat.unref();
|
|
68
|
+
const completion = new Promise((resolve, reject) => {
|
|
69
|
+
child.on('error', error => {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
clearInterval(heartbeat);
|
|
72
|
+
reject(error);
|
|
73
|
+
});
|
|
74
|
+
child.on('close', (exitCode, signal) => {
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
clearInterval(heartbeat);
|
|
77
|
+
let handoff;
|
|
78
|
+
try {
|
|
79
|
+
handoff = readWorkerHandoff(paths.handoffFile, {
|
|
80
|
+
workerId: request.workerId,
|
|
81
|
+
runId: request.runId,
|
|
82
|
+
stepId: request.stepId,
|
|
83
|
+
contextReceipt: request.contextReceipt,
|
|
84
|
+
worktreePath: request.worktreePath,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Process exit is only a report event; missing handoff is handled by verification.
|
|
89
|
+
}
|
|
90
|
+
resolve({ exitCode, signal, timedOut, cancelled, handoff });
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
child,
|
|
95
|
+
completion,
|
|
96
|
+
cancel: () => { cancelled = true; terminate(); },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=host-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-launcher.js","sourceRoot":"","sources":["../../src/workers/host-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './paths.js';
|
|
3
|
+
export * from './git-worktree.js';
|
|
4
|
+
export * from './handoff.js';
|
|
5
|
+
export * from './host-launcher.js';
|
|
6
|
+
export * from './file-ownership.js';
|
|
7
|
+
export * from './scheduler.js';
|
|
8
|
+
export * from './context-session.js';
|
|
9
|
+
export * from './verifier.js';
|
|
10
|
+
export * from './merge-queue.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './paths.js';
|
|
3
|
+
export * from './git-worktree.js';
|
|
4
|
+
export * from './handoff.js';
|
|
5
|
+
export * from './host-launcher.js';
|
|
6
|
+
export * from './file-ownership.js';
|
|
7
|
+
export * from './scheduler.js';
|
|
8
|
+
export * from './context-session.js';
|
|
9
|
+
export * from './verifier.js';
|
|
10
|
+
export * from './merge-queue.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { WorkerVerificationResult } from './verifier.js';
|
|
2
|
+
export interface MergeQueueRecord {
|
|
3
|
+
mergeId: string;
|
|
4
|
+
workerId: string;
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
state: 'waiting' | 'ready' | 'conflict' | 'merged' | 'rejected';
|
|
7
|
+
parentRevision: string;
|
|
8
|
+
candidateRevision: string;
|
|
9
|
+
graderReceipts: string[];
|
|
10
|
+
simulationHash?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MergeQueueStore {
|
|
13
|
+
enqueueWorkflowMerge(input: {
|
|
14
|
+
workerId: string;
|
|
15
|
+
projectRoot: string;
|
|
16
|
+
baseRevision: string;
|
|
17
|
+
parentRevision: string;
|
|
18
|
+
candidateRevision: string;
|
|
19
|
+
graderReceipts: string[];
|
|
20
|
+
simulationHash?: string;
|
|
21
|
+
}): MergeQueueRecord | Promise<MergeQueueRecord>;
|
|
22
|
+
transitionWorkflowMerge(projectRoot: string, mergeId: string, target: MergeQueueRecord['state'], update?: {
|
|
23
|
+
parentRevision?: string;
|
|
24
|
+
simulationHash?: string;
|
|
25
|
+
mergeCommit?: string;
|
|
26
|
+
reason?: string;
|
|
27
|
+
}): MergeQueueRecord | Promise<MergeQueueRecord>;
|
|
28
|
+
}
|
|
29
|
+
export declare class SerializedWorkerMergeQueue {
|
|
30
|
+
private readonly store;
|
|
31
|
+
private readonly lifecycle;
|
|
32
|
+
constructor(store: MergeQueueStore, lifecycle?: {
|
|
33
|
+
onMerged?: (input: {
|
|
34
|
+
workerId: string;
|
|
35
|
+
mergeCommit: string;
|
|
36
|
+
}) => void | Promise<void>;
|
|
37
|
+
scheduleCleanup?: (input: {
|
|
38
|
+
workerId: string;
|
|
39
|
+
mergeCommit: string;
|
|
40
|
+
}) => void | Promise<void>;
|
|
41
|
+
});
|
|
42
|
+
enqueueAndMerge(input: {
|
|
43
|
+
workerId: string;
|
|
44
|
+
projectRoot: string;
|
|
45
|
+
baseRevision: string;
|
|
46
|
+
verification: WorkerVerificationResult;
|
|
47
|
+
message: string;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
state: 'merged' | 'conflict';
|
|
50
|
+
mergeCommit?: string;
|
|
51
|
+
reason?: string;
|
|
52
|
+
}>;
|
|
53
|
+
private serialize;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=merge-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-queue.d.ts","sourceRoot":"","sources":["../../src/workers/merge-queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,oBAAoB,CAAC,KAAK,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjD,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,EACjC,MAAM,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACnG,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjD;AAID,qBAAa,0BAA0B;IAEnC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,eAAe,EACtB,SAAS,GAAE;QAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACtF,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACzF;IAGF,eAAe,CAAC,KAAK,EAAE;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,wBAAwB,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YAiDtE,SAAS;CAYxB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { gitRevision, runGit, simulateMerge } from './git-worktree.js';
|
|
3
|
+
const projectQueues = new Map();
|
|
4
|
+
export class SerializedWorkerMergeQueue {
|
|
5
|
+
store;
|
|
6
|
+
lifecycle;
|
|
7
|
+
constructor(store, lifecycle = {}) {
|
|
8
|
+
this.store = store;
|
|
9
|
+
this.lifecycle = lifecycle;
|
|
10
|
+
}
|
|
11
|
+
async enqueueAndMerge(input) {
|
|
12
|
+
if (!input.verification.passed || !input.verification.finalRevision || !input.verification.simulationHash) {
|
|
13
|
+
throw new Error('WORKER_MERGE_REQUIRES_VERIFIED_EVIDENCE');
|
|
14
|
+
}
|
|
15
|
+
const record = await this.store.enqueueWorkflowMerge({
|
|
16
|
+
workerId: input.workerId,
|
|
17
|
+
projectRoot: input.projectRoot,
|
|
18
|
+
baseRevision: input.baseRevision,
|
|
19
|
+
parentRevision: input.verification.parentRevision,
|
|
20
|
+
candidateRevision: input.verification.finalRevision,
|
|
21
|
+
graderReceipts: input.verification.graderReceipts,
|
|
22
|
+
simulationHash: input.verification.simulationHash,
|
|
23
|
+
});
|
|
24
|
+
return this.serialize(input.projectRoot, async () => {
|
|
25
|
+
const currentParent = await gitRevision(input.projectRoot, 'HEAD');
|
|
26
|
+
if (currentParent !== record.parentRevision) {
|
|
27
|
+
await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', {
|
|
28
|
+
parentRevision: currentParent, reason: 'parent_advanced_after_simulation',
|
|
29
|
+
});
|
|
30
|
+
return { state: 'conflict', reason: 'parent_advanced_after_simulation' };
|
|
31
|
+
}
|
|
32
|
+
const simulation = await simulateMerge(input.projectRoot, currentParent, record.candidateRevision);
|
|
33
|
+
const currentHash = createHash('sha256').update(JSON.stringify({
|
|
34
|
+
parent: currentParent, candidate: record.candidateRevision, exitCode: simulation.exitCode,
|
|
35
|
+
stdout: simulation.stdout, stderr: simulation.stderr,
|
|
36
|
+
})).digest('hex');
|
|
37
|
+
if (simulation.exitCode !== 0 || currentHash !== record.simulationHash) {
|
|
38
|
+
await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', {
|
|
39
|
+
simulationHash: currentHash, reason: 'merge_simulation_changed',
|
|
40
|
+
});
|
|
41
|
+
return { state: 'conflict', reason: 'merge_simulation_changed' };
|
|
42
|
+
}
|
|
43
|
+
await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'ready');
|
|
44
|
+
const merged = await runGit(input.projectRoot, [
|
|
45
|
+
'merge', '--no-ff', '--no-edit', '-m', input.message.slice(0, 500), record.candidateRevision,
|
|
46
|
+
], { timeoutMs: 120_000, maxOutputBytes: 1_000_000 });
|
|
47
|
+
if (merged.exitCode !== 0) {
|
|
48
|
+
await runGit(input.projectRoot, ['merge', '--abort']);
|
|
49
|
+
await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', { reason: 'merge_command_conflict' });
|
|
50
|
+
return { state: 'conflict', reason: 'merge_command_conflict' };
|
|
51
|
+
}
|
|
52
|
+
const mergeCommit = await gitRevision(input.projectRoot, 'HEAD');
|
|
53
|
+
await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'merged', { mergeCommit });
|
|
54
|
+
await this.lifecycle.onMerged?.({ workerId: input.workerId, mergeCommit });
|
|
55
|
+
await this.lifecycle.scheduleCleanup?.({ workerId: input.workerId, mergeCommit });
|
|
56
|
+
return { state: 'merged', mergeCommit };
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async serialize(projectRoot, operation) {
|
|
60
|
+
const prior = projectQueues.get(projectRoot) ?? Promise.resolve();
|
|
61
|
+
let release;
|
|
62
|
+
const current = new Promise(resolve => { release = resolve; });
|
|
63
|
+
const queued = prior.then(() => current);
|
|
64
|
+
projectQueues.set(projectRoot, queued);
|
|
65
|
+
await prior.catch(() => undefined);
|
|
66
|
+
try {
|
|
67
|
+
return await operation();
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
release();
|
|
71
|
+
if (projectQueues.get(projectRoot) === queued)
|
|
72
|
+
projectQueues.delete(projectRoot);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=merge-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-queue.js","sourceRoot":"","sources":["../../src/workers/merge-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function sanitizeWorkerSlug(value: string, fallback?: string): string;
|
|
2
|
+
export declare function projectWorktreeHash(repositoryRoot: string): string;
|
|
3
|
+
export declare function workerBranch(runId: string, stepId: string): string;
|
|
4
|
+
export declare function workerWorktreePath(repositoryRoot: string, runId: string, stepId: string, home?: string): string;
|
|
5
|
+
export declare function workerCoordinationRoot(workerId: string, home?: string): string;
|
|
6
|
+
export declare function isPathInside(parent: string, candidate: string): boolean;
|
|
7
|
+
export declare function assertSafeWorkerPath(repositoryRoot: string, candidate: string, home?: string): string;
|
|
8
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/workers/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,MAAM,CAM7E;AAED,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,SAAY,GACf,MAAM,CAGR;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAY,GAAG,MAAM,CAEjF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGvE;AAED,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,SAAY,GACf,MAAM,CAoBR"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
5
|
+
export function sanitizeWorkerSlug(value, fallback = 'worker') {
|
|
6
|
+
const slug = value.trim().toLowerCase()
|
|
7
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
8
|
+
.replace(/^[._-]+|[._-]+$/g, '')
|
|
9
|
+
.slice(0, 64);
|
|
10
|
+
return slug || fallback;
|
|
11
|
+
}
|
|
12
|
+
export function projectWorktreeHash(repositoryRoot) {
|
|
13
|
+
return createHash('sha256').update(resolve(repositoryRoot)).digest('hex').slice(0, 16);
|
|
14
|
+
}
|
|
15
|
+
export function workerBranch(runId, stepId) {
|
|
16
|
+
return `devflow/${sanitizeWorkerSlug(runId, 'run')}/${sanitizeWorkerSlug(stepId, 'step')}`;
|
|
17
|
+
}
|
|
18
|
+
export function workerWorktreePath(repositoryRoot, runId, stepId, home = homedir()) {
|
|
19
|
+
const name = `${sanitizeWorkerSlug(runId, 'run')}-${sanitizeWorkerSlug(stepId, 'step')}`;
|
|
20
|
+
return join(home, '.devflow', 'worktrees', projectWorktreeHash(repositoryRoot), name);
|
|
21
|
+
}
|
|
22
|
+
export function workerCoordinationRoot(workerId, home = homedir()) {
|
|
23
|
+
return join(home, '.devflow', 'workers', sanitizeWorkerSlug(workerId));
|
|
24
|
+
}
|
|
25
|
+
export function isPathInside(parent, candidate) {
|
|
26
|
+
const rel = relative(resolve(parent), resolve(candidate));
|
|
27
|
+
return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel));
|
|
28
|
+
}
|
|
29
|
+
export function assertSafeWorkerPath(repositoryRoot, candidate, home = homedir()) {
|
|
30
|
+
const expectedRoot = canonicalizeThroughExistingAncestor(resolve(home, '.devflow', 'worktrees', projectWorktreeHash(repositoryRoot)));
|
|
31
|
+
const resolvedCandidate = canonicalizeThroughExistingAncestor(candidate);
|
|
32
|
+
if (!isPathInside(expectedRoot, resolvedCandidate) || resolvedCandidate === expectedRoot) {
|
|
33
|
+
throw new Error(`WORKTREE_PATH_OUTSIDE_MANAGED_ROOT:${candidate}`);
|
|
34
|
+
}
|
|
35
|
+
if (isPathInside(repositoryRoot, resolvedCandidate)) {
|
|
36
|
+
throw new Error(`WORKTREE_PATH_INSIDE_SOURCE:${candidate}`);
|
|
37
|
+
}
|
|
38
|
+
const parent = resolve(resolvedCandidate, '..');
|
|
39
|
+
if (existsSync(parent)) {
|
|
40
|
+
const realParent = realpathSync(parent);
|
|
41
|
+
if (!isPathInside(expectedRoot, realParent)) {
|
|
42
|
+
throw new Error(`WORKTREE_PATH_SYMLINK_ESCAPE:${candidate}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!basename(resolvedCandidate).trim())
|
|
46
|
+
throw new Error('WORKTREE_PATH_EMPTY_NAME');
|
|
47
|
+
return resolvedCandidate;
|
|
48
|
+
}
|
|
49
|
+
function canonicalizeThroughExistingAncestor(path) {
|
|
50
|
+
const resolved = resolve(path);
|
|
51
|
+
let ancestor = resolved;
|
|
52
|
+
const suffix = [];
|
|
53
|
+
while (!existsSync(ancestor)) {
|
|
54
|
+
const parent = dirname(ancestor);
|
|
55
|
+
if (parent === ancestor)
|
|
56
|
+
break;
|
|
57
|
+
suffix.unshift(basename(ancestor));
|
|
58
|
+
ancestor = parent;
|
|
59
|
+
}
|
|
60
|
+
const canonicalAncestor = existsSync(ancestor) ? realpathSync(ancestor) : ancestor;
|
|
61
|
+
return resolve(canonicalAncestor, ...suffix);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/workers/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,QAAQ,GAAG,QAAQ;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,IAAI,IAAI,QAAQ,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,cAAsB;IACxD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc;IACxD,OAAO,WAAW,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,cAAsB,EACtB,KAAa,EACb,MAAc,EACd,IAAI,GAAG,OAAO,EAAE;IAEhB,MAAM,IAAI,GAAG,GAAG,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACzF,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,mBAAmB,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB,EAAE,IAAI,GAAG,OAAO,EAAE;IACvE,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,SAAiB;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1D,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,cAAsB,EACtB,SAAiB,EACjB,IAAI,GAAG,OAAO,EAAE;IAEhB,MAAM,YAAY,GAAG,mCAAmC,CACtD,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAC5E,CAAC;IACF,MAAM,iBAAiB,GAAG,mCAAmC,CAAC,SAAS,CAAC,CAAC;IACzE,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,iBAAiB,CAAC,IAAI,iBAAiB,KAAK,YAAY,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,sCAAsC,SAAS,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,YAAY,CAAC,cAAc,EAAE,iBAAiB,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACrF,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,mCAAmC,CAAC,IAAY;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,QAAQ;YAAE,MAAM;QAC/B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnC,QAAQ,GAAG,MAAM,CAAC;IACpB,CAAC;IACD,MAAM,iBAAiB,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnF,OAAO,OAAO,CAAC,iBAAiB,EAAE,GAAG,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StepInstruction, WorkflowStepDef } from '@devflow-tools/sdk';
|
|
2
|
+
import { type FileOwnership } from './file-ownership.js';
|
|
3
|
+
export interface ScheduledWorkerStep<T> {
|
|
4
|
+
step: T;
|
|
5
|
+
ownership: FileOwnership;
|
|
6
|
+
eligible: boolean;
|
|
7
|
+
reason?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkerSchedule<T> {
|
|
10
|
+
batches: Array<Array<ScheduledWorkerStep<T>>>;
|
|
11
|
+
maxConcurrency: number;
|
|
12
|
+
recursiveRequestRejected: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveWorkerConcurrency(env?: NodeJS.ProcessEnv): number;
|
|
15
|
+
export declare function scheduleWorkerSteps<T extends WorkflowStepDef | StepInstruction>(steps: T[], inputs?: Map<string, Record<string, unknown>>, options?: {
|
|
16
|
+
maxConcurrency?: number;
|
|
17
|
+
recursiveRequest?: boolean;
|
|
18
|
+
}): WorkerSchedule<T>;
|
|
19
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/workers/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElG,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAIrF;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAC7E,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,GAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa,EACxD,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GACpE,cAAc,CAAC,CAAC,CAAC,CA0BnB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ownershipOverlaps, predictFileOwnership } from './file-ownership.js';
|
|
2
|
+
export function resolveWorkerConcurrency(env = process.env) {
|
|
3
|
+
const requested = Number(env.DEVFLOW_WORKER_CONCURRENCY ?? 3);
|
|
4
|
+
if (!Number.isFinite(requested))
|
|
5
|
+
return 3;
|
|
6
|
+
return Math.max(1, Math.min(3, Math.floor(requested)));
|
|
7
|
+
}
|
|
8
|
+
export function scheduleWorkerSteps(steps, inputs = new Map(), options = {}) {
|
|
9
|
+
const maxConcurrency = Math.max(1, Math.min(3, options.maxConcurrency ?? resolveWorkerConcurrency()));
|
|
10
|
+
if (options.recursiveRequest) {
|
|
11
|
+
return { batches: [], maxConcurrency, recursiveRequestRejected: true };
|
|
12
|
+
}
|
|
13
|
+
const scheduled = steps.map(step => {
|
|
14
|
+
const ownership = predictFileOwnership(step, inputs.get(step.id) ?? {});
|
|
15
|
+
return {
|
|
16
|
+
step,
|
|
17
|
+
ownership,
|
|
18
|
+
eligible: ownership.risk === 'low',
|
|
19
|
+
...(ownership.risk === 'high' ? { reason: ownership.reasons.join(',') } : {}),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
const batches = [];
|
|
23
|
+
for (const candidate of scheduled) {
|
|
24
|
+
if (!candidate.eligible) {
|
|
25
|
+
batches.push([candidate]);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const batch = batches.find(current => current.length < maxConcurrency
|
|
29
|
+
&& current.every(existing => existing.eligible && !ownershipOverlaps(existing.ownership, candidate.ownership)));
|
|
30
|
+
if (batch)
|
|
31
|
+
batch.push(candidate);
|
|
32
|
+
else
|
|
33
|
+
batches.push([candidate]);
|
|
34
|
+
}
|
|
35
|
+
return { batches, maxConcurrency, recursiveRequestRejected: false };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/workers/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAelG,MAAM,UAAU,wBAAwB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,IAAI,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAU,EACV,SAA+C,IAAI,GAAG,EAAE,EACxD,UAAmE,EAAE;IAErE,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,wBAAwB,EAAE,CAAC,CAAC,CAAC;IACtG,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACjC,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,OAAO;YACL,IAAI;YACJ,SAAS;YACT,QAAQ,EAAE,SAAS,CAAC,IAAI,KAAK,KAAK;YAClC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7C,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAyC,EAAE,CAAC;IACzD,KAAK,MAAM,SAAS,IAAI,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,cAAc;eAChE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAClH,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type WorkerHost = 'claude-code' | 'codex' | 'custom';
|
|
2
|
+
export interface WorkerLaunchRequest {
|
|
3
|
+
workerId: string;
|
|
4
|
+
runId: string;
|
|
5
|
+
stepId: string;
|
|
6
|
+
host: WorkerHost;
|
|
7
|
+
worktreePath: string;
|
|
8
|
+
taskFile: string;
|
|
9
|
+
handoffFile: string;
|
|
10
|
+
statusFile: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
executionId: string;
|
|
13
|
+
contextReceipt: string;
|
|
14
|
+
timeoutMs: number;
|
|
15
|
+
}
|
|
16
|
+
export interface WorkerTaskEnvelope {
|
|
17
|
+
workerId: string;
|
|
18
|
+
runId: string;
|
|
19
|
+
stepId: string;
|
|
20
|
+
projectRoot: string;
|
|
21
|
+
worktreePath: string;
|
|
22
|
+
baseRevision: string;
|
|
23
|
+
contextReceipt: string;
|
|
24
|
+
retrievalSessionId?: string;
|
|
25
|
+
allowedFiles: string[];
|
|
26
|
+
requiredTools: string[];
|
|
27
|
+
task: Record<string, unknown>;
|
|
28
|
+
verification: {
|
|
29
|
+
commands: Array<{
|
|
30
|
+
command: string;
|
|
31
|
+
args: string[];
|
|
32
|
+
}>;
|
|
33
|
+
graders: string[];
|
|
34
|
+
};
|
|
35
|
+
constraints: {
|
|
36
|
+
recursiveWorkers: false;
|
|
37
|
+
maxContextCycles: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface WorkerHandoff {
|
|
41
|
+
workerId: string;
|
|
42
|
+
runId: string;
|
|
43
|
+
stepId: string;
|
|
44
|
+
baseRevision: string;
|
|
45
|
+
finalRevision: string;
|
|
46
|
+
changedFiles: string[];
|
|
47
|
+
contextReceipt: string;
|
|
48
|
+
toolReceipts: string[];
|
|
49
|
+
reportReceipts: string[];
|
|
50
|
+
verificationIntent: string[];
|
|
51
|
+
summary: string;
|
|
52
|
+
hostStatus: 'completed' | 'failed' | 'cancelled' | 'timed_out';
|
|
53
|
+
}
|
|
54
|
+
export interface WorkerCoordinationPaths {
|
|
55
|
+
root: string;
|
|
56
|
+
taskFile: string;
|
|
57
|
+
handoffFile: string;
|
|
58
|
+
statusFile: string;
|
|
59
|
+
stdoutFile: string;
|
|
60
|
+
stderrFile: string;
|
|
61
|
+
}
|
|
62
|
+
export interface GitCommandResult {
|
|
63
|
+
command: string;
|
|
64
|
+
args: string[];
|
|
65
|
+
cwd: string;
|
|
66
|
+
exitCode: number;
|
|
67
|
+
stdout: string;
|
|
68
|
+
stderr: string;
|
|
69
|
+
timedOut: boolean;
|
|
70
|
+
truncated: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface WorktreeDescriptor {
|
|
73
|
+
repositoryRoot: string;
|
|
74
|
+
worktreePath: string;
|
|
75
|
+
branch: string;
|
|
76
|
+
baseRevision: string;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workers/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,YAAY,EAAE;QACZ,QAAQ,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;QACrD,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,gBAAgB,EAAE,KAAK,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;CAChE;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workers/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { WorkerHandoff } from './types.js';
|
|
2
|
+
export interface WorkerGraderResult {
|
|
3
|
+
graderId: string;
|
|
4
|
+
kind: 'deterministic' | 'model' | 'human';
|
|
5
|
+
status: 'passed' | 'failed' | 'unavailable';
|
|
6
|
+
receipt: string;
|
|
7
|
+
reason?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkerGraderSummary {
|
|
10
|
+
status: 'passed' | 'failed' | 'unavailable';
|
|
11
|
+
results: WorkerGraderResult[];
|
|
12
|
+
blockingFailures: string[];
|
|
13
|
+
unavailableBlocking: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface WorkerGraderRunner {
|
|
16
|
+
run(context: {
|
|
17
|
+
taskKind: string;
|
|
18
|
+
projectRoot: string;
|
|
19
|
+
evidence: Record<string, unknown>;
|
|
20
|
+
}, graderIds?: string[]): Promise<WorkerGraderSummary>;
|
|
21
|
+
}
|
|
22
|
+
export interface WorkerVerificationInput {
|
|
23
|
+
workerId: string;
|
|
24
|
+
projectRoot: string;
|
|
25
|
+
worktreePath: string;
|
|
26
|
+
baseRevision: string;
|
|
27
|
+
parentRevision: string;
|
|
28
|
+
contextReceipt: string;
|
|
29
|
+
allowedFiles: string[];
|
|
30
|
+
handoff: WorkerHandoff;
|
|
31
|
+
hostAction: {
|
|
32
|
+
state: string;
|
|
33
|
+
evidenceHash?: string;
|
|
34
|
+
report: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
graderRunner?: WorkerGraderRunner;
|
|
37
|
+
graderIds?: string[];
|
|
38
|
+
verificationCommands?: Array<{
|
|
39
|
+
command: string;
|
|
40
|
+
args: string[];
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export interface WorkerVerificationResult {
|
|
45
|
+
passed: boolean;
|
|
46
|
+
state: 'merge_ready' | 'hold' | 'failed';
|
|
47
|
+
reason?: string;
|
|
48
|
+
finalRevision?: string;
|
|
49
|
+
changedFiles: string[];
|
|
50
|
+
graderReceipts: string[];
|
|
51
|
+
simulationHash?: string;
|
|
52
|
+
parentRevision: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function verifyWorkerOutput(input: WorkerVerificationInput): Promise<WorkerVerificationResult>;
|
|
55
|
+
export declare function runVerificationCommands(cwd: string, commands: Array<{
|
|
56
|
+
command: string;
|
|
57
|
+
args: string[];
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
}>): Promise<Array<{
|
|
60
|
+
command: string;
|
|
61
|
+
args: string[];
|
|
62
|
+
exitCode: number;
|
|
63
|
+
timedOut: boolean;
|
|
64
|
+
outputHash: string;
|
|
65
|
+
}>>;
|
|
66
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/workers/verifier.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC;IAC1C,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC5C,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,OAAO,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACtF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA2D1G;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACvE,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAoC9G"}
|