@wjarka/cezarion 0.14.9-dev.933 → 0.14.9-dev.936
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/ci-wait/controller.d.ts +12 -12
- package/dist/delegation/process-liveness.d.ts +66 -0
- package/dist/delegation/process-liveness.js +215 -0
- package/dist/delegation/process-liveness.js.map +1 -0
- package/dist/delegation/routes.d.ts +54 -54
- package/dist/delegation/service.d.ts +2 -0
- package/dist/delegation/service.js +15 -3
- package/dist/delegation/service.js.map +1 -1
- package/dist/runs/agent-tmpdir.d.ts +2 -0
- package/dist/runs/agent-tmpdir.js +5 -2
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/store.d.ts +10 -0
- package/dist/runs/store.js +76 -0
- package/dist/runs/store.js.map +1 -1
- package/dist/server/server.d.ts +1221 -1221
- package/dist/workflows/run.d.ts +55 -1
- package/dist/workflows/run.js +235 -10
- package/dist/workflows/run.js.map +1 -1
- package/package.json +3 -3
|
@@ -41,17 +41,11 @@ export declare function ciToolRoutes(capabilities: Map<string, Capability>): imp
|
|
|
41
41
|
"/api/v1/tools/ci-wait": {
|
|
42
42
|
$post: {
|
|
43
43
|
output: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
prNumber: number;
|
|
47
|
-
headSha: string;
|
|
48
|
-
waitId: string;
|
|
49
|
-
registeredAt: string;
|
|
50
|
-
deadline: string;
|
|
51
|
-
phase: "delivered" | "parked" | "registered" | "wake-pending" | "withdrawn";
|
|
44
|
+
code: "authentication" | "capacity" | "command_failed" | "gh_missing" | "inaccessible_pr" | "invalid_request" | "malformed_data" | "output_limit" | "persistence" | "query_timeout" | "unauthorized" | "unavailable" | "unsupported_host" | "wait_conflict";
|
|
45
|
+
message: string;
|
|
52
46
|
};
|
|
53
47
|
outputFormat: "json";
|
|
54
|
-
status:
|
|
48
|
+
status: 503;
|
|
55
49
|
input: {
|
|
56
50
|
json: {
|
|
57
51
|
pr: string;
|
|
@@ -60,11 +54,17 @@ export declare function ciToolRoutes(capabilities: Map<string, Capability>): imp
|
|
|
60
54
|
};
|
|
61
55
|
} | {
|
|
62
56
|
output: {
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
prUrl: string;
|
|
58
|
+
repository: string;
|
|
59
|
+
prNumber: number;
|
|
60
|
+
headSha: string;
|
|
61
|
+
waitId: string;
|
|
62
|
+
registeredAt: string;
|
|
63
|
+
deadline: string;
|
|
64
|
+
phase: "delivered" | "parked" | "registered" | "wake-pending" | "withdrawn";
|
|
65
65
|
};
|
|
66
66
|
outputFormat: "json";
|
|
67
|
-
status:
|
|
67
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
68
68
|
input: {
|
|
69
69
|
json: {
|
|
70
70
|
pr: string;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous, dependency-free proof that a crashed worker generation's processes are gone
|
|
3
|
+
* (#469, spec 2026-09-26-worker-orphan-finalization). Sync so `continueRun` stays sync.
|
|
4
|
+
* Every uncertainty answers "alive" or "unknown", never "gone".
|
|
5
|
+
*/
|
|
6
|
+
export type RecordedProcess = {
|
|
7
|
+
pid: number;
|
|
8
|
+
startToken?: string;
|
|
9
|
+
};
|
|
10
|
+
export type WorkerProcessRecord = {
|
|
11
|
+
generation: string;
|
|
12
|
+
controller: RecordedProcess;
|
|
13
|
+
processes: RecordedProcess[];
|
|
14
|
+
};
|
|
15
|
+
export type GenerationLiveness = 'gone' | 'alive' | 'unknown';
|
|
16
|
+
/** `/proc/<pid>/stat` field 22 (`starttime`); `comm` may hold spaces and `)`, so parse after the LAST `)`. */
|
|
17
|
+
export declare function parseProcStat(stat: string): {
|
|
18
|
+
state: string;
|
|
19
|
+
startToken: string;
|
|
20
|
+
} | undefined;
|
|
21
|
+
/** One process incarnation, so a reused PID never matches. Absent when the platform cannot say. */
|
|
22
|
+
export declare function processStartToken(pid: number, platform?: NodeJS.Platform): string | undefined;
|
|
23
|
+
/** Live and the same incarnation. A token-less entry (or an unreadable current token) counts while the PID exists. */
|
|
24
|
+
export declare function recordedProcessLive(entry: RecordedProcess): boolean;
|
|
25
|
+
export declare function isCurrentProcess(entry: RecordedProcess): boolean;
|
|
26
|
+
/** The `/proc` reads the Linux scan makes; injectable because EACCES cannot be staged for real. */
|
|
27
|
+
export type ProcReader = {
|
|
28
|
+
readdir: () => string[];
|
|
29
|
+
readlink: (pid: string) => string;
|
|
30
|
+
ownerUid: (pid: string) => number | undefined;
|
|
31
|
+
startedAtMs: (pid: string) => number | undefined;
|
|
32
|
+
};
|
|
33
|
+
/** The darwin scan: `lsof` for working directories, `ps` for our own user's processes. */
|
|
34
|
+
export type DarwinReader = {
|
|
35
|
+
lsof: () => {
|
|
36
|
+
ok: boolean;
|
|
37
|
+
stdout: string;
|
|
38
|
+
};
|
|
39
|
+
ownProcesses: () => Array<{
|
|
40
|
+
pid: number;
|
|
41
|
+
startedAtMs?: number;
|
|
42
|
+
}> | undefined;
|
|
43
|
+
};
|
|
44
|
+
/** PIDs (never this process) whose working directory is one of `dirs` or beneath it, in one scan
|
|
45
|
+
* pass; `unknown` when no scan can run. cezar's own short-lived git children in a worktree make
|
|
46
|
+
* this read "alive" briefly: conservative, and a retry self-heals. `since` (epoch ms) is the
|
|
47
|
+
* earliest moment the generation's processes can have started; see the EACCES rule below. */
|
|
48
|
+
export declare function processesWithCwdUnder(dirs: string | readonly string[], platform?: NodeJS.Platform, proc?: ProcReader, since?: number, darwin?: DarwinReader): number[] | 'unknown';
|
|
49
|
+
export type GenerationProbe = {
|
|
50
|
+
liveness: GenerationLiveness;
|
|
51
|
+
controller?: number;
|
|
52
|
+
pids: number[];
|
|
53
|
+
};
|
|
54
|
+
/** A missing record (legacy) relies on the working-directory scan alone. `paths` are the
|
|
55
|
+
* worktree and every scratch location, which finalization deletes. A live foreign controller
|
|
56
|
+
* short-circuits the scan; otherwise `pids` names every live recorded or scanned process. */
|
|
57
|
+
export declare function inspectGeneration({ record, paths, since }: {
|
|
58
|
+
record?: WorkerProcessRecord;
|
|
59
|
+
paths: readonly string[];
|
|
60
|
+
since?: number;
|
|
61
|
+
}): GenerationProbe;
|
|
62
|
+
export declare function probeGeneration(input: {
|
|
63
|
+
record?: WorkerProcessRecord;
|
|
64
|
+
paths: readonly string[];
|
|
65
|
+
since?: number;
|
|
66
|
+
}): GenerationLiveness;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { readdirSync, readFileSync, readlinkSync, realpathSync, statSync } from 'node:fs';
|
|
3
|
+
import { resolve, sep } from 'node:path';
|
|
4
|
+
/** `/proc/<pid>/stat` field 22 (`starttime`); `comm` may hold spaces and `)`, so parse after the LAST `)`. */
|
|
5
|
+
export function parseProcStat(stat) {
|
|
6
|
+
const fields = stat.slice(stat.lastIndexOf(')') + 1).trim().split(/\s+/);
|
|
7
|
+
return stat.includes(')') && fields.length >= 20 && /^\d+$/.test(fields[19]) ? { state: fields[0], startToken: fields[19] } : undefined;
|
|
8
|
+
}
|
|
9
|
+
function procStat(pid) {
|
|
10
|
+
try {
|
|
11
|
+
return parseProcStat(readFileSync(`/proc/${pid}/stat`, 'utf8'));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
let bootId;
|
|
18
|
+
/** `starttime` counts ticks since boot, so it repeats across reboots; the boot id scopes it. */
|
|
19
|
+
function linuxBootId() {
|
|
20
|
+
if (bootId === undefined) {
|
|
21
|
+
try {
|
|
22
|
+
bootId = readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim() || null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
bootId = null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return bootId ?? undefined;
|
|
29
|
+
}
|
|
30
|
+
/** One process incarnation, so a reused PID never matches. Absent when the platform cannot say. */
|
|
31
|
+
export function processStartToken(pid, platform = process.platform) {
|
|
32
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
33
|
+
return undefined;
|
|
34
|
+
if (platform === 'linux') {
|
|
35
|
+
const start = procStat(pid)?.startToken;
|
|
36
|
+
const boot = linuxBootId();
|
|
37
|
+
return start && boot ? `${boot}:${start}` : start;
|
|
38
|
+
}
|
|
39
|
+
if (platform !== 'darwin')
|
|
40
|
+
return undefined;
|
|
41
|
+
// `lstart` is locale- and zone-formatted; pin both so the token is stable across cezar processes.
|
|
42
|
+
const ps = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 2_000, env: { ...process.env, LC_ALL: 'C', TZ: 'UTC' } });
|
|
43
|
+
const token = ps.status === 0 ? ps.stdout.trim() : '';
|
|
44
|
+
return token || undefined;
|
|
45
|
+
}
|
|
46
|
+
function pidExists(pid) {
|
|
47
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
48
|
+
return false;
|
|
49
|
+
try {
|
|
50
|
+
process.kill(pid, 0);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return error.code === 'EPERM';
|
|
54
|
+
}
|
|
55
|
+
// A zombie has exited; only its parent's wait remains.
|
|
56
|
+
return process.platform !== 'linux' || procStat(pid)?.state !== 'Z';
|
|
57
|
+
}
|
|
58
|
+
const LINUX_TOKEN = /^(?:[0-9a-f-]{36}:)?(\d+)$/;
|
|
59
|
+
/** Liveness-only comparison: when exactly one Linux token lacks the boot id (it was unreadable on one
|
|
60
|
+
* side), the `starttime` suffix decides. Reaping still requires an exact match. */
|
|
61
|
+
function sameIncarnation(recorded, current) {
|
|
62
|
+
if (recorded === current)
|
|
63
|
+
return true;
|
|
64
|
+
const a = LINUX_TOKEN.exec(recorded), b = LINUX_TOKEN.exec(current);
|
|
65
|
+
return !!a && !!b && recorded.includes(':') !== current.includes(':') && a[1] === b[1];
|
|
66
|
+
}
|
|
67
|
+
/** Live and the same incarnation. A token-less entry (or an unreadable current token) counts while the PID exists. */
|
|
68
|
+
export function recordedProcessLive(entry) {
|
|
69
|
+
if (!pidExists(entry.pid))
|
|
70
|
+
return false;
|
|
71
|
+
if (entry.startToken === undefined)
|
|
72
|
+
return true;
|
|
73
|
+
const current = processStartToken(entry.pid);
|
|
74
|
+
return current === undefined || sameIncarnation(entry.startToken, current);
|
|
75
|
+
}
|
|
76
|
+
export function isCurrentProcess(entry) {
|
|
77
|
+
if (entry.pid !== process.pid)
|
|
78
|
+
return false;
|
|
79
|
+
const own = processStartToken(process.pid);
|
|
80
|
+
return entry.startToken === undefined || own === undefined || sameIncarnation(entry.startToken, own);
|
|
81
|
+
}
|
|
82
|
+
let clockTicks;
|
|
83
|
+
let bootTimeMs;
|
|
84
|
+
/** Wall-clock start of a process: boot time (`/proc/stat` btime) plus its starttime ticks. */
|
|
85
|
+
function procStartedAtMs(pid) {
|
|
86
|
+
try {
|
|
87
|
+
bootTimeMs ??= Number(/^btime (\d+)$/m.exec(readFileSync('/proc/stat', 'utf8'))?.[1]) * 1000;
|
|
88
|
+
clockTicks ??= Number(spawnSync('getconf', ['CLK_TCK'], { encoding: 'utf8', timeout: 2_000 }).stdout.trim()) || 100;
|
|
89
|
+
const start = procStat(Number(pid))?.startToken;
|
|
90
|
+
return start === undefined || !Number.isFinite(bootTimeMs) ? undefined : bootTimeMs + Number(start) / clockTicks * 1000;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const realDarwin = {
|
|
97
|
+
lsof: () => {
|
|
98
|
+
const lsof = spawnSync('lsof', ['-a', '-d', 'cwd', '-Fpn'], { encoding: 'utf8', timeout: 5_000, maxBuffer: 16 * 1024 * 1024 });
|
|
99
|
+
// Status 1 is ordinary (some process unreadable); completeness is judged against `ps` instead.
|
|
100
|
+
return { ok: !lsof.error && (lsof.status === 0 || lsof.status === 1) && !!lsof.stdout, stdout: lsof.stdout ?? '' };
|
|
101
|
+
},
|
|
102
|
+
ownProcesses: () => {
|
|
103
|
+
const uid = process.getuid?.();
|
|
104
|
+
if (uid === undefined)
|
|
105
|
+
return undefined;
|
|
106
|
+
const ps = spawnSync('ps', ['-U', String(uid), '-o', 'pid=,lstart='], { encoding: 'utf8', timeout: 2_000, env: { ...process.env, LC_ALL: 'C', TZ: 'UTC' } });
|
|
107
|
+
if (ps.error || ps.status !== 0 || !ps.stdout)
|
|
108
|
+
return undefined;
|
|
109
|
+
return ps.stdout.split('\n').flatMap(line => {
|
|
110
|
+
const match = /^\s*(\d+)\s+(.+?)\s*$/.exec(line);
|
|
111
|
+
// `ps` lists itself, and lsof (which ran first) never saw it.
|
|
112
|
+
if (!match || Number(match[1]) === ps.pid)
|
|
113
|
+
return [];
|
|
114
|
+
const startedAtMs = Date.parse(`${match[2]} UTC`);
|
|
115
|
+
return [{ pid: Number(match[1]), ...(Number.isFinite(startedAtMs) ? { startedAtMs } : {}) }];
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const realProc = {
|
|
120
|
+
readdir: () => readdirSync('/proc'),
|
|
121
|
+
readlink: pid => readlinkSync(`/proc/${pid}/cwd`),
|
|
122
|
+
ownerUid: pid => { try {
|
|
123
|
+
return statSync(`/proc/${pid}`).uid;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return undefined;
|
|
127
|
+
} },
|
|
128
|
+
startedAtMs: procStartedAtMs,
|
|
129
|
+
};
|
|
130
|
+
/** PIDs (never this process) whose working directory is one of `dirs` or beneath it, in one scan
|
|
131
|
+
* pass; `unknown` when no scan can run. cezar's own short-lived git children in a worktree make
|
|
132
|
+
* this read "alive" briefly: conservative, and a retry self-heals. `since` (epoch ms) is the
|
|
133
|
+
* earliest moment the generation's processes can have started; see the EACCES rule below. */
|
|
134
|
+
export function processesWithCwdUnder(dirs, platform = process.platform, proc = realProc, since, darwin = realDarwin) {
|
|
135
|
+
const targets = (typeof dirs === 'string' ? [dirs] : dirs).map(dir => { try {
|
|
136
|
+
return realpathSync(dir);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return resolve(dir);
|
|
140
|
+
} });
|
|
141
|
+
const under = (cwd) => { const path = cwd.replace(/ \(deleted\)$/, ''); return targets.some(target => path === target || path.startsWith(target + sep)); };
|
|
142
|
+
const found = [];
|
|
143
|
+
if (platform === 'linux') {
|
|
144
|
+
let entries;
|
|
145
|
+
try {
|
|
146
|
+
entries = proc.readdir();
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return 'unknown';
|
|
150
|
+
}
|
|
151
|
+
const uid = process.getuid?.();
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (!/^\d+$/.test(entry) || Number(entry) === process.pid)
|
|
154
|
+
continue;
|
|
155
|
+
try {
|
|
156
|
+
if (under(proc.readlink(entry)))
|
|
157
|
+
found.push(Number(entry));
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
// A vanished process is gone; another user's is unreadable by design and skipped. Our own
|
|
161
|
+
// user's non-dumpable processes are unreadable too (systemd --user, sshd, gpg-agent, which
|
|
162
|
+
// every host has), so they cannot all block the proof: one that started before the worker
|
|
163
|
+
// existed cannot be its descendant. A later one is a possible holder, never signalled.
|
|
164
|
+
if (error.code === 'ENOENT' || uid === undefined || proc.ownerUid(entry) !== uid)
|
|
165
|
+
continue;
|
|
166
|
+
const started = since === undefined ? undefined : proc.startedAtMs(entry);
|
|
167
|
+
if (started === undefined || started >= since)
|
|
168
|
+
found.push(Number(entry));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return found;
|
|
172
|
+
}
|
|
173
|
+
if (platform !== 'darwin')
|
|
174
|
+
return 'unknown';
|
|
175
|
+
const lsof = darwin.lsof();
|
|
176
|
+
if (!lsof.ok)
|
|
177
|
+
return 'unknown';
|
|
178
|
+
const seen = new Set();
|
|
179
|
+
let pid;
|
|
180
|
+
for (const line of lsof.stdout.split('\n')) {
|
|
181
|
+
if (line.startsWith('p')) {
|
|
182
|
+
pid = Number(line.slice(1));
|
|
183
|
+
seen.add(pid);
|
|
184
|
+
}
|
|
185
|
+
else if (line.startsWith('n') && pid !== undefined && pid !== process.pid && under(line.slice(1)))
|
|
186
|
+
found.push(pid);
|
|
187
|
+
}
|
|
188
|
+
// lsof silently omits what it cannot read. An own-user process it omitted is judged by the
|
|
189
|
+
// Linux EACCES rule: a possible holder unless it predates the worker. Other users' are skipped.
|
|
190
|
+
const own = darwin.ownProcesses();
|
|
191
|
+
if (!own)
|
|
192
|
+
return 'unknown';
|
|
193
|
+
for (const entry of own) {
|
|
194
|
+
if (seen.has(entry.pid) || entry.pid === process.pid)
|
|
195
|
+
continue;
|
|
196
|
+
if (since === undefined || entry.startedAtMs === undefined || entry.startedAtMs >= since)
|
|
197
|
+
found.push(entry.pid);
|
|
198
|
+
}
|
|
199
|
+
return [...new Set(found)];
|
|
200
|
+
}
|
|
201
|
+
/** A missing record (legacy) relies on the working-directory scan alone. `paths` are the
|
|
202
|
+
* worktree and every scratch location, which finalization deletes. A live foreign controller
|
|
203
|
+
* short-circuits the scan; otherwise `pids` names every live recorded or scanned process. */
|
|
204
|
+
export function inspectGeneration({ record, paths, since }) {
|
|
205
|
+
if (record && !isCurrentProcess(record.controller) && recordedProcessLive(record.controller))
|
|
206
|
+
return { liveness: 'alive', controller: record.controller.pid, pids: [] };
|
|
207
|
+
const recorded = record?.processes.filter(recordedProcessLive).map(entry => entry.pid) ?? [];
|
|
208
|
+
const scan = processesWithCwdUnder(paths, process.platform, realProc, since);
|
|
209
|
+
const pids = [...new Set([...recorded, ...(scan === 'unknown' ? [] : scan)])];
|
|
210
|
+
return { liveness: pids.length ? 'alive' : scan === 'unknown' ? 'unknown' : 'gone', pids };
|
|
211
|
+
}
|
|
212
|
+
export function probeGeneration(input) {
|
|
213
|
+
return inspectGeneration(input).liveness;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=process-liveness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-liveness.js","sourceRoot":"","sources":["../../src/delegation/process-liveness.ts"],"names":[],"mappings":"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"}
|
|
@@ -82,13 +82,13 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
82
82
|
status: 200;
|
|
83
83
|
input: {
|
|
84
84
|
json: {
|
|
85
|
-
requestIds: string[];
|
|
86
|
-
mode?: "all" | "any" | "one" | undefined;
|
|
87
|
-
timeoutSeconds?: number | undefined;
|
|
88
|
-
} | {
|
|
89
85
|
workerIds: string[];
|
|
90
86
|
timeoutSeconds?: number | undefined;
|
|
91
87
|
mode?: "all" | "any" | "one" | undefined;
|
|
88
|
+
} | {
|
|
89
|
+
requestIds: string[];
|
|
90
|
+
mode?: "all" | "any" | "one" | undefined;
|
|
91
|
+
timeoutSeconds?: number | undefined;
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
94
|
};
|
|
@@ -439,18 +439,6 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
439
439
|
} & {
|
|
440
440
|
"/:workerId": {
|
|
441
441
|
$get: {
|
|
442
|
-
output: {
|
|
443
|
-
error: string;
|
|
444
|
-
code?: "invalid_input" | undefined;
|
|
445
|
-
};
|
|
446
|
-
outputFormat: "json";
|
|
447
|
-
status: 400;
|
|
448
|
-
input: {
|
|
449
|
-
param: {
|
|
450
|
-
workerId: string;
|
|
451
|
-
};
|
|
452
|
-
};
|
|
453
|
-
} | {
|
|
454
442
|
output: {
|
|
455
443
|
workerId: string;
|
|
456
444
|
parentRunId: string;
|
|
@@ -527,11 +515,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
527
515
|
workerId: string;
|
|
528
516
|
};
|
|
529
517
|
};
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
} & {
|
|
533
|
-
"/:workerId/collect": {
|
|
534
|
-
$post: {
|
|
518
|
+
} | {
|
|
535
519
|
output: {
|
|
536
520
|
error: string;
|
|
537
521
|
code?: "invalid_input" | undefined;
|
|
@@ -542,10 +526,12 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
542
526
|
param: {
|
|
543
527
|
workerId: string;
|
|
544
528
|
};
|
|
545
|
-
} & {
|
|
546
|
-
json: Record<string, never>;
|
|
547
529
|
};
|
|
548
|
-
}
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
} & {
|
|
533
|
+
"/:workerId/collect": {
|
|
534
|
+
$post: {
|
|
549
535
|
output: {
|
|
550
536
|
workerId: string;
|
|
551
537
|
parentRunId: string;
|
|
@@ -647,11 +633,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
647
633
|
} & {
|
|
648
634
|
json: Record<string, never>;
|
|
649
635
|
};
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
} & {
|
|
653
|
-
"/:workerId/steer": {
|
|
654
|
-
$post: {
|
|
636
|
+
} | {
|
|
655
637
|
output: {
|
|
656
638
|
error: string;
|
|
657
639
|
code?: "invalid_input" | undefined;
|
|
@@ -663,11 +645,13 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
663
645
|
workerId: string;
|
|
664
646
|
};
|
|
665
647
|
} & {
|
|
666
|
-
json:
|
|
667
|
-
text: string;
|
|
668
|
-
};
|
|
648
|
+
json: Record<string, never>;
|
|
669
649
|
};
|
|
670
|
-
}
|
|
650
|
+
};
|
|
651
|
+
};
|
|
652
|
+
} & {
|
|
653
|
+
"/:workerId/steer": {
|
|
654
|
+
$post: {
|
|
671
655
|
output: {
|
|
672
656
|
workerId: string;
|
|
673
657
|
state: "delivered" | "queued";
|
|
@@ -683,11 +667,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
683
667
|
text: string;
|
|
684
668
|
};
|
|
685
669
|
};
|
|
686
|
-
}
|
|
687
|
-
};
|
|
688
|
-
} & {
|
|
689
|
-
"/:workerId/stop": {
|
|
690
|
-
$post: {
|
|
670
|
+
} | {
|
|
691
671
|
output: {
|
|
692
672
|
error: string;
|
|
693
673
|
code?: "invalid_input" | undefined;
|
|
@@ -699,9 +679,15 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
699
679
|
workerId: string;
|
|
700
680
|
};
|
|
701
681
|
} & {
|
|
702
|
-
json:
|
|
682
|
+
json: {
|
|
683
|
+
text: string;
|
|
684
|
+
};
|
|
703
685
|
};
|
|
704
|
-
}
|
|
686
|
+
};
|
|
687
|
+
};
|
|
688
|
+
} & {
|
|
689
|
+
"/:workerId/stop": {
|
|
690
|
+
$post: {
|
|
705
691
|
output: {
|
|
706
692
|
workerId: string;
|
|
707
693
|
state: "stopping" | "terminated";
|
|
@@ -715,11 +701,7 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
715
701
|
} & {
|
|
716
702
|
json: Record<string, never>;
|
|
717
703
|
};
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
} & {
|
|
721
|
-
"/:workerId/destroy": {
|
|
722
|
-
$post: {
|
|
704
|
+
} | {
|
|
723
705
|
output: {
|
|
724
706
|
error: string;
|
|
725
707
|
code?: "invalid_input" | undefined;
|
|
@@ -733,7 +715,11 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
733
715
|
} & {
|
|
734
716
|
json: Record<string, never>;
|
|
735
717
|
};
|
|
736
|
-
}
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
} & {
|
|
721
|
+
"/:workerId/destroy": {
|
|
722
|
+
$post: {
|
|
737
723
|
output: {
|
|
738
724
|
workerId: string;
|
|
739
725
|
state: "complete" | "incomplete";
|
|
@@ -756,6 +742,20 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
756
742
|
} & {
|
|
757
743
|
json: Record<string, never>;
|
|
758
744
|
};
|
|
745
|
+
} | {
|
|
746
|
+
output: {
|
|
747
|
+
error: string;
|
|
748
|
+
code?: "invalid_input" | undefined;
|
|
749
|
+
};
|
|
750
|
+
outputFormat: "json";
|
|
751
|
+
status: 400;
|
|
752
|
+
input: {
|
|
753
|
+
param: {
|
|
754
|
+
workerId: string;
|
|
755
|
+
};
|
|
756
|
+
} & {
|
|
757
|
+
json: Record<string, never>;
|
|
758
|
+
};
|
|
759
759
|
} | {
|
|
760
760
|
output: {
|
|
761
761
|
workerId: string;
|
|
@@ -785,11 +785,13 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
785
785
|
"/:workerId/diff": {
|
|
786
786
|
$get: {
|
|
787
787
|
output: {
|
|
788
|
-
|
|
789
|
-
|
|
788
|
+
workerId: string;
|
|
789
|
+
baselineSha: string;
|
|
790
|
+
diff: string;
|
|
791
|
+
truncated: boolean;
|
|
790
792
|
};
|
|
791
793
|
outputFormat: "json";
|
|
792
|
-
status:
|
|
794
|
+
status: 200;
|
|
793
795
|
input: {
|
|
794
796
|
param: {
|
|
795
797
|
workerId: string;
|
|
@@ -797,13 +799,11 @@ export declare function createDelegationRoutes(service: DelegationService, crede
|
|
|
797
799
|
};
|
|
798
800
|
} | {
|
|
799
801
|
output: {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
diff: string;
|
|
803
|
-
truncated: boolean;
|
|
802
|
+
error: string;
|
|
803
|
+
code?: "invalid_input" | undefined;
|
|
804
804
|
};
|
|
805
805
|
outputFormat: "json";
|
|
806
|
-
status:
|
|
806
|
+
status: 400;
|
|
807
807
|
input: {
|
|
808
808
|
param: {
|
|
809
809
|
workerId: string;
|
|
@@ -13,6 +13,8 @@ export declare const delegationEnabled: () => boolean;
|
|
|
13
13
|
export declare class DelegationService {
|
|
14
14
|
private projects;
|
|
15
15
|
private serial;
|
|
16
|
+
/** How long destroy waits for proven termination; private and overridable so tests need not wait it out. */
|
|
17
|
+
private terminationTimeoutMs;
|
|
16
18
|
registerProject(project: DelegationProject): () => void;
|
|
17
19
|
private context;
|
|
18
20
|
private serialized;
|
|
@@ -80,6 +80,8 @@ export const delegationEnabled = () => process.env.CEZ_DELEGATION === '1';
|
|
|
80
80
|
export class DelegationService {
|
|
81
81
|
projects = new Map();
|
|
82
82
|
serial = new Map();
|
|
83
|
+
/** How long destroy waits for proven termination; private and overridable so tests need not wait it out. */
|
|
84
|
+
terminationTimeoutMs = 30_000;
|
|
83
85
|
registerProject(project) {
|
|
84
86
|
const existing = this.projects.get(project.id);
|
|
85
87
|
if (existing?.store === project.store && existing.manager === project.manager)
|
|
@@ -452,9 +454,10 @@ export class DelegationService {
|
|
|
452
454
|
});
|
|
453
455
|
}
|
|
454
456
|
async inspect(caller, params) {
|
|
455
|
-
const { worker, parent } = this.target(caller, params, 'inspect');
|
|
457
|
+
const { project, worker, parent } = this.target(caller, params, 'inspect');
|
|
456
458
|
if (worker.delegation?.role !== 'worker')
|
|
457
459
|
throw new DelegationPolicyError('denied_scope', 'Worker scope denied');
|
|
460
|
+
project.manager.settleOrphanedWorkerExecution(worker.id); // #469: an orphan that died after recovery settles
|
|
458
461
|
const outcome = workerOutcome(worker, new Date().toISOString());
|
|
459
462
|
const wait = parent.delegation?.role === 'root' ? parent.delegation.wait : undefined;
|
|
460
463
|
return { workerId: worker.id, parentRunId: parent.id, status: worker.status, workspace: worker.delegation.workspace,
|
|
@@ -477,6 +480,7 @@ export class DelegationService {
|
|
|
477
480
|
return project.store.commitWorkerResult(caller.runId, evidence, project.store.readWorkerResultDiff(caller.runId, workerId));
|
|
478
481
|
}
|
|
479
482
|
authorizeWorker(caller, worker, 'inspect', parent, project.id);
|
|
483
|
+
project.manager.settleOrphanedWorkerExecution(workerId); // #469: before `settled` is computed
|
|
480
484
|
if (parent?.delegation?.role === 'root' && parent.delegation.receipts.some(receipt => receipt.workerId === workerId && receipt.deletion?.phase === 'pending')) {
|
|
481
485
|
const retained = project.store.readWorkerResult(parent.id, workerId);
|
|
482
486
|
if (!retained || !project.store.canDeleteRun(workerId))
|
|
@@ -576,8 +580,16 @@ export class DelegationService {
|
|
|
576
580
|
persist('terminating', ['process', ...resources]);
|
|
577
581
|
project.manager.requestWorkerStop(workerId);
|
|
578
582
|
let result;
|
|
579
|
-
if (!await project.manager.awaitRunTermination(workerId,
|
|
580
|
-
|
|
583
|
+
if (!await project.manager.awaitRunTermination(workerId, this.terminationTimeoutMs, { reapOrphans: true })) {
|
|
584
|
+
// #469: name what blocks a crashed generation; other causes keep the generic message.
|
|
585
|
+
const taken = project.manager.takeWorkerTerminationBlocker(workerId);
|
|
586
|
+
const reason = taken && (taken.blocker.kind === 'unreadable' ? 'worker process record is unreadable; termination cannot be proven'
|
|
587
|
+
: taken.blocker.kind === 'controller' ? `the worker is still controlled by a live cezar (pid ${taken.blocker.pid})`
|
|
588
|
+
: `${taken.blocker.pids.length === 1 ? 'process' : 'processes'} ${taken.blocker.pids.join(', ')} still ${taken.blocker.pids.length === 1 ? 'holds' : 'hold'} the worker's worktree or scratch`);
|
|
589
|
+
if (taken?.changed)
|
|
590
|
+
project.store.appendEvent(workerId, { type: 'lifecycle', message: `destroy blocked: ${reason}` });
|
|
591
|
+
result = { workerId, state: 'incomplete', remaining: ['process', ...resources], error: !taken ? 'Worker termination is not proven; retry cleanup later'
|
|
592
|
+
: taken.blocker.kind === 'unreadable' ? reason : `Worker termination is not proven: ${reason}; retry cleanup later` };
|
|
581
593
|
}
|
|
582
594
|
else {
|
|
583
595
|
persist('cleaning', resources);
|