agentic-workflow-manager 9.16.0 → 9.16.1
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/src/core/journal/process.js +22 -8
- package/dist/tests/core/journal/process.test.js +33 -10
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/secure_fs.node +0 -0
- package/prebuilds/darwin-x64/secure_fs.node +0 -0
- package/prebuilds/win32-arm64/secure_fs.node +0 -0
- package/prebuilds/win32-x64/secure_fs.node +0 -0
|
@@ -470,7 +470,10 @@ function descendantActivity(psTable, rootPid) {
|
|
|
470
470
|
const children = new Map();
|
|
471
471
|
let rows = 0;
|
|
472
472
|
for (const line of psTable.split('\n')) {
|
|
473
|
-
|
|
473
|
+
// time may be empty on some Darwin samples for a just-spawned process;
|
|
474
|
+
// treat blank as "0" so the pid still joins the descendant tree (otherwise
|
|
475
|
+
// a healthy detached grandchild is invisible and activity reads as frozen).
|
|
476
|
+
const match = /^\s*(\d+)\s+(\d+)(?:\s+(\S+))?\s*$/.exec(line);
|
|
474
477
|
if (match === null)
|
|
475
478
|
continue;
|
|
476
479
|
if (++rows > MAX_PS_ROWS)
|
|
@@ -478,7 +481,7 @@ function descendantActivity(psTable, rootPid) {
|
|
|
478
481
|
const pid = Number(match[1]);
|
|
479
482
|
const ppid = Number(match[2]);
|
|
480
483
|
const siblings = children.get(ppid) ?? [];
|
|
481
|
-
siblings.push({ pid, time: match[3] });
|
|
484
|
+
siblings.push({ pid, time: match[3] && match[3].length > 0 ? match[3] : '0' });
|
|
482
485
|
children.set(ppid, siblings);
|
|
483
486
|
}
|
|
484
487
|
const seen = new Set([rootPid]);
|
|
@@ -499,13 +502,24 @@ function descendantActivity(psTable, rootPid) {
|
|
|
499
502
|
return `${found.length}:${crypto_1.default.createHash('sha256').update(found.join('\n')).digest('hex')}`;
|
|
500
503
|
}
|
|
501
504
|
function observeDescendants(rootPid) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
505
|
+
// One transient `ps` failure under CI load used to freeze the snapshot at
|
|
506
|
+
// `unknown`, which made the Darwin integration test (and a real supervisor
|
|
507
|
+
// tick) treat a later concrete `0:none` as "activity changed" without ever
|
|
508
|
+
// seeing the grandchild. Retry once before degrading.
|
|
509
|
+
let lastError;
|
|
510
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
511
|
+
try {
|
|
512
|
+
const table = (0, child_process_1.execFileSync)('ps', ['-A', '-o', 'pid=,ppid=,time='], {
|
|
513
|
+
encoding: 'utf8', stdio: exports.EXEC_STDIO, timeout: PS_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024,
|
|
514
|
+
});
|
|
515
|
+
return descendantActivity(table, rootPid);
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
lastError = error;
|
|
519
|
+
}
|
|
508
520
|
}
|
|
521
|
+
void lastError;
|
|
522
|
+
return 'unknown';
|
|
509
523
|
}
|
|
510
524
|
/** Llamada UNA VEZ POR TICK por el supervisor (ver superviseController en
|
|
511
525
|
* commands/watch/supervisor.ts) mientras un controlador este activo — el
|
|
@@ -202,28 +202,51 @@ describe('process identity', () => {
|
|
|
202
202
|
test('ignores malformed ps lines instead of inventing processes', () => {
|
|
203
203
|
expect((0, process_1.descendantActivity)('garbage\n 20 10 00:00:01\n\n x y z', 10)).toMatch(/^1:/);
|
|
204
204
|
});
|
|
205
|
+
test('keeps Darwin-style rows with blank or dotted cputime in the tree', () => {
|
|
206
|
+
// macOS `ps -o time=` is often `0:00.01`; a brand-new process can also
|
|
207
|
+
// omit the third column entirely on some samples.
|
|
208
|
+
expect((0, process_1.descendantActivity)(' 10 1 0:00.05\n 20 10 0:00.01\n 30 20\n', 10)).toMatch(/^2:/);
|
|
209
|
+
expect((0, process_1.descendantActivity)(' 10 1\n 20 10\n', 10)).toMatch(/^1:/);
|
|
210
|
+
});
|
|
205
211
|
});
|
|
206
212
|
test('activitySnapshot ve un nieto fuera del process group del controlador', async () => {
|
|
207
213
|
if ((0, paths_1.isWindowsNative)())
|
|
208
214
|
return; // win32 degrada activity sin ps (ver activitySnapshot)
|
|
209
|
-
const script = "setTimeout(() => { require('child_process').spawn(process.execPath, ['-e', 'setTimeout(()=>{},
|
|
215
|
+
const script = "setTimeout(() => { require('child_process').spawn(process.execPath, ['-e', 'setTimeout(()=>{}, 15000)'], { detached: true, stdio: 'ignore' }).unref(); }, 200); setTimeout(()=>{}, 15000)";
|
|
210
216
|
const { child, ref } = (0, process_1.spawnStructured)(['node', '-e', script], process.cwd(), 'n-desc');
|
|
211
217
|
try {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
let
|
|
215
|
-
for (let i = 0; i < 40 && after !== null && after.descendants === before.descendants; i++) {
|
|
218
|
+
// Wait for a concrete baseline (not `unknown` from a transient ps miss).
|
|
219
|
+
let before = (0, process_1.activitySnapshot)(ref);
|
|
220
|
+
for (let i = 0; i < 50 && (before === null || before.descendants === 'unknown'); i++) {
|
|
216
221
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
217
|
-
|
|
222
|
+
before = (0, process_1.activitySnapshot)(ref);
|
|
223
|
+
}
|
|
224
|
+
expect(before).not.toBeNull();
|
|
225
|
+
expect(before.descendants).not.toBe('unknown');
|
|
226
|
+
const beforeGroup = before.groupSize;
|
|
227
|
+
let after = before;
|
|
228
|
+
const deadline = Date.now() + 8000;
|
|
229
|
+
while (Date.now() < deadline) {
|
|
230
|
+
const snap = (0, process_1.activitySnapshot)(ref);
|
|
231
|
+
if (snap !== null)
|
|
232
|
+
after = snap;
|
|
233
|
+
// Success: same process group, at least one PPID-descendant appeared.
|
|
234
|
+
if (after.groupSize === beforeGroup && /^[1-9]\d*:/.test(after.descendants))
|
|
235
|
+
break;
|
|
236
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
218
237
|
}
|
|
219
|
-
expect(after).not.toBeNull();
|
|
220
238
|
// The detached grandchild lives in its own process group: the group
|
|
221
239
|
// signal cannot see it, the descendant signal must.
|
|
222
|
-
expect(after.groupSize).toBe(
|
|
223
|
-
expect(after.descendants).
|
|
224
|
-
expect(after.descendants).toMatch(/^1:/);
|
|
240
|
+
expect(after.groupSize).toBe(beforeGroup);
|
|
241
|
+
expect(after.descendants).toMatch(/^[1-9]\d*:/);
|
|
225
242
|
}
|
|
226
243
|
finally {
|
|
244
|
+
// Detached grandchildren are outside `-PGID`; reap by parent pid too.
|
|
245
|
+
try {
|
|
246
|
+
const { execFileSync } = require('child_process');
|
|
247
|
+
execFileSync('pkill', ['-P', String(ref.pid)], { stdio: 'ignore', timeout: 1000 });
|
|
248
|
+
}
|
|
249
|
+
catch { /* ya ausente */ }
|
|
227
250
|
try {
|
|
228
251
|
process.kill(-ref.processGroup, 'SIGKILL');
|
|
229
252
|
}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|