devharness 0.9.14 → 0.9.16
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/build/github/issue-body.d.ts +4 -4
- package/build/mcp-supervisor.js +60 -2
- package/build/mcp-supervisor.js.map +1 -1
- package/build/supervisor/client-watcher.d.ts +13 -2
- package/build/supervisor/client-watcher.d.ts.map +1 -1
- package/build/supervisor/client-watcher.js +60 -16
- package/build/supervisor/client-watcher.js.map +1 -1
- package/build/supervisor/client-watcher.test.js +110 -3
- package/build/supervisor/client-watcher.test.js.map +1 -1
- package/build/supervisor/stderr-log.d.ts +29 -0
- package/build/supervisor/stderr-log.d.ts.map +1 -0
- package/build/supervisor/stderr-log.js +52 -0
- package/build/supervisor/stderr-log.js.map +1 -0
- package/build/supervisor/stderr-log.test.d.ts +9 -0
- package/build/supervisor/stderr-log.test.d.ts.map +1 -0
- package/build/supervisor/stderr-log.test.js +80 -0
- package/build/supervisor/stderr-log.test.js.map +1 -0
- package/build/tools/issues-tools.d.ts.map +1 -1
- package/build/tools/issues-tools.js +29 -3
- package/build/tools/issues-tools.js.map +1 -1
- package/build/tools/issues-tools.test.js +86 -0
- package/build/tools/issues-tools.test.js.map +1 -1
- package/build/tools/replay-executor.d.ts +9 -0
- package/build/tools/replay-executor.d.ts.map +1 -1
- package/build/tools/replay-executor.js +15 -1
- package/build/tools/replay-executor.js.map +1 -1
- package/build/tools/replay-nested-rebase.test.d.ts +15 -0
- package/build/tools/replay-nested-rebase.test.d.ts.map +1 -0
- package/build/tools/replay-nested-rebase.test.js +139 -0
- package/build/tools/replay-nested-rebase.test.js.map +1 -0
- package/build/tools/replay-rebase.test.js +25 -0
- package/build/tools/replay-rebase.test.js.map +1 -1
- package/build/tools/replay-run-all-parity.test.d.ts +2 -0
- package/build/tools/replay-run-all-parity.test.d.ts.map +1 -0
- package/build/tools/replay-run-all-parity.test.js +90 -0
- package/build/tools/replay-run-all-parity.test.js.map +1 -0
- package/build/tools/replay-tools.d.ts +21 -21
- package/build/tools/replay-tools.d.ts.map +1 -1
- package/build/tools/replay-tools.js +17 -8
- package/build/tools/replay-tools.js.map +1 -1
- package/docs/instructions.md +3 -2
- package/docs/messages.md +3 -2
- package/docs/replay.md +17 -4
- package/package.json +1 -1
- package/plugin/skills/devharness/SKILL.md +1 -1
- package/plugin/skills/devharness/references/tool-categories.md +1 -0
|
@@ -115,8 +115,6 @@ declare const remoteSequenceSchema: z.ZodObject<{
|
|
|
115
115
|
}[];
|
|
116
116
|
name?: string | undefined;
|
|
117
117
|
startUrl?: string | undefined;
|
|
118
|
-
description?: string | undefined;
|
|
119
|
-
expectedOutcome?: string | undefined;
|
|
120
118
|
requiredConnections?: {
|
|
121
119
|
reference: string;
|
|
122
120
|
profile?: string | undefined;
|
|
@@ -124,6 +122,8 @@ declare const remoteSequenceSchema: z.ZodObject<{
|
|
|
124
122
|
forceNewInstance?: boolean | undefined;
|
|
125
123
|
role?: string | undefined;
|
|
126
124
|
}[] | undefined;
|
|
125
|
+
description?: string | undefined;
|
|
126
|
+
expectedOutcome?: string | undefined;
|
|
127
127
|
tags?: string[] | undefined;
|
|
128
128
|
requiredSockets?: string[] | undefined;
|
|
129
129
|
teardown?: {
|
|
@@ -141,8 +141,6 @@ declare const remoteSequenceSchema: z.ZodObject<{
|
|
|
141
141
|
}[];
|
|
142
142
|
name?: string | undefined;
|
|
143
143
|
startUrl?: string | undefined;
|
|
144
|
-
description?: string | undefined;
|
|
145
|
-
expectedOutcome?: string | undefined;
|
|
146
144
|
requiredConnections?: {
|
|
147
145
|
reference: string;
|
|
148
146
|
profile?: string | undefined;
|
|
@@ -150,6 +148,8 @@ declare const remoteSequenceSchema: z.ZodObject<{
|
|
|
150
148
|
forceNewInstance?: boolean | undefined;
|
|
151
149
|
role?: string | undefined;
|
|
152
150
|
}[] | undefined;
|
|
151
|
+
description?: string | undefined;
|
|
152
|
+
expectedOutcome?: string | undefined;
|
|
153
153
|
tags?: string[] | undefined;
|
|
154
154
|
requiredSockets?: string[] | undefined;
|
|
155
155
|
teardown?: {
|
package/build/mcp-supervisor.js
CHANGED
|
@@ -40,11 +40,43 @@ import { NdjsonReader } from './supervisor/ndjson-reader.js';
|
|
|
40
40
|
import { recordOwnSupervisor, removeOwnPidFile } from './supervisor/pidfile.js';
|
|
41
41
|
import { ClientWatcher } from './supervisor/client-watcher.js';
|
|
42
42
|
import { readSupervisorSessionConfig, idleCheckIntervalMs } from './supervisor/idle-config.js';
|
|
43
|
+
import { createStderrLog } from './supervisor/stderr-log.js';
|
|
43
44
|
import { runCli, isCliCommand, isVersionFlag, readPackageVersion, CLI_COMMANDS } from './cli/index.js';
|
|
44
45
|
const __filename = fileURLToPath(import.meta.url);
|
|
45
46
|
const __dirname = path.dirname(__filename);
|
|
47
|
+
// Set once main() has a shutdown to run. A write that fails on either host
|
|
48
|
+
// pipe means the host's end closed, which is the client being gone.
|
|
49
|
+
let onHostPipeBroken;
|
|
50
|
+
const stderrLog = createStderrLog('[mcp-supervisor]', process.stderr, () => {
|
|
51
|
+
if (onHostPipeBroken)
|
|
52
|
+
onHostPipeBroken();
|
|
53
|
+
});
|
|
54
|
+
// The host holds the read end of stdout. Its exit closes that end and the next
|
|
55
|
+
// frame write returns EPIPE, which without a listener reaches the
|
|
56
|
+
// uncaughtException handler - the same loop the stderr latch closes. This
|
|
57
|
+
// listener takes it off that path; the latch bounds the writes that follow.
|
|
58
|
+
let hostStdoutBroken = false;
|
|
59
|
+
process.stdout.on('error', () => {
|
|
60
|
+
if (hostStdoutBroken)
|
|
61
|
+
return;
|
|
62
|
+
hostStdoutBroken = true;
|
|
63
|
+
if (onHostPipeBroken)
|
|
64
|
+
onHostPipeBroken();
|
|
65
|
+
});
|
|
66
|
+
function writeToHostStdout(line) {
|
|
67
|
+
if (hostStdoutBroken)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
process.stdout.write(line.endsWith('\n') ? line : line + '\n');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
hostStdoutBroken = true;
|
|
74
|
+
if (onHostPipeBroken)
|
|
75
|
+
onHostPipeBroken();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
46
78
|
function logStderr(message) {
|
|
47
|
-
|
|
79
|
+
stderrLog.write(message);
|
|
48
80
|
}
|
|
49
81
|
async function main() {
|
|
50
82
|
// A CLI command runs here, in this process, and exits. Supervising a child
|
|
@@ -125,7 +157,7 @@ async function main() {
|
|
|
125
157
|
// call that runs longer than the idle threshold isn't suspended the
|
|
126
158
|
// moment it finally answers.
|
|
127
159
|
lastActivityAt = Date.now();
|
|
128
|
-
|
|
160
|
+
writeToHostStdout(line);
|
|
129
161
|
},
|
|
130
162
|
killChild: () => childManager.kill(),
|
|
131
163
|
suspendChild: () => childManager.suspend(),
|
|
@@ -238,7 +270,33 @@ async function main() {
|
|
|
238
270
|
// Claude Code exiting without sending a signal still closes its end of stdin.
|
|
239
271
|
process.stdin.on('end', () => void shutdown('host stdin ended'));
|
|
240
272
|
process.stdin.on('close', () => void shutdown('host stdin closed'));
|
|
273
|
+
// A closed host pipe - stderr or stdout - means the session that launched
|
|
274
|
+
// this supervisor is gone. Shutdown from here releases the child and its
|
|
275
|
+
// dev servers and removes the pidfile entry, in place of running on
|
|
276
|
+
// unattached: 12 such
|
|
277
|
+
// supervisors were found alive on one machine, the oldest 5 days 16 hours
|
|
278
|
+
// past its session's exit, each holding a pidfile slot and a child slot.
|
|
279
|
+
onHostPipeBroken = () => void shutdown('host pipe closed');
|
|
280
|
+
// Repeats of one exception are counted and capped. The stderr latch already
|
|
281
|
+
// bounds the EPIPE loop this handler used to feed, so a storm reaching this
|
|
282
|
+
// count originates elsewhere; the exit stops it holding a core either way.
|
|
283
|
+
// Same shape as the child's handler in index.ts (issue #74).
|
|
284
|
+
let lastUncaughtMessage = '';
|
|
285
|
+
let lastUncaughtAt = 0;
|
|
286
|
+
let repeatCount = 0;
|
|
241
287
|
process.on('uncaughtException', (error) => {
|
|
288
|
+
const now = Date.now();
|
|
289
|
+
const message = error?.message ?? String(error);
|
|
290
|
+
if (message === lastUncaughtMessage && now - lastUncaughtAt < 1000) {
|
|
291
|
+
if (++repeatCount > 50) {
|
|
292
|
+
logStderr('Same uncaught exception >50x in <1s, exiting to break the loop');
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
lastUncaughtMessage = message;
|
|
298
|
+
lastUncaughtAt = now;
|
|
299
|
+
repeatCount = 0;
|
|
242
300
|
logStderr(`Uncaught exception: ${error?.stack || error}`);
|
|
243
301
|
});
|
|
244
302
|
process.on('unhandledRejection', (reason) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-supervisor.js","sourceRoot":"","sources":["../src/mcp-supervisor.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEvG,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,SAAS,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"mcp-supervisor.js","sourceRoot":"","sources":["../src/mcp-supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,15 +5,24 @@ export interface ProcessInfo {
|
|
|
5
5
|
export interface ProcessProbe {
|
|
6
6
|
/** Parent pid + command for a pid, or null if the pid is gone/unreadable. */
|
|
7
7
|
info(pid: number): ProcessInfo | null;
|
|
8
|
-
/** Whether the pid still exists. */
|
|
9
|
-
isAlive(pid: number): boolean;
|
|
10
8
|
}
|
|
11
9
|
export interface ClientIdentity {
|
|
12
10
|
pid: number;
|
|
13
11
|
command: string;
|
|
14
12
|
}
|
|
13
|
+
export declare function parseProcessLine(line: string): ProcessInfo | null;
|
|
15
14
|
/** Reads process info via `ps`. Unavailable on Windows, which has no `ps`. */
|
|
16
15
|
export declare const systemProcessProbe: ProcessProbe;
|
|
16
|
+
/** Consecutive polls that must miss the client before the tree comes down. */
|
|
17
|
+
export declare const MISSES_BEFORE_SHUTDOWN = 3;
|
|
18
|
+
/**
|
|
19
|
+
* True while a fresh walk from `startPid` lands on the same client.
|
|
20
|
+
*
|
|
21
|
+
* The client's exit reparents the tree onto init, so the walk stops at ppid 1
|
|
22
|
+
* and returns null however the pid is reused afterwards. A different pid, or
|
|
23
|
+
* the same pid carrying a different command, is the same reading.
|
|
24
|
+
*/
|
|
25
|
+
export declare function clientStillPresent(startPid: number, client: ClientIdentity, probe: ProcessProbe): boolean;
|
|
17
26
|
/**
|
|
18
27
|
* Walk up from `startPid`'s parent and return the first ancestor that isn't
|
|
19
28
|
* launch plumbing, or null if there is none.
|
|
@@ -36,6 +45,8 @@ export declare class ClientWatcher {
|
|
|
36
45
|
private readonly pollIntervalMs;
|
|
37
46
|
private readonly logStderr;
|
|
38
47
|
private client;
|
|
48
|
+
/** Consecutive polls that have not found the client. */
|
|
49
|
+
private misses;
|
|
39
50
|
constructor(options?: ClientWatcherOptions);
|
|
40
51
|
getClient(): ClientIdentity | null;
|
|
41
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-watcher.d.ts","sourceRoot":"","sources":["../../src/supervisor/client-watcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client-watcher.d.ts","sourceRoot":"","sources":["../../src/supervisor/client-watcher.ts"],"names":[],"mappings":"AAiDA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAuED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIjE;AAED,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,EAAE,YAahC,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY,GAClB,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,QAAQ,SAAK,GACZ,cAAc,GAAG,IAAI,CAYvB;AAED,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;GAGG;AACH,qBAAa,aAAa;IASZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,MAAM,CAA+B;IAC7C,wDAAwD;IACxD,OAAO,CAAC,MAAM,CAAK;gBAEU,OAAO,GAAE,oBAAyB;IAM/D,SAAS,IAAI,cAAc,GAAG,IAAI;IAIlC;;;OAGG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,cAAc,GAAG,IAAI;IAmC9F,IAAI,IAAI,IAAI;CAMb"}
|
|
@@ -26,6 +26,24 @@
|
|
|
26
26
|
* If the walk finds nothing but plumbing all the way to pid 1, there is no
|
|
27
27
|
* client to watch and reaping is disabled - better to leak than to kill a tree
|
|
28
28
|
* that is still serving someone.
|
|
29
|
+
*
|
|
30
|
+
* IDENTIFYING THE CLIENT ACROSS DAYS
|
|
31
|
+
* A pid alone does not identify a process for the length of a session. The
|
|
32
|
+
* client exits, the OS recycles its pid onto an unrelated process, and a
|
|
33
|
+
* liveness check on that number reports alive forever. Twelve supervisors were
|
|
34
|
+
* found in exactly that state, the oldest 5 days 16 hours past its session,
|
|
35
|
+
* each consuming CPU linear in its age at about 1.4 ms per 60-second poll -
|
|
36
|
+
* that poll and nothing else.
|
|
37
|
+
*
|
|
38
|
+
* So each poll re-walks the ancestry instead of testing a number. The client's
|
|
39
|
+
* death reparents everything below it onto init, so the walk hits ppid 1 and
|
|
40
|
+
* yields null - a reading that holds however the pid is later reused. A walk
|
|
41
|
+
* that lands on a different pid, or the same pid running a different command,
|
|
42
|
+
* reads as gone for the same reason.
|
|
43
|
+
*
|
|
44
|
+
* `ps` failing is indistinguishable from an exit in a single reading, so the
|
|
45
|
+
* tree comes down on the third consecutive miss. A transient probe failure
|
|
46
|
+
* costs two poll intervals; a real exit costs the same delay.
|
|
29
47
|
*/
|
|
30
48
|
import { execFileSync } from 'child_process';
|
|
31
49
|
/**
|
|
@@ -81,6 +99,22 @@ function isPlumbing(command) {
|
|
|
81
99
|
}
|
|
82
100
|
return false;
|
|
83
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Parses one `ps -o ppid=,command=` line: leading spaces, the numeric ppid,
|
|
104
|
+
* then the command as the rest of the line.
|
|
105
|
+
*
|
|
106
|
+
* `ps` prints start times in a locale-shaped form - this machine gives
|
|
107
|
+
* `Sat 5 Sep 11:04:52 2026`, where another gives `Sat Sep 5 11:04:52 2026` -
|
|
108
|
+
* so no start-time column is requested. A mis-parsed date would land inside
|
|
109
|
+
* the command string and defeat the plumbing check that finds the client.
|
|
110
|
+
*/
|
|
111
|
+
const PS_LINE = /^\s*(\d+)\s+(.*)$/;
|
|
112
|
+
export function parseProcessLine(line) {
|
|
113
|
+
const match = line.match(PS_LINE);
|
|
114
|
+
if (!match)
|
|
115
|
+
return null;
|
|
116
|
+
return { ppid: Number(match[1]), command: match[2] };
|
|
117
|
+
}
|
|
84
118
|
/** Reads process info via `ps`. Unavailable on Windows, which has no `ps`. */
|
|
85
119
|
export const systemProcessProbe = {
|
|
86
120
|
info(pid) {
|
|
@@ -91,26 +125,28 @@ export const systemProcessProbe = {
|
|
|
91
125
|
}).trim();
|
|
92
126
|
if (!out)
|
|
93
127
|
return null;
|
|
94
|
-
|
|
95
|
-
if (!match)
|
|
96
|
-
return null;
|
|
97
|
-
return { ppid: Number(match[1]), command: match[2] };
|
|
128
|
+
return parseProcessLine(out);
|
|
98
129
|
}
|
|
99
130
|
catch {
|
|
100
131
|
return null;
|
|
101
132
|
}
|
|
102
133
|
},
|
|
103
|
-
isAlive(pid) {
|
|
104
|
-
try {
|
|
105
|
-
process.kill(pid, 0);
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
catch (err) {
|
|
109
|
-
// EPERM means it exists but belongs to another user - still alive.
|
|
110
|
-
return err?.code === 'EPERM';
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
134
|
};
|
|
135
|
+
/** Consecutive polls that must miss the client before the tree comes down. */
|
|
136
|
+
export const MISSES_BEFORE_SHUTDOWN = 3;
|
|
137
|
+
/**
|
|
138
|
+
* True while a fresh walk from `startPid` lands on the same client.
|
|
139
|
+
*
|
|
140
|
+
* The client's exit reparents the tree onto init, so the walk stops at ppid 1
|
|
141
|
+
* and returns null however the pid is reused afterwards. A different pid, or
|
|
142
|
+
* the same pid carrying a different command, is the same reading.
|
|
143
|
+
*/
|
|
144
|
+
export function clientStillPresent(startPid, client, probe) {
|
|
145
|
+
const current = resolveClientIdentity(startPid, probe);
|
|
146
|
+
if (!current)
|
|
147
|
+
return false;
|
|
148
|
+
return current.pid === client.pid && current.command === client.command;
|
|
149
|
+
}
|
|
114
150
|
/**
|
|
115
151
|
* Walk up from `startPid`'s parent and return the first ancestor that isn't
|
|
116
152
|
* launch plumbing, or null if there is none.
|
|
@@ -126,7 +162,7 @@ export function resolveClientIdentity(startPid, probe, maxDepth = 12) {
|
|
|
126
162
|
if (!isPlumbing(parent.command)) {
|
|
127
163
|
return { pid: current.ppid, command: parent.command };
|
|
128
164
|
}
|
|
129
|
-
current =
|
|
165
|
+
current = parent;
|
|
130
166
|
}
|
|
131
167
|
return null;
|
|
132
168
|
}
|
|
@@ -141,6 +177,8 @@ export class ClientWatcher {
|
|
|
141
177
|
pollIntervalMs;
|
|
142
178
|
logStderr;
|
|
143
179
|
client = null;
|
|
180
|
+
/** Consecutive polls that have not found the client. */
|
|
181
|
+
misses = 0;
|
|
144
182
|
constructor(options = {}) {
|
|
145
183
|
this.options = options;
|
|
146
184
|
this.probe = options.probe ?? systemProcessProbe;
|
|
@@ -167,8 +205,14 @@ export class ClientWatcher {
|
|
|
167
205
|
const client = this.client;
|
|
168
206
|
this.logStderr(`Watching client PID ${client.pid} (${client.command.slice(0, 80)})`);
|
|
169
207
|
this.timer = setInterval(() => {
|
|
170
|
-
if (this.probe
|
|
208
|
+
if (clientStillPresent(startPid, client, this.probe)) {
|
|
209
|
+
this.misses = 0;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (++this.misses < MISSES_BEFORE_SHUTDOWN) {
|
|
213
|
+
this.logStderr(`Client PID ${client.pid} not found (${this.misses}/${MISSES_BEFORE_SHUTDOWN})`);
|
|
171
214
|
return;
|
|
215
|
+
}
|
|
172
216
|
this.stop();
|
|
173
217
|
this.logStderr(`Client PID ${client.pid} is gone; shutting down`);
|
|
174
218
|
onClientGone(client);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-watcher.js","sourceRoot":"","sources":["../../src/supervisor/client-watcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"client-watcher.js","sourceRoot":"","sources":["../../src/supervisor/client-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { ClientWatcher, resolveClientIdentity } from './client-watcher.js';
|
|
2
|
+
import { ClientWatcher, clientStillPresent, MISSES_BEFORE_SHUTDOWN, parseProcessLine, resolveClientIdentity, } from './client-watcher.js';
|
|
3
3
|
/** Builds a probe over a fake process table: pid -> { ppid, command }. */
|
|
4
4
|
function makeProbe(table, dead = new Set()) {
|
|
5
5
|
return {
|
|
6
6
|
info: (pid) => (dead.has(pid) ? null : table[pid] ?? null),
|
|
7
|
-
isAlive: (pid) => !dead.has(pid) && pid in table,
|
|
8
7
|
};
|
|
9
8
|
}
|
|
10
9
|
describe('resolveClientIdentity', () => {
|
|
@@ -93,7 +92,7 @@ describe('ClientWatcher', () => {
|
|
|
93
92
|
vi.advanceTimersByTime(3000);
|
|
94
93
|
expect(onGone).not.toHaveBeenCalled();
|
|
95
94
|
dead.add(300);
|
|
96
|
-
vi.advanceTimersByTime(1000);
|
|
95
|
+
vi.advanceTimersByTime(1000 * MISSES_BEFORE_SHUTDOWN);
|
|
97
96
|
expect(onGone).toHaveBeenCalledTimes(1);
|
|
98
97
|
expect(onGone).toHaveBeenCalledWith({ pid: 300, command: 'claude' });
|
|
99
98
|
// Stops polling after firing - one shutdown is enough.
|
|
@@ -118,4 +117,112 @@ describe('ClientWatcher', () => {
|
|
|
118
117
|
expect(onGone).not.toHaveBeenCalled();
|
|
119
118
|
});
|
|
120
119
|
});
|
|
120
|
+
/**
|
|
121
|
+
* Twelve supervisors were found alive with their sessions days gone, each
|
|
122
|
+
* burning CPU linear in its age at about 1.4 ms per 60-second poll - that poll
|
|
123
|
+
* and nothing else. A pid-only liveness check on a recycled pid reads alive
|
|
124
|
+
* forever, so the reaper never fired.
|
|
125
|
+
*/
|
|
126
|
+
describe('clientStillPresent', () => {
|
|
127
|
+
const TREE = {
|
|
128
|
+
100: { ppid: 200, command: 'node .bin/devharness' },
|
|
129
|
+
200: { ppid: 300, command: 'npm exec devharness@0.9.14' },
|
|
130
|
+
300: { ppid: 1, command: 'claude' },
|
|
131
|
+
};
|
|
132
|
+
const CLIENT = { pid: 300, command: 'claude' };
|
|
133
|
+
it('holds while the whole ancestry is intact', () => {
|
|
134
|
+
expect(clientStillPresent(100, CLIENT, makeProbe(TREE))).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
it('fails once the client exits and the wrapper reparents onto init', () => {
|
|
137
|
+
// What `npm exec` surviving its client actually looks like: the wrapper
|
|
138
|
+
// lives on with ppid 1, so the walk stops there instead of finding a client.
|
|
139
|
+
const orphaned = {
|
|
140
|
+
100: { ppid: 200, command: 'node .bin/devharness' },
|
|
141
|
+
200: { ppid: 1, command: 'npm exec devharness@0.9.14' },
|
|
142
|
+
};
|
|
143
|
+
expect(clientStillPresent(100, CLIENT, makeProbe(orphaned))).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
it('fails when the client pid was recycled onto another process', () => {
|
|
146
|
+
// The pid is alive and would pass a kill(pid, 0) check; the ancestry no
|
|
147
|
+
// longer runs through it, which is what the twelve orphans missed.
|
|
148
|
+
const recycled = {
|
|
149
|
+
100: { ppid: 200, command: 'node .bin/devharness' },
|
|
150
|
+
200: { ppid: 1, command: 'npm exec devharness@0.9.14' },
|
|
151
|
+
300: { ppid: 1, command: '/usr/sbin/cupsd' },
|
|
152
|
+
};
|
|
153
|
+
expect(clientStillPresent(100, CLIENT, makeProbe(recycled))).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
it('fails when the walk lands on a different pid', () => {
|
|
156
|
+
const moved = {
|
|
157
|
+
100: { ppid: 200, command: 'node .bin/devharness' },
|
|
158
|
+
200: { ppid: 999, command: 'npm exec devharness@0.9.14' },
|
|
159
|
+
999: { ppid: 1, command: 'claude' },
|
|
160
|
+
};
|
|
161
|
+
expect(clientStillPresent(100, CLIENT, makeProbe(moved))).toBe(false);
|
|
162
|
+
});
|
|
163
|
+
it('fails when the pid carries a different command', () => {
|
|
164
|
+
const swapped = {
|
|
165
|
+
...TREE,
|
|
166
|
+
300: { ppid: 1, command: 'code helper' },
|
|
167
|
+
};
|
|
168
|
+
expect(clientStillPresent(100, CLIENT, makeProbe(swapped))).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('ClientWatcher miss tolerance', () => {
|
|
172
|
+
beforeEach(() => vi.useFakeTimers());
|
|
173
|
+
afterEach(() => vi.useRealTimers());
|
|
174
|
+
const TREE = {
|
|
175
|
+
100: { ppid: 200, command: 'node .bin/devharness' },
|
|
176
|
+
200: { ppid: 300, command: 'npm exec devharness@0.9.14' },
|
|
177
|
+
300: { ppid: 1, command: 'claude' },
|
|
178
|
+
};
|
|
179
|
+
it('waits for three consecutive misses before shutting the tree down', () => {
|
|
180
|
+
const dead = new Set();
|
|
181
|
+
const watcher = new ClientWatcher({ pollIntervalMs: 1000, probe: makeProbe(TREE, dead) });
|
|
182
|
+
const onGone = vi.fn();
|
|
183
|
+
watcher.start(100, onGone);
|
|
184
|
+
dead.add(300);
|
|
185
|
+
for (let poll = 1; poll < MISSES_BEFORE_SHUTDOWN; poll++) {
|
|
186
|
+
vi.advanceTimersByTime(1000);
|
|
187
|
+
expect(onGone).not.toHaveBeenCalled();
|
|
188
|
+
}
|
|
189
|
+
vi.advanceTimersByTime(1000);
|
|
190
|
+
expect(onGone).toHaveBeenCalledTimes(1);
|
|
191
|
+
});
|
|
192
|
+
it('forgets earlier misses once the client is found again', () => {
|
|
193
|
+
// A `ps` that times out reads exactly like an exit. Without the reset, two
|
|
194
|
+
// unrelated timeouts days apart would add up to a shutdown.
|
|
195
|
+
const dead = new Set();
|
|
196
|
+
const watcher = new ClientWatcher({ pollIntervalMs: 1000, probe: makeProbe(TREE, dead) });
|
|
197
|
+
const onGone = vi.fn();
|
|
198
|
+
watcher.start(100, onGone);
|
|
199
|
+
dead.add(300);
|
|
200
|
+
vi.advanceTimersByTime(2000);
|
|
201
|
+
dead.delete(300);
|
|
202
|
+
vi.advanceTimersByTime(1000);
|
|
203
|
+
dead.add(300);
|
|
204
|
+
vi.advanceTimersByTime(2000);
|
|
205
|
+
expect(onGone).not.toHaveBeenCalled();
|
|
206
|
+
vi.advanceTimersByTime(1000);
|
|
207
|
+
expect(onGone).toHaveBeenCalledTimes(1);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
describe('parseProcessLine', () => {
|
|
211
|
+
it('reads ppid and command from a ps line', () => {
|
|
212
|
+
expect(parseProcessLine(' 40544 node /opt/homebrew/bin/devharness')).toEqual({
|
|
213
|
+
ppid: 40544,
|
|
214
|
+
command: 'node /opt/homebrew/bin/devharness',
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
it('keeps the whole command including its arguments', () => {
|
|
218
|
+
expect(parseProcessLine('81785 claude --resume d100b5ed-ecf8')).toEqual({
|
|
219
|
+
ppid: 81785,
|
|
220
|
+
command: 'claude --resume d100b5ed-ecf8',
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
it('returns null for a line carrying no pid', () => {
|
|
224
|
+
expect(parseProcessLine('')).toBeNull();
|
|
225
|
+
expect(parseProcessLine('no numbers here')).toBeNull();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
121
228
|
//# sourceMappingURL=client-watcher.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-watcher.test.js","sourceRoot":"","sources":["../../src/supervisor/client-watcher.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client-watcher.test.js","sourceRoot":"","sources":["../../src/supervisor/client-watcher.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guarded stderr writer for the supervisor.
|
|
3
|
+
*
|
|
4
|
+
* The supervisor's stderr is a pipe held by the Claude Code host. The host
|
|
5
|
+
* exits and closes its end; the supervisor's next write to fd 2 returns
|
|
6
|
+
* errno 32, EPIPE. Node delivers that as an `error` event on the stream, and a
|
|
7
|
+
* stream with no `error` listener raises it as an `uncaughtException`. The
|
|
8
|
+
* supervisor's `uncaughtException` handler logs the exception, which writes to
|
|
9
|
+
* the same closed pipe, which raises the same EPIPE: a write loop with no pause
|
|
10
|
+
* that holds a core until the process is killed. Two such supervisors were
|
|
11
|
+
* measured at about 89,000 write calls a second each, every call returning
|
|
12
|
+
* errno 32, five days after their sessions ended.
|
|
13
|
+
*
|
|
14
|
+
* Two guards break that chain. An `error` listener on the stream takes the
|
|
15
|
+
* EPIPE off the `uncaughtException` path, so a failed write raises nothing. A
|
|
16
|
+
* `broken` latch turns every later write into a no-op, so the count of writes
|
|
17
|
+
* to a closed pipe is bounded at one.
|
|
18
|
+
*
|
|
19
|
+
* `isBroken()` reports the latch. A closed host pipe means the host is gone,
|
|
20
|
+
* which is the supervisor's signal to shut down rather than run on unattached.
|
|
21
|
+
*/
|
|
22
|
+
export interface StderrLog {
|
|
23
|
+
/** Writes one prefixed line. A latched-broken stream consumes nothing. */
|
|
24
|
+
write(message: string): void;
|
|
25
|
+
/** True once a write to the stream has failed. */
|
|
26
|
+
isBroken(): boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function createStderrLog(prefix: string, stream?: NodeJS.WriteStream | NodeJS.WritableStream, onBroken?: () => void): StderrLog;
|
|
29
|
+
//# sourceMappingURL=stderr-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stderr-log.d.ts","sourceRoot":"","sources":["../../src/supervisor/stderr-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,SAAS;IACxB,0EAA0E;IAC1E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kDAAkD;IAClD,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,cAA+B,EACnE,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,SAAS,CA4BX"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guarded stderr writer for the supervisor.
|
|
3
|
+
*
|
|
4
|
+
* The supervisor's stderr is a pipe held by the Claude Code host. The host
|
|
5
|
+
* exits and closes its end; the supervisor's next write to fd 2 returns
|
|
6
|
+
* errno 32, EPIPE. Node delivers that as an `error` event on the stream, and a
|
|
7
|
+
* stream with no `error` listener raises it as an `uncaughtException`. The
|
|
8
|
+
* supervisor's `uncaughtException` handler logs the exception, which writes to
|
|
9
|
+
* the same closed pipe, which raises the same EPIPE: a write loop with no pause
|
|
10
|
+
* that holds a core until the process is killed. Two such supervisors were
|
|
11
|
+
* measured at about 89,000 write calls a second each, every call returning
|
|
12
|
+
* errno 32, five days after their sessions ended.
|
|
13
|
+
*
|
|
14
|
+
* Two guards break that chain. An `error` listener on the stream takes the
|
|
15
|
+
* EPIPE off the `uncaughtException` path, so a failed write raises nothing. A
|
|
16
|
+
* `broken` latch turns every later write into a no-op, so the count of writes
|
|
17
|
+
* to a closed pipe is bounded at one.
|
|
18
|
+
*
|
|
19
|
+
* `isBroken()` reports the latch. A closed host pipe means the host is gone,
|
|
20
|
+
* which is the supervisor's signal to shut down rather than run on unattached.
|
|
21
|
+
*/
|
|
22
|
+
export function createStderrLog(prefix, stream = process.stderr, onBroken) {
|
|
23
|
+
let broken = false;
|
|
24
|
+
const latch = () => {
|
|
25
|
+
if (broken)
|
|
26
|
+
return;
|
|
27
|
+
broken = true;
|
|
28
|
+
if (onBroken)
|
|
29
|
+
onBroken();
|
|
30
|
+
};
|
|
31
|
+
// Attached once, for the lifetime of the process: an EPIPE that arrives
|
|
32
|
+
// asynchronously lands here instead of on the uncaughtException path.
|
|
33
|
+
stream.on('error', latch);
|
|
34
|
+
return {
|
|
35
|
+
write(message) {
|
|
36
|
+
if (broken)
|
|
37
|
+
return;
|
|
38
|
+
try {
|
|
39
|
+
stream.write(`${prefix} ${message}\n`);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// A synchronous throw covers the case where the write fails inline
|
|
43
|
+
// rather than through the stream's error event.
|
|
44
|
+
latch();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
isBroken() {
|
|
48
|
+
return broken;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=stderr-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stderr-log.js","sourceRoot":"","sources":["../../src/supervisor/stderr-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,SAAqD,OAAO,CAAC,MAAM,EACnE,QAAqB;IAErB,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,IAAI,QAAQ;YAAE,QAAQ,EAAE,CAAC;IAC3B,CAAC,CAAC;IAEF,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE1B,OAAO;QACL,KAAK,CAAC,OAAe;YACnB,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,IAAI,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;gBACnE,gDAAgD;gBAChD,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,QAAQ;YACN,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observed for real: two supervisors from sessions that had ended days earlier
|
|
3
|
+
* were each issuing about 89,000 write calls a second to fd 2, every call
|
|
4
|
+
* returning errno 32 (EPIPE), together accounting for 96.8% of the machine's
|
|
5
|
+
* filesystem syscalls. The loop is the supervisor's uncaughtException handler
|
|
6
|
+
* logging to the closed host pipe, which raises the next uncaughtException.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=stderr-log.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stderr-log.test.d.ts","sourceRoot":"","sources":["../../src/supervisor/stderr-log.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|