@detergent-software/conductor 3.4.0 → 3.5.0-dev.10
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/CHANGELOG.md +95 -0
- package/README.md +16 -8
- package/build/brief.js +9 -2
- package/build/brief.js.map +1 -1
- package/build/broker.js +9 -3
- package/build/broker.js.map +1 -1
- package/build/cli.js +5 -0
- package/build/cli.js.map +1 -1
- package/build/config.js +12 -0
- package/build/config.js.map +1 -1
- package/build/credentials.js +4 -0
- package/build/credentials.js.map +1 -1
- package/build/daemon.js +6 -1
- package/build/daemon.js.map +1 -1
- package/build/help.js +22 -2
- package/build/help.js.map +1 -1
- package/build/host/browser.js +163 -0
- package/build/host/browser.js.map +1 -0
- package/build/host/worktree-processes.js +389 -0
- package/build/host/worktree-processes.js.map +1 -0
- package/build/inbox.js +35 -4
- package/build/inbox.js.map +1 -1
- package/build/manager.js +181 -27
- package/build/manager.js.map +1 -1
- package/build/mcp-approval.js +94 -0
- package/build/mcp-approval.js.map +1 -0
- package/build/notes.js +22 -5
- package/build/notes.js.map +1 -1
- package/build/project-check.js +38 -3
- package/build/project-check.js.map +1 -1
- package/build/scheduler.js +25 -6
- package/build/scheduler.js.map +1 -1
- package/build/spend.js +36 -14
- package/build/spend.js.map +1 -1
- package/build/watchers/boards.js +3 -2
- package/build/watchers/boards.js.map +1 -1
- package/build/watchers/index.js +10 -2
- package/build/watchers/index.js.map +1 -1
- package/build/watchers/issues.js +5 -2
- package/build/watchers/issues.js.map +1 -1
- package/build/watchers/linear-queue.js +11 -4
- package/build/watchers/linear-queue.js.map +1 -1
- package/build/watchers/linear.js +55 -17
- package/build/watchers/linear.js.map +1 -1
- package/build/watchers/source.js +27 -3
- package/build/watchers/source.js.map +1 -1
- package/build/worktrees.js +30 -20
- package/build/worktrees.js.map +1 -1
- package/package.json +3 -3
- package/plugin/hooks/model.ts +30 -3
- package/plugin/hooks/register.tsx +98 -13
- package/plugin/skills/conductor-console/SKILL.md +1 -1
- package/plugin/skills/work-item/SKILL.md +4 -3
- package/protocol/PROTOCOL.md +1 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, readlinkSync } from 'node:fs';
|
|
2
|
+
import { posix, win32 } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { ConductorError } from "../errors.js";
|
|
5
|
+
import { processAlive } from "../lock.js";
|
|
6
|
+
import { realOr } from "../paths.js";
|
|
7
|
+
import { outputOf, run as runCommand } from "../run.js";
|
|
8
|
+
import { hostPlatform } from "./platform.js";
|
|
9
|
+
// The programs that run a script file: the first absolute path among their words that aren't options
|
|
10
|
+
// is the script. Not shells, whose options take folders (`pwsh -WorkingDirectory <dir>`, `bash
|
|
11
|
+
// --rcfile <file>`): a terminal opened in the worktree is the operator's.
|
|
12
|
+
const INTERPRETERS = new Set([
|
|
13
|
+
'bun',
|
|
14
|
+
'deno',
|
|
15
|
+
'node',
|
|
16
|
+
'nodejs',
|
|
17
|
+
'perl',
|
|
18
|
+
'php',
|
|
19
|
+
'python',
|
|
20
|
+
'python3',
|
|
21
|
+
'ruby',
|
|
22
|
+
]);
|
|
23
|
+
// How long a POSIX process gets after SIGTERM before SIGKILL.
|
|
24
|
+
const TERM_MS = 5000;
|
|
25
|
+
// The processes of the listing that belong to the worktree (worktreeProcesses' find), parents first.
|
|
26
|
+
export function belonging(listing, worktree, ports, self, platform) {
|
|
27
|
+
const byPid = new Map(listing.processes.map((p) => [p.pid, p]));
|
|
28
|
+
// The conductor and every process it descends from (a terminal, a supervisor): never stopped, and
|
|
29
|
+
// never looked through for children.
|
|
30
|
+
const guarded = new Set();
|
|
31
|
+
for (let pid = self; pid !== undefined && !guarded.has(pid);) {
|
|
32
|
+
guarded.add(pid);
|
|
33
|
+
const entry = byPid.get(pid);
|
|
34
|
+
if (entry === undefined || entry.ppid === pid)
|
|
35
|
+
break;
|
|
36
|
+
const parent = byPid.get(entry.ppid);
|
|
37
|
+
// A parent that started after its child is a reused pid's process (Windows), not its parent: the
|
|
38
|
+
// walk stops there, or it would guard a process of the worktree.
|
|
39
|
+
const reused = parent !== undefined && parent.started !== null && entry.started !== null && parent.started > entry.started;
|
|
40
|
+
pid = reused ? undefined : entry.ppid;
|
|
41
|
+
}
|
|
42
|
+
const roots = worktreeRoots(worktree, platform);
|
|
43
|
+
const found = new Map();
|
|
44
|
+
const add = (entry, why) => {
|
|
45
|
+
if (!guarded.has(entry.pid) && !found.has(entry.pid))
|
|
46
|
+
found.set(entry.pid, { command: entry.command, pid: entry.pid, why });
|
|
47
|
+
};
|
|
48
|
+
for (const entry of listing.processes)
|
|
49
|
+
if (programPaths(entry, platform).some((path) => roots.some((root) => isUnder(path, root, platform))))
|
|
50
|
+
add(entry, 'path');
|
|
51
|
+
for (const port of ports)
|
|
52
|
+
for (const pid of listing.listeners.get(port) ?? []) {
|
|
53
|
+
const entry = byPid.get(pid);
|
|
54
|
+
add(entry ?? { command: '', executable: null, pid, ppid: 0, started: null }, 'port');
|
|
55
|
+
}
|
|
56
|
+
// Each one's descendants, as each is stopped with its tree.
|
|
57
|
+
const children = new Map();
|
|
58
|
+
for (const entry of listing.processes) {
|
|
59
|
+
if (entry.ppid === entry.pid)
|
|
60
|
+
continue;
|
|
61
|
+
children.set(entry.ppid, [...(children.get(entry.ppid) ?? []), entry]);
|
|
62
|
+
}
|
|
63
|
+
const queue = [...found.keys()];
|
|
64
|
+
for (let pid = queue.shift(); pid !== undefined; pid = queue.shift()) {
|
|
65
|
+
const parent = byPid.get(pid);
|
|
66
|
+
// A listener the process listing missed (it started between the two): with no start to compare,
|
|
67
|
+
// a child of its pid could be a reused pid's.
|
|
68
|
+
if (!parent)
|
|
69
|
+
continue;
|
|
70
|
+
for (const child of children.get(pid) ?? []) {
|
|
71
|
+
if (guarded.has(child.pid) || found.has(child.pid))
|
|
72
|
+
continue;
|
|
73
|
+
// A pid Windows reused: the "child" started before its parent did.
|
|
74
|
+
if (parent.started !== null && child.started !== null && child.started < parent.started)
|
|
75
|
+
continue;
|
|
76
|
+
add(child, 'child');
|
|
77
|
+
queue.push(child.pid);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [...found.values()];
|
|
81
|
+
}
|
|
82
|
+
// The command that ends a process by hand, for an inbox item: one that outlived the conductor's own
|
|
83
|
+
// stop, so forcibly, and that process alone, as the item names each one (taskkill /T would walk
|
|
84
|
+
// parent pids Windows may have reused).
|
|
85
|
+
export function killCommand(pid, platform = hostPlatform()) {
|
|
86
|
+
return platform === 'win32' ? `taskkill /PID ${pid} /F` : `kill -9 ${pid}`;
|
|
87
|
+
}
|
|
88
|
+
// `lsof -F pn` output: a `p<pid>` line, then one `n<name>` line per file (other field lines, such as
|
|
89
|
+
// `f<fd>`, are skipped). Listening sockets are named `*:41000`, `127.0.0.1:41000` or `[::1]:41000`.
|
|
90
|
+
export function parseLsofListeners(stdout, ports) {
|
|
91
|
+
const listeners = new Map();
|
|
92
|
+
let pid = null;
|
|
93
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
94
|
+
if (line.startsWith('p'))
|
|
95
|
+
pid = Number(line.slice(1)) || null;
|
|
96
|
+
else if (line.startsWith('n') && pid !== null)
|
|
97
|
+
addListener(listeners, ports, portOf(line.slice(1)), pid);
|
|
98
|
+
}
|
|
99
|
+
return listeners;
|
|
100
|
+
}
|
|
101
|
+
// `ps -A -ww -o pid=,ppid=,args=` output.
|
|
102
|
+
export function parsePs(stdout) {
|
|
103
|
+
const entries = [];
|
|
104
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
105
|
+
const match = /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line);
|
|
106
|
+
if (!match)
|
|
107
|
+
continue;
|
|
108
|
+
entries.push({
|
|
109
|
+
command: match[3] ?? '',
|
|
110
|
+
executable: null,
|
|
111
|
+
pid: Number(match[1]),
|
|
112
|
+
ppid: Number(match[2]),
|
|
113
|
+
started: null,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return entries;
|
|
117
|
+
}
|
|
118
|
+
// `ss -ltnpH` output: `LISTEN 0 511 *:41000 *:* users:(("node",pid=1234,fd=20))`. The local address
|
|
119
|
+
// is the fourth column.
|
|
120
|
+
export function parseSs(stdout, ports) {
|
|
121
|
+
const listeners = new Map();
|
|
122
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
123
|
+
const local = line.trim().split(/\s+/)[3];
|
|
124
|
+
if (local === undefined)
|
|
125
|
+
continue;
|
|
126
|
+
for (const match of line.matchAll(/pid=(\d+)/g))
|
|
127
|
+
addListener(listeners, ports, portOf(local), Number(match[1]));
|
|
128
|
+
}
|
|
129
|
+
return listeners;
|
|
130
|
+
}
|
|
131
|
+
// The Windows script's JSON (windowsListingScript).
|
|
132
|
+
export function parseWindowsListing(stdout, ports) {
|
|
133
|
+
const parsed = windowsListing.safeParse(parseJson(stdout));
|
|
134
|
+
if (!parsed.success)
|
|
135
|
+
throw new ConductorError("couldn't read the process listing", [stdout.slice(0, 500)]);
|
|
136
|
+
const listeners = new Map();
|
|
137
|
+
for (const l of parsed.data.listeners)
|
|
138
|
+
addListener(listeners, ports, l.port, l.pid);
|
|
139
|
+
return {
|
|
140
|
+
listeners,
|
|
141
|
+
processes: parsed.data.processes.map((p) => ({
|
|
142
|
+
command: p.c ?? '',
|
|
143
|
+
executable: p.e ?? null,
|
|
144
|
+
pid: p.p,
|
|
145
|
+
ppid: p.pp,
|
|
146
|
+
started: p.s ?? null,
|
|
147
|
+
})),
|
|
148
|
+
unseen: parsed.data.gap === null || parsed.data.gap === undefined ? [] : [parsed.data.gap],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// Processes as a retire step or an inbox item names them: `8640 node …\next dev; 912 …`.
|
|
152
|
+
export function processesText(processes) {
|
|
153
|
+
return processes
|
|
154
|
+
.map(({ command, pid }) => {
|
|
155
|
+
const text = command.replace(/\s+/g, ' ').trim();
|
|
156
|
+
return text === '' ? String(pid) : `${pid} ${text.length > 160 ? `${text.slice(0, 159)}…` : text}`;
|
|
157
|
+
})
|
|
158
|
+
.join('; ');
|
|
159
|
+
}
|
|
160
|
+
// One Windows PowerShell run, encoded so its own command line never holds the worktree's path: every
|
|
161
|
+
// process with its parent, executable, command line and start, and the owners of the given ports
|
|
162
|
+
// listening. Get-NetTCPConnection answers an error for a port nobody listens on, hence
|
|
163
|
+
// SilentlyContinue; a Windows without it says so in `gap`.
|
|
164
|
+
export function windowsListingScript(ports) {
|
|
165
|
+
return [
|
|
166
|
+
'[Console]::OutputEncoding = [Text.Encoding]::UTF8',
|
|
167
|
+
`$ports = @(${ports.map((p) => String(Math.trunc(p))).join(',')})`,
|
|
168
|
+
'$procs = @(Get-CimInstance Win32_Process | ForEach-Object { [pscustomobject]@{ p = [int]$_.ProcessId; pp = [int]$_.ParentProcessId; e = $_.ExecutablePath; c = $_.CommandLine; s = $(if ($_.CreationDate) { ([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds() } else { $null }) } })',
|
|
169
|
+
'$gap = $null',
|
|
170
|
+
'$listen = @()',
|
|
171
|
+
"if ($ports.Count -gt 0) { if (Get-Command Get-NetTCPConnection -ErrorAction SilentlyContinue) { $listen = @(Get-NetTCPConnection -State Listen -LocalPort $ports -ErrorAction SilentlyContinue | ForEach-Object { [pscustomobject]@{ port = [int]$_.LocalPort; pid = [int]$_.OwningProcess } }) } else { $gap = 'listening ports: no Get-NetTCPConnection' } }",
|
|
172
|
+
'[pscustomobject]@{ processes = $procs; listeners = $listen; gap = $gap } | ConvertTo-Json -Compress -Depth 3',
|
|
173
|
+
].join('\n');
|
|
174
|
+
}
|
|
175
|
+
export function worktreeProcesses(host = {}) {
|
|
176
|
+
const platform = host.platform ?? hostPlatform();
|
|
177
|
+
const run = host.run ?? runCommand;
|
|
178
|
+
const self = host.self ?? process.pid;
|
|
179
|
+
const kill = host.kill ?? ((pid, signal) => process.kill(pid, signal));
|
|
180
|
+
const proc = host.proc ?? realProc;
|
|
181
|
+
// A zombie answers kill(pid, 0) until its parent reaps it, but it has ended: Linux says so in /proc.
|
|
182
|
+
const alive = host.alive ??
|
|
183
|
+
(platform === 'linux'
|
|
184
|
+
? (pid) => processAlive(pid) && !isZombie(proc.read(posix.join('/proc', String(pid), 'stat')))
|
|
185
|
+
: processAlive);
|
|
186
|
+
const sleep = host.sleep ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
|
|
187
|
+
return {
|
|
188
|
+
find: async (worktree, ports) => {
|
|
189
|
+
const listing = await listProcesses(platform, ports, run, proc);
|
|
190
|
+
return { processes: belonging(listing, worktree, ports, self, platform), unseen: listing.unseen };
|
|
191
|
+
},
|
|
192
|
+
stop: async (pids) => {
|
|
193
|
+
const send = (signal, to) => {
|
|
194
|
+
for (const pid of to) {
|
|
195
|
+
try {
|
|
196
|
+
kill(pid, signal);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Gone already, or not ours to end: what still runs is reported below.
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
// On Windows every signal ends the process at once (TerminateProcess).
|
|
204
|
+
send(platform === 'win32' ? 'SIGKILL' : 'SIGTERM', pids);
|
|
205
|
+
for (let waited = 0; waited < (platform === 'win32' ? 1000 : TERM_MS); waited += 250) {
|
|
206
|
+
if (!pids.some(alive))
|
|
207
|
+
return [];
|
|
208
|
+
await sleep(250);
|
|
209
|
+
}
|
|
210
|
+
if (platform !== 'win32') {
|
|
211
|
+
send('SIGKILL', pids.filter(alive));
|
|
212
|
+
await sleep(250);
|
|
213
|
+
}
|
|
214
|
+
return pids.filter(alive);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function addListener(listeners, ports, port, pid) {
|
|
219
|
+
if (port === null || !ports.includes(port) || !Number.isInteger(pid) || pid <= 0)
|
|
220
|
+
return;
|
|
221
|
+
const pids = listeners.get(port) ?? [];
|
|
222
|
+
if (!pids.includes(pid))
|
|
223
|
+
listeners.set(port, [...pids, pid]);
|
|
224
|
+
}
|
|
225
|
+
// Whether the path is inside the root: a file in it, never the folder itself, which only an argument
|
|
226
|
+
// names (a terminal's or an editor's). Both are normal().
|
|
227
|
+
function isUnder(path, root, platform) {
|
|
228
|
+
const sep = platform === 'win32' ? '\\' : '/';
|
|
229
|
+
const prefix = root.endsWith(sep) ? root : `${root}${sep}`;
|
|
230
|
+
return path.length > prefix.length && path.startsWith(prefix);
|
|
231
|
+
}
|
|
232
|
+
// Whether a /proc/<pid>/stat says the process is a zombie: its state, after the command's `) `, is Z.
|
|
233
|
+
function isZombie(stat) {
|
|
234
|
+
return stat !== null && stat.charAt(stat.lastIndexOf(')') + 2) === 'Z';
|
|
235
|
+
}
|
|
236
|
+
// Linux: every process's parent and start from /proc/<pid>/stat, its executable and its command line.
|
|
237
|
+
// A process that ends while it is read, or one of another user's whose exe can't be read, keeps what
|
|
238
|
+
// could be read.
|
|
239
|
+
function linuxProcesses(proc) {
|
|
240
|
+
const entries = [];
|
|
241
|
+
for (const name of proc.list()) {
|
|
242
|
+
if (!/^\d+$/.test(name))
|
|
243
|
+
continue;
|
|
244
|
+
const stat = proc.read(posix.join('/proc', name, 'stat'));
|
|
245
|
+
// pid (comm) state ppid … starttime (field 22); comm may hold spaces and parentheses.
|
|
246
|
+
const fields = stat?.slice(stat.lastIndexOf(')') + 2).split(' ');
|
|
247
|
+
if (!fields)
|
|
248
|
+
continue;
|
|
249
|
+
const cmdline = proc.read(posix.join('/proc', name, 'cmdline')) ?? '';
|
|
250
|
+
entries.push({
|
|
251
|
+
// Quoted where a word holds a space, so programPaths reads the words back.
|
|
252
|
+
command: cmdline
|
|
253
|
+
.split('\0')
|
|
254
|
+
.filter(Boolean)
|
|
255
|
+
.map((word) => (/\s/.test(word) ? `"${word}"` : word))
|
|
256
|
+
.join(' '),
|
|
257
|
+
executable: proc.link(posix.join('/proc', name, 'exe')),
|
|
258
|
+
pid: Number(name),
|
|
259
|
+
ppid: Number(fields[1]),
|
|
260
|
+
started: Number(fields[19]) || null,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return entries;
|
|
264
|
+
}
|
|
265
|
+
async function listProcesses(platform, ports, run, proc) {
|
|
266
|
+
if (platform === 'win32') {
|
|
267
|
+
const result = await run('powershell.exe', [
|
|
268
|
+
'-NoProfile',
|
|
269
|
+
'-NonInteractive',
|
|
270
|
+
'-EncodedCommand',
|
|
271
|
+
Buffer.from(windowsListingScript(ports), 'utf16le').toString('base64'),
|
|
272
|
+
], { timeoutMs: 30_000 });
|
|
273
|
+
if (result.code !== 0)
|
|
274
|
+
throw new ConductorError("couldn't list the processes", [outputOf(result, 500)]);
|
|
275
|
+
return parseWindowsListing(result.stdout, ports);
|
|
276
|
+
}
|
|
277
|
+
const unseen = [];
|
|
278
|
+
let processes;
|
|
279
|
+
if (platform === 'linux') {
|
|
280
|
+
processes = linuxProcesses(proc);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// -ww: BSD ps cuts a line at the terminal's width, or 80 columns with none.
|
|
284
|
+
const ps = await run('ps', ['-A', '-ww', '-o', 'pid=,ppid=,args='], { timeoutMs: 20_000 });
|
|
285
|
+
if (ps.code !== 0)
|
|
286
|
+
throw new ConductorError("couldn't list the processes", [outputOf(ps, 500)]);
|
|
287
|
+
processes = parsePs(ps.stdout);
|
|
288
|
+
}
|
|
289
|
+
let listeners = new Map();
|
|
290
|
+
if (ports.length > 0) {
|
|
291
|
+
const result = platform === 'linux'
|
|
292
|
+
? await run('ss', ['-ltnpH'], { timeoutMs: 20_000 })
|
|
293
|
+
: await run('lsof', ['-nP', '-iTCP', '-sTCP:LISTEN', '-Fpn'], { timeoutMs: 20_000 });
|
|
294
|
+
// lsof exits 1 when nothing listens.
|
|
295
|
+
if (result.code === 0 || (platform === 'darwin' && result.code === 1 && result.stdout.trim() === ''))
|
|
296
|
+
listeners = platform === 'linux' ? parseSs(result.stdout, ports) : parseLsofListeners(result.stdout, ports);
|
|
297
|
+
else
|
|
298
|
+
unseen.push(`listening ports: ${platform === 'linux' ? 'ss' : 'lsof'} failed: ${outputOf(result, 200)}`);
|
|
299
|
+
}
|
|
300
|
+
return { listeners, processes, unseen };
|
|
301
|
+
}
|
|
302
|
+
// A path as compared: Windows' without case and with backslashes alone, so `C:/wt/X` matches `C:\wt\X`.
|
|
303
|
+
function normal(path, platform) {
|
|
304
|
+
return platform === 'win32' ? path.replace(/\//g, '\\').toLowerCase() : path;
|
|
305
|
+
}
|
|
306
|
+
function parseJson(text) {
|
|
307
|
+
try {
|
|
308
|
+
// A PowerShell can start its UTF-8 output with a byte order mark.
|
|
309
|
+
return JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function portOf(address) {
|
|
316
|
+
const port = Number(/:(\d+)$/.exec(address.trim())?.[1]);
|
|
317
|
+
return Number.isInteger(port) && port > 0 ? port : null;
|
|
318
|
+
}
|
|
319
|
+
// A program's file name, lower case and without .exe on Windows.
|
|
320
|
+
function programName(path, platform) {
|
|
321
|
+
const base = platform === 'win32' ? win32.basename(path.replace(/\//g, '\\')) : posix.basename(path);
|
|
322
|
+
return platform === 'win32' ? base.toLowerCase().replace(/\.exe$/, '') : base;
|
|
323
|
+
}
|
|
324
|
+
// The paths a process runs from, normal(): its executable, its program word, and, for an interpreter
|
|
325
|
+
// such as node, the script it runs (the first absolute path among the words after the program that
|
|
326
|
+
// aren't options, past an option's value such as `--import tsx`). Never another argument: a process
|
|
327
|
+
// that only takes the worktree as one, such as a terminal or editor opened there or a shell told to
|
|
328
|
+
// cd there, doesn't run from it, and its tree isn't the worker's.
|
|
329
|
+
function programPaths(entry, platform) {
|
|
330
|
+
const path = platform === 'win32' ? win32 : posix;
|
|
331
|
+
const words = [...entry.command.matchAll(/"([^"]*)"|(\S+)/g)].map((m) => m[1] ?? m[2] ?? '');
|
|
332
|
+
const [program = '', ...rest] = words;
|
|
333
|
+
const paths = [program, ...(entry.executable === null ? [] : [entry.executable])];
|
|
334
|
+
if (INTERPRETERS.has(programName(entry.executable ?? program, platform))) {
|
|
335
|
+
const script = rest.find((word) => !word.startsWith('-') && path.isAbsolute(word));
|
|
336
|
+
if (script !== undefined)
|
|
337
|
+
paths.push(script);
|
|
338
|
+
}
|
|
339
|
+
// Normalized, so `<worktree>\..\elsewhere` isn't taken for a path in the worktree.
|
|
340
|
+
return paths.filter((p) => path.isAbsolute(p)).map((p) => normal(path.normalize(p), platform));
|
|
341
|
+
}
|
|
342
|
+
// The worktree's path as given and as its real (long, linked) form, without a trailing separator.
|
|
343
|
+
function worktreeRoots(worktree, platform) {
|
|
344
|
+
const path = platform === 'win32' ? win32 : posix;
|
|
345
|
+
const trim = (p) => {
|
|
346
|
+
const n = normal(p, platform);
|
|
347
|
+
return n.length > 1 && /[\\/]$/.test(n) && !/^[a-z]:\\$/.test(n) ? n.slice(0, -1) : n;
|
|
348
|
+
};
|
|
349
|
+
return [...new Set([trim(path.resolve(worktree)), trim(realOr(worktree))])];
|
|
350
|
+
}
|
|
351
|
+
const realProc = {
|
|
352
|
+
link: (p) => {
|
|
353
|
+
try {
|
|
354
|
+
return readlinkSync(p);
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
list: () => {
|
|
361
|
+
try {
|
|
362
|
+
return readdirSync('/proc');
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
read: (p) => {
|
|
369
|
+
try {
|
|
370
|
+
return readFileSync(p, 'utf8');
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
const windowsListing = z.object({
|
|
378
|
+
gap: z.string().nullish(),
|
|
379
|
+
// ConvertTo-Json writes a one-element array as the element alone in some PowerShells.
|
|
380
|
+
listeners: z.preprocess((v) => (v === null || v === undefined ? [] : Array.isArray(v) ? v : [v]), z.array(z.object({ pid: z.number(), port: z.number() }))),
|
|
381
|
+
processes: z.preprocess((v) => (v === null || v === undefined ? [] : Array.isArray(v) ? v : [v]), z.array(z.object({
|
|
382
|
+
c: z.string().nullish(),
|
|
383
|
+
e: z.string().nullish(),
|
|
384
|
+
p: z.number(),
|
|
385
|
+
pp: z.number(),
|
|
386
|
+
s: z.number().nullish(),
|
|
387
|
+
}))),
|
|
388
|
+
});
|
|
389
|
+
//# sourceMappingURL=worktree-processes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-processes.js","sourceRoot":"","sources":["../../src/host/worktree-processes.ts"],"names":[],"mappings":"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"}
|
package/build/inbox.js
CHANGED
|
@@ -10,6 +10,7 @@ import { refusalProblems } from "./rules-service.js";
|
|
|
10
10
|
import { formatTokens } from "./spend.js";
|
|
11
11
|
import {} from "./store.js";
|
|
12
12
|
import { describePending, pendingCallSchema } from "./transcript.js";
|
|
13
|
+
import { goneMessage } from "./watchers/source.js";
|
|
13
14
|
// A Handoff kind (protocol.ts) to the item it raises. `conductor` isn't the operator's: the console
|
|
14
15
|
// answers it.
|
|
15
16
|
const NOTE_KINDS = {
|
|
@@ -97,6 +98,9 @@ const waitData = z.looseObject({
|
|
|
97
98
|
// A PR's settled checks, on a checks wait (watchers/index.ts).
|
|
98
99
|
checks: z.string().optional(),
|
|
99
100
|
condition: z.string(),
|
|
101
|
+
// The item the wait's tracker no longer has (watchers/index.ts, ATK-870).
|
|
102
|
+
gone: z.string().optional(),
|
|
103
|
+
name: z.string().optional(),
|
|
100
104
|
resolution: z.string().optional(),
|
|
101
105
|
worker: z.number(),
|
|
102
106
|
});
|
|
@@ -354,11 +358,30 @@ export function inboxService({ onWaitResolved, store, tracker }) {
|
|
|
354
358
|
.at(-1);
|
|
355
359
|
return newest?.resolvedBy?.startsWith(HELD) ? newest : null;
|
|
356
360
|
};
|
|
361
|
+
// A wait whose item its tracker no longer has (ATK-870): the worker wakes to it, and the operator
|
|
362
|
+
// hears of it once per worker and item, until the worker's next note on its item or its retire.
|
|
363
|
+
const onGone = (event, gone, resolution, worker, name) => {
|
|
364
|
+
const text = `${goneText(gone)} (${goneMessage(gone, resolution)}), so ${name ?? 'its worker'}'s wait on it ended and it woke`;
|
|
365
|
+
if (openOf(worker, ['failed']).some((i) => i.text.startsWith(goneText(gone))))
|
|
366
|
+
return;
|
|
367
|
+
raise({
|
|
368
|
+
commands: name === undefined ? [] : [`conduct attach ${name}`],
|
|
369
|
+
condition: null,
|
|
370
|
+
item: event.subject,
|
|
371
|
+
kind: 'failed',
|
|
372
|
+
links: [],
|
|
373
|
+
project: event.project,
|
|
374
|
+
text,
|
|
375
|
+
worker,
|
|
376
|
+
});
|
|
377
|
+
};
|
|
357
378
|
const onResolvedWait = (event) => {
|
|
358
379
|
const data = waitData.safeParse(event.data);
|
|
359
380
|
if (!data.success)
|
|
360
381
|
return;
|
|
361
|
-
const { checks, condition: text, resolution = text, worker } = data.data;
|
|
382
|
+
const { checks, condition: text, gone, name, resolution = text, worker } = data.data;
|
|
383
|
+
if (gone !== undefined)
|
|
384
|
+
onGone(event, gone, resolution, worker, name);
|
|
362
385
|
const condition = conditionOf(text);
|
|
363
386
|
const release = condition ? releaseGate(condition.kind) : null;
|
|
364
387
|
if (condition?.kind === 'approval') {
|
|
@@ -521,7 +544,7 @@ export function inboxService({ onWaitResolved, store, tracker }) {
|
|
|
521
544
|
// Red checks are the PR's, and a failed Handoff the worker's, not the session's: a lost session
|
|
522
545
|
// still raises its own failure.
|
|
523
546
|
const own = (kind, text, commands) => {
|
|
524
|
-
if (openOf(worker, [kind]).some((i) => !isChecksFailure(i) && !answeredOnItem(i)))
|
|
547
|
+
if (openOf(worker, [kind]).some((i) => !isChecksFailure(i) && !answeredOnItem(i) && !isGoneItem(i)))
|
|
525
548
|
return;
|
|
526
549
|
raise({ commands, condition: null, item: event.subject, kind, links: [], project: event.project, text, worker });
|
|
527
550
|
};
|
|
@@ -583,8 +606,8 @@ export function inboxService({ onWaitResolved, store, tracker }) {
|
|
|
583
606
|
case 'worker.revived':
|
|
584
607
|
case 'worker.running-again':
|
|
585
608
|
// Red checks wake their worker, which doesn't make them green, and a failed Handoff waits on
|
|
586
|
-
// its answer or the worker's next note (ATK-718).
|
|
587
|
-
resolveAll(openOf(worker, [...SESSION_KINDS, 'failed']).filter((i) => !isChecksFailure(i) && !answeredOnItem(i)), `${name} running again`);
|
|
609
|
+
// its answer or the worker's next note (ATK-718), as does a gone item, which woke it (ATK-870).
|
|
610
|
+
resolveAll(openOf(worker, [...SESSION_KINDS, 'failed']).filter((i) => !isChecksFailure(i) && !answeredOnItem(i) && !isGoneItem(i)), `${name} running again`);
|
|
588
611
|
return;
|
|
589
612
|
case 'worker.retired': {
|
|
590
613
|
resolveAll(store.openInbox().filter((i) => i.worker === worker), `${name} retired`);
|
|
@@ -807,6 +830,10 @@ function conditionOf(text) {
|
|
|
807
830
|
return null;
|
|
808
831
|
}
|
|
809
832
|
}
|
|
833
|
+
// How a gone item's failure starts (onGone raises them), which also marks it as one.
|
|
834
|
+
function goneText(item) {
|
|
835
|
+
return `${item} is gone from its tracker`;
|
|
836
|
+
}
|
|
810
837
|
// A failure about a PR's red checks (onChecksFailed raises them), the only failure on a checks wait.
|
|
811
838
|
function isChecksFailure(item) {
|
|
812
839
|
return item.kind === 'failed' && item.condition !== null && item.condition.endsWith(':checks');
|
|
@@ -816,6 +843,10 @@ function isChecksFailure(item) {
|
|
|
816
843
|
function isCompactFailure(item) {
|
|
817
844
|
return item.kind === 'context' && item.commands.some((c) => c.startsWith('conduct retire '));
|
|
818
845
|
}
|
|
846
|
+
// A failure about an item its tracker no longer has (onGone raises them).
|
|
847
|
+
function isGoneItem(item) {
|
|
848
|
+
return item.kind === 'failed' && /^\S+ is gone from its tracker /.test(item.text);
|
|
849
|
+
}
|
|
819
850
|
function isParkStall(item) {
|
|
820
851
|
return item.kind === 'stall' && item.commands.some((c) => c.startsWith('conduct retire '));
|
|
821
852
|
}
|