@linzumi/cli 1.0.110 → 1.0.112

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.
@@ -0,0 +1,734 @@
1
+ // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
2
+ // (M3 cluster 10, commander-core / supervisor).
3
+ // Relationship: Builds the TS-side PARITY ORACLE for the `connect
4
+ // --supervise` supervisor port (src/supervisor.ts -> ReScript
5
+ // CommanderSupervisor), the sibling of build-pipeline-parity-oracle.mjs
6
+ // (cluster 9). The oracle bundles the REAL supervisor module - the flag
7
+ // helpers, the code fingerprint, the supervisor lock (real fs on a scratch
8
+ // dir, byte-compared records), the console logger + signal disposition, the
9
+ // gone-TTY write-guard slice of ttyTeardownGuard.ts, the runSuperviseLoop
10
+ // refusal legs, and createSupervisor (THE state machine) driven through
11
+ // fully scripted deps: a scripted scheduler/clock (the scriptedTimers
12
+ // pattern), a scripted child-process seam (ops declare exits with
13
+ // codes/signals and IPC frames; spawns/kills/sends land in the trace), and
14
+ // scripted probe/install/fingerprint/reexec seams - behind the one-shot
15
+ // stdin/stdout JSON batch driver. Every supervision run returns the FULL
16
+ // trace (spawn calls with argv/env deltas, signals sent, timer set/clear,
17
+ // log events, store writes) for byte comparison.
18
+ //
19
+ // Determinism: clocks are injected per case; timers fire in scheduling
20
+ // order once the scripted clock passes their due instant, with a full
21
+ // microtask settle between fires and between ops (both drivers settle
22
+ // identically, so async update-check chains interleave identically); the
23
+ // only non-injectable TS timestamp (the lock record's startedAt) is pinned
24
+ // with a scoped global-Date override, the cluster 2 oracle's technique.
25
+ //
26
+ // SECRETS: the oracle only ever sees the conformance suite's synthetic
27
+ // argv/env/payloads. The output is a local test artifact (.differential/
28
+ // is gitignored, never published) and stays unminified for debuggability.
29
+ import { mkdir } from 'node:fs/promises';
30
+ import { dirname, join } from 'node:path';
31
+ import { fileURLToPath } from 'node:url';
32
+ import { build } from 'esbuild';
33
+
34
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
35
+
36
+ const driverSource = `
37
+ import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
38
+ import { tmpdir } from 'node:os';
39
+ import { dirname, join } from 'node:path';
40
+ import {
41
+ acquireSupervisorLock,
42
+ createSupervisor,
43
+ createSupervisorConsoleLogger,
44
+ defaultSupervisorReexecStatePath,
45
+ defaultSupervisorTiming,
46
+ hasSuperviseFlag,
47
+ installSupervisorSignalHandlers,
48
+ isSupervisedChild,
49
+ runSuperviseLoop,
50
+ supervisedChildEnvKey,
51
+ supervisorCodeFingerprint,
52
+ supervisorLockKey,
53
+ supervisorLockPath,
54
+ withoutSuperviseFlags,
55
+ } from './src/supervisor';
56
+ import {
57
+ defaultGenerationStillbornWindowMs,
58
+ generationEpochEnvKey,
59
+ generationHandoffPidEnvKey,
60
+ generationOverlapFlagEnvKey,
61
+ } from './src/generationOverlap';
62
+ import { defaultLinzumiWebSocketUrl } from './src/defaultUrls';
63
+ import {
64
+ goneTtyErrorCode,
65
+ goneTtyWriteErrorCode,
66
+ guardStreamWriteAgainstGoneTty,
67
+ streamGoneTtyWriteCodeForTest,
68
+ } from './src/ttyTeardownGuard';
69
+
70
+ const RealDate = Date;
71
+
72
+ function withPinnedDate(nowMs, fn) {
73
+ class PinnedDate extends RealDate {
74
+ constructor(...args) {
75
+ if (args.length === 0) {
76
+ super(nowMs);
77
+ } else {
78
+ super(...args);
79
+ }
80
+ }
81
+ }
82
+ PinnedDate.now = () => nowMs;
83
+ globalThis.Date = PinnedDate;
84
+ try {
85
+ return fn();
86
+ } finally {
87
+ globalThis.Date = RealDate;
88
+ }
89
+ }
90
+
91
+ const settle = () => new Promise((resolve) => setImmediate(resolve));
92
+
93
+ // --- Scripted scheduler (the scriptedTimers pattern; ids in creation order) ---
94
+
95
+ function scriptedScheduler(clock, trace) {
96
+ let nextId = 1;
97
+ const pending = [];
98
+ return {
99
+ scheduler: {
100
+ setTimeout: (callback, ms) => {
101
+ const id = nextId;
102
+ nextId += 1;
103
+ trace.push({ t: 'timer_set', id, delayMs: ms });
104
+ pending.push({ id, dueAtMs: clock.nowMs + ms, callback });
105
+ return id;
106
+ },
107
+ clearTimeout: (handle) => {
108
+ const index = pending.findIndex((timer) => timer.id === handle);
109
+ if (index >= 0) {
110
+ trace.push({ t: 'timer_clear', id: pending[index].id });
111
+ pending.splice(index, 1);
112
+ }
113
+ },
114
+ },
115
+ fireNextDue: () => {
116
+ const index = pending.findIndex((timer) => timer.dueAtMs <= clock.nowMs);
117
+ if (index < 0) return false;
118
+ const timer = pending.splice(index, 1)[0];
119
+ trace.push({ t: 'timer_fire', id: timer.id });
120
+ timer.callback();
121
+ return true;
122
+ },
123
+ };
124
+ }
125
+
126
+ // --- The scripted supervision run --------------------------------------------------
127
+
128
+ async function runSupervisionCase(caseInput) {
129
+ // The TS serial drain reads process.platform at drain time (the win32
130
+ // SIGTERM fallback); the ReScript port injects isWin32. Pin the live
131
+ // platform for win32 cases so both impls run the same branch.
132
+ const platformDescriptor = Object.getOwnPropertyDescriptor(process, 'platform');
133
+ if (caseInput.win32 === true) {
134
+ Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
135
+ }
136
+ try {
137
+ return await runSupervisionCaseInner(caseInput);
138
+ } finally {
139
+ if (caseInput.win32 === true && platformDescriptor !== undefined) {
140
+ Object.defineProperty(process, 'platform', platformDescriptor);
141
+ }
142
+ }
143
+ }
144
+
145
+ async function runSupervisionCaseInner(caseInput) {
146
+ const clock = { nowMs: caseInput.startMs ?? 0 };
147
+ const trace = [];
148
+ const timers = scriptedScheduler(clock, trace);
149
+ const children = [];
150
+ const entryBytes = new Map(Object.entries(caseInput.entryBytes ?? {}));
151
+ let probeState = { kind: 'none' };
152
+ let installState = { kind: 'none' };
153
+ let storedAttempt = caseInput.attemptRecord ?? undefined;
154
+
155
+ const initialEntryPath = caseInput.initialEntryPath ?? '/stable/v-base/bin/linzumi.js';
156
+ const childArgs = caseInput.childArgs ?? ['--workspace', 'ws-parity'];
157
+
158
+ const supervisor = createSupervisor({
159
+ childArgs,
160
+ initialEntryPath,
161
+ initialVersion: caseInput.initialVersion ?? '1.0.0',
162
+ ownEntryPath:
163
+ caseInput.ownEntryPath === null
164
+ ? undefined
165
+ : (caseInput.ownEntryPath ?? initialEntryPath),
166
+ spawnChild: ({ entryPath, childArgs: spawnArgs, onExit, generation }) => {
167
+ const index = children.length;
168
+ const pid = 4200 + index;
169
+ const record = { index, pid, alive: true, onExit, generation, sendOk: true };
170
+ children.push(record);
171
+ trace.push({
172
+ t: 'spawn',
173
+ index,
174
+ pid,
175
+ entryPath,
176
+ argv: [entryPath, 'connect', ...spawnArgs],
177
+ generation:
178
+ generation === undefined
179
+ ? null
180
+ : {
181
+ epoch: generation.epoch,
182
+ handoffFromPid: generation.handoffFromPid ?? null,
183
+ ipc: generation.onMessage !== undefined,
184
+ },
185
+ envDelta:
186
+ generation === undefined
187
+ ? { [supervisedChildEnvKey]: '1' }
188
+ : {
189
+ [supervisedChildEnvKey]: '1',
190
+ [generationEpochEnvKey]: String(generation.epoch),
191
+ ...(generation.handoffFromPid === undefined
192
+ ? {}
193
+ : {
194
+ [generationHandoffPidEnvKey]: String(generation.handoffFromPid),
195
+ }),
196
+ },
197
+ });
198
+ return {
199
+ pid,
200
+ kill: (signal) => trace.push({ t: 'kill', child: index, signal }),
201
+ ...(generation === undefined
202
+ ? {}
203
+ : {
204
+ send: (message) => {
205
+ trace.push({ t: 'send', child: index, message, ok: record.sendOk });
206
+ return record.sendOk;
207
+ },
208
+ }),
209
+ };
210
+ },
211
+ probeLatestVersion: async () => {
212
+ trace.push({ t: 'probe' });
213
+ if (probeState.kind === 'error') throw new Error(probeState.message);
214
+ return probeState.kind === 'version' ? probeState.version : undefined;
215
+ },
216
+ installVersion: async (version) => {
217
+ trace.push({ t: 'install', version });
218
+ if (installState.kind === 'error') throw new Error(installState.message);
219
+ if (installState.kind === 'entry') return { entryPath: installState.entryPath };
220
+ throw new Error('no scripted install result');
221
+ },
222
+ readEntryBytes: (entryPath) => {
223
+ trace.push({ t: 'read_bytes', path: entryPath });
224
+ return entryBytes.get(entryPath);
225
+ },
226
+ reexecSelf: ({ entryPath }) => trace.push({ t: 'reexec', entryPath }),
227
+ reexecAttemptStore: {
228
+ load: () => storedAttempt,
229
+ save: (record) => {
230
+ trace.push({ t: 'attempt_save', record });
231
+ storedAttempt = record;
232
+ },
233
+ },
234
+ log: (event, payload = {}) => trace.push({ t: 'log', event, payload }),
235
+ scheduler: timers.scheduler,
236
+ now: () => clock.nowMs,
237
+ timing: caseInput.timing ?? undefined,
238
+ ...(caseInput.overlap === undefined
239
+ ? {}
240
+ : {
241
+ generationOverlap: {
242
+ enabled: caseInput.overlap.enabled === true,
243
+ stillbornWindowMs: caseInput.overlap.stillbornWindowMs,
244
+ },
245
+ }),
246
+ });
247
+
248
+ const aliveChildren = () => children.filter((child) => child.alive);
249
+ const exitChild = (record, code, signal) => {
250
+ record.alive = false;
251
+ trace.push({ t: 'exit', child: record.index, code, signal });
252
+ record.onExit({ code, signal });
253
+ };
254
+ const ipcTo = (record, label, message) => {
255
+ if (
256
+ record === undefined ||
257
+ record.generation === undefined ||
258
+ record.generation.onMessage === undefined
259
+ ) {
260
+ trace.push({ t: 'ipc_no_channel', op: label });
261
+ return;
262
+ }
263
+ trace.push({ t: 'ipc', child: record.index, message });
264
+ record.generation.onMessage(message);
265
+ };
266
+
267
+ for (const op of caseInput.ops ?? []) {
268
+ switch (op.op) {
269
+ case 'start':
270
+ supervisor.start();
271
+ break;
272
+ case 'advance': {
273
+ clock.nowMs += op.byMs;
274
+ let fired = timers.fireNextDue();
275
+ while (fired) {
276
+ await settle();
277
+ fired = timers.fireNextDue();
278
+ }
279
+ break;
280
+ }
281
+ case 'exitNewest':
282
+ case 'exitOldest': {
283
+ const alive = aliveChildren();
284
+ const target = op.op === 'exitNewest' ? alive[alive.length - 1] : alive[0];
285
+ if (target === undefined) {
286
+ trace.push({ t: 'no_child', op: op.op });
287
+ } else {
288
+ exitChild(target, op.code ?? null, op.signal ?? null);
289
+ }
290
+ break;
291
+ }
292
+ case 'exitAll': {
293
+ for (const record of aliveChildren()) {
294
+ exitChild(record, op.code ?? null, op.signal ?? null);
295
+ await settle();
296
+ }
297
+ break;
298
+ }
299
+ case 'ipcReadyNewest': {
300
+ const alive = aliveChildren();
301
+ const target = alive[alive.length - 1];
302
+ ipcTo(target, op.op, {
303
+ type: 'generation_ready',
304
+ epoch: target?.generation?.epoch ?? 0,
305
+ });
306
+ break;
307
+ }
308
+ case 'ipcPinSnapshotOldest': {
309
+ const target = aliveChildren()[0];
310
+ ipcTo(target, op.op, {
311
+ type: 'generation_pin_snapshot',
312
+ epoch: target?.generation?.epoch ?? 0,
313
+ threadIds: op.threadIds,
314
+ });
315
+ break;
316
+ }
317
+ case 'ipcPinReleasedOldest': {
318
+ const target = aliveChildren()[0];
319
+ ipcTo(target, op.op, {
320
+ type: 'generation_pin_released',
321
+ epoch: target?.generation?.epoch ?? 0,
322
+ threadId: op.threadId,
323
+ });
324
+ break;
325
+ }
326
+ case 'ipcGarbageNewest': {
327
+ const alive = aliveChildren();
328
+ ipcTo(alive[alive.length - 1], op.op, op.message);
329
+ break;
330
+ }
331
+ case 'setLatest':
332
+ probeState =
333
+ op.version === null ? { kind: 'none' } : { kind: 'version', version: op.version };
334
+ break;
335
+ case 'probeError':
336
+ probeState = { kind: 'error', message: op.message };
337
+ break;
338
+ case 'setInstall':
339
+ installState = { kind: 'entry', entryPath: op.entryPath };
340
+ break;
341
+ case 'installError':
342
+ installState = { kind: 'error', message: op.message };
343
+ break;
344
+ case 'setBytes':
345
+ if (op.bytes === null) entryBytes.delete(op.path);
346
+ else entryBytes.set(op.path, op.bytes);
347
+ break;
348
+ case 'setSendNewest': {
349
+ const alive = aliveChildren();
350
+ const target = alive[alive.length - 1];
351
+ if (target === undefined) trace.push({ t: 'no_child', op: op.op });
352
+ else target.sendOk = op.ok === true;
353
+ break;
354
+ }
355
+ case 'requestStop':
356
+ supervisor.requestStop(
357
+ op.forwardSignal === undefined ? undefined : { forwardSignal: op.forwardSignal }
358
+ );
359
+ break;
360
+ case 'childActive':
361
+ trace.push({ t: 'child_active', value: supervisor.childActive() });
362
+ break;
363
+ case 'awaitDone': {
364
+ const outcome = await Promise.race([
365
+ supervisor.done.then(() => 'done'),
366
+ new Promise((resolve) => setTimeout(() => resolve('done_timeout'), 5000)),
367
+ ]);
368
+ trace.push({ t: outcome });
369
+ break;
370
+ }
371
+ default:
372
+ trace.push({ t: 'unknown_op', op: op.op });
373
+ }
374
+ await settle();
375
+ }
376
+
377
+ return { trace };
378
+ }
379
+
380
+ // --- Lock acquire runs (real fs on a scratch dir; startedAt pinned) --------------------
381
+
382
+ function runAcquireLockCase(caseInput) {
383
+ const scratch = mkdtempSync(join(tmpdir(), 'linzumi-core-sup-lock-'));
384
+ const lockPath = join(scratch, 'sup.lock');
385
+ const trace = [];
386
+ const releases = [];
387
+ for (const step of caseInput.steps ?? []) {
388
+ if (step.action === 'acquire') {
389
+ const alivePids = step.alivePids ?? [];
390
+ const result = withPinnedDate(caseInput.nowMs ?? 0, () =>
391
+ acquireSupervisorLock({
392
+ path: lockPath,
393
+ workspace: caseInput.workspace ?? 'ws-lock',
394
+ linzumiUrl: caseInput.linzumiUrl ?? 'wss://parity.example',
395
+ pid: step.pid,
396
+ isPidAlive: (candidate) => alivePids.includes(candidate),
397
+ })
398
+ );
399
+ if (result.ok) {
400
+ releases.push(result.release);
401
+ trace.push({ t: 'acquired' });
402
+ } else {
403
+ trace.push({ t: 'held', holderPid: result.holderPid ?? null });
404
+ }
405
+ trace.push({
406
+ t: 'lock_bytes',
407
+ bytes: existsSync(lockPath) ? readFileSync(lockPath, 'utf8') : null,
408
+ });
409
+ } else if (step.action === 'releaseLast') {
410
+ const release = releases.pop();
411
+ if (release !== undefined) release();
412
+ trace.push({ t: 'released', fileExists: existsSync(lockPath) });
413
+ } else if (step.action === 'seedLock') {
414
+ writeFileSync(lockPath, step.content);
415
+ trace.push({ t: 'seeded' });
416
+ }
417
+ }
418
+ return { trace };
419
+ }
420
+
421
+ // --- Console logger / signal handlers / tty guard --------------------------------------
422
+
423
+ function runConsoleLoggerCase(caseInput) {
424
+ const stderrLines = [];
425
+ const audits = [];
426
+ let writes = 0;
427
+ const logger = createSupervisorConsoleLogger({
428
+ writeStderr: (line) => {
429
+ writes += 1;
430
+ if (
431
+ caseInput.stderrFailAfter !== undefined &&
432
+ writes > caseInput.stderrFailAfter
433
+ ) {
434
+ throw new Error('EIO scripted console death');
435
+ }
436
+ stderrLines.push(line);
437
+ },
438
+ audit: (event, payload) => {
439
+ if (caseInput.auditFails === true) throw new Error('scripted audit failure');
440
+ audits.push({ event, payload });
441
+ },
442
+ now: () => new RealDate(caseInput.nowMs ?? 0),
443
+ });
444
+ for (const entry of caseInput.events ?? []) {
445
+ logger(entry.event, entry.payload);
446
+ }
447
+ return { stderrLines, audits };
448
+ }
449
+
450
+ function runSignalHandlersCase(caseInput) {
451
+ const trace = [];
452
+ const once = new Map();
453
+ const on = new Map();
454
+ installSupervisorSignalHandlers(
455
+ {
456
+ requestStop: (options) =>
457
+ trace.push({ t: 'request_stop', forwardSignal: options?.forwardSignal ?? null }),
458
+ },
459
+ (event, payload = {}) => trace.push({ t: 'log', event, payload }),
460
+ {
461
+ once: (event, listener) => {
462
+ const queue = once.get(event) ?? [];
463
+ queue.push(listener);
464
+ once.set(event, queue);
465
+ trace.push({ t: 'registered_once', event });
466
+ },
467
+ on: (event, listener) => {
468
+ const queue = on.get(event) ?? [];
469
+ queue.push(listener);
470
+ on.set(event, queue);
471
+ trace.push({ t: 'registered_on', event });
472
+ },
473
+ }
474
+ );
475
+ for (const signal of caseInput.fires ?? []) {
476
+ trace.push({ t: 'fire', signal });
477
+ const onceQueue = once.get(signal) ?? [];
478
+ if (onceQueue.length > 0) {
479
+ const listener = onceQueue.shift();
480
+ listener();
481
+ }
482
+ for (const listener of on.get(signal) ?? []) {
483
+ listener();
484
+ }
485
+ }
486
+ return { trace };
487
+ }
488
+
489
+ function errorOfSpec(spec) {
490
+ if (spec.kind === 'null') return null;
491
+ if (spec.kind === 'string') return spec.value;
492
+ if (spec.kind === 'number') return spec.value;
493
+ const error = {};
494
+ if (spec.code !== undefined) error.code = spec.code;
495
+ if (spec.message !== undefined) error.message = spec.message;
496
+ return error;
497
+ }
498
+
499
+ function runTtyClassifyCase(caseInput) {
500
+ return (caseInput.errors ?? []).map((spec) => {
501
+ const error = errorOfSpec(spec);
502
+ return {
503
+ gone: goneTtyErrorCode(error) ?? null,
504
+ write: goneTtyWriteErrorCode(error) ?? null,
505
+ };
506
+ });
507
+ }
508
+
509
+ function runTtyGuardCase(caseInput) {
510
+ const trace = [];
511
+ const errorListeners = [];
512
+ let throwSpec;
513
+ const stream = {
514
+ isTTY: true,
515
+ write: (chunk) => {
516
+ if (throwSpec !== undefined) {
517
+ const error = new Error(throwSpec.message);
518
+ if (throwSpec.code !== undefined) error.code = throwSpec.code;
519
+ throwSpec = undefined;
520
+ throw error;
521
+ }
522
+ trace.push({ t: 'underlying_write', chunk });
523
+ return true;
524
+ },
525
+ on: (event, listener) => {
526
+ if (event === 'error') errorListeners.push(listener);
527
+ trace.push({ t: 'listener_added', event });
528
+ },
529
+ listenerCount: (event) => (event === 'error' ? errorListeners.length : 0),
530
+ };
531
+ const sinks = {
532
+ audit: (event, fields) => trace.push({ t: 'sink', leg: 'audit', event, fields }),
533
+ log: (event, fields) => trace.push({ t: 'sink', leg: 'log', event, fields }),
534
+ };
535
+ const guard = (label) =>
536
+ trace.push({
537
+ t: 'guarded',
538
+ label,
539
+ result: guardStreamWriteAgainstGoneTty(stream, {
540
+ context: { surface: 'parity_surface' },
541
+ sinks,
542
+ onGoneTty: (code) => trace.push({ t: 'gone_tty', label, code }),
543
+ rethrow: (error) =>
544
+ trace.push({
545
+ t: 'rethrown',
546
+ message: error instanceof Error ? error.message : String(error),
547
+ }),
548
+ }),
549
+ });
550
+ guard('first');
551
+ for (const op of caseInput.ops ?? []) {
552
+ if (op.op === 'write') {
553
+ if (op.throwCode !== undefined || op.throwMessage !== undefined) {
554
+ throwSpec = { code: op.throwCode, message: op.throwMessage ?? 'scripted write failure' };
555
+ }
556
+ let outcome;
557
+ let threwMessage = null;
558
+ try {
559
+ outcome = stream.write(op.data);
560
+ } catch (error) {
561
+ outcome = null;
562
+ threwMessage = error instanceof Error ? error.message : String(error);
563
+ }
564
+ trace.push({ t: 'write_result', returned: outcome, threw: threwMessage });
565
+ } else if (op.op === 'emitError') {
566
+ const error = new Error(op.message ?? 'scripted stream error');
567
+ if (op.code !== undefined) error.code = op.code;
568
+ trace.push({ t: 'emit_error', code: op.code ?? null });
569
+ for (const listener of [...errorListeners]) listener(error);
570
+ } else if (op.op === 'guardAgain') {
571
+ guard(op.label ?? 'again');
572
+ }
573
+ }
574
+ return { trace, goneCode: streamGoneTtyWriteCodeForTest(stream) ?? null };
575
+ }
576
+
577
+ // --- runSuperviseLoop refusal legs -----------------------------------------------------
578
+
579
+ async function runLockRefusalCase(caseInput) {
580
+ const scratch = mkdtempSync(join(tmpdir(), 'linzumi-core-sup-home-'));
581
+ const workspace = caseInput.workspace ?? '';
582
+ const args = workspace === '' ? [] : ['--workspace', workspace];
583
+ const lockPath = supervisorLockPath(
584
+ { workspace, linzumiUrl: defaultLinzumiWebSocketUrl },
585
+ scratch
586
+ );
587
+ mkdirSync(dirname(lockPath), { recursive: true });
588
+ writeFileSync(
589
+ lockPath,
590
+ JSON.stringify({
591
+ pid: 1,
592
+ workspace,
593
+ linzumiUrl: defaultLinzumiWebSocketUrl,
594
+ startedAt: '2026-01-01T00:00:00.000Z',
595
+ }) + '\\n'
596
+ );
597
+ const previousHome = process.env.HOME;
598
+ process.env.HOME = scratch;
599
+ try {
600
+ await runSuperviseLoop(['--supervise', ...args]);
601
+ return { message: null };
602
+ } catch (error) {
603
+ const message = error instanceof Error ? error.message : String(error);
604
+ return { message: message.split(scratch).join('$SCRATCH') };
605
+ } finally {
606
+ process.env.HOME = previousHome;
607
+ }
608
+ }
609
+
610
+ async function runEmptyEntryCase() {
611
+ const scratch = mkdtempSync(join(tmpdir(), 'linzumi-core-sup-home-'));
612
+ const previousHome = process.env.HOME;
613
+ const previousArgv1 = process.argv[1];
614
+ process.env.HOME = scratch;
615
+ process.argv[1] = '';
616
+ try {
617
+ await runSuperviseLoop(['--supervise', '--workspace', 'ws-empty']);
618
+ return { message: null };
619
+ } catch (error) {
620
+ const message = error instanceof Error ? error.message : String(error);
621
+ return { message: message.split(scratch).join('$SCRATCH') };
622
+ } finally {
623
+ process.env.HOME = previousHome;
624
+ process.argv[1] = previousArgv1;
625
+ }
626
+ }
627
+
628
+ // --- Case dispatch -----------------------------------------------------------------------
629
+
630
+ async function runCase(input) {
631
+ switch (input.kind) {
632
+ case 'constants':
633
+ return {
634
+ supervisedChildEnvKey,
635
+ generationOverlapFlagEnvKey,
636
+ generationEpochEnvKey,
637
+ generationHandoffPidEnvKey,
638
+ defaultGenerationStillbornWindowMs,
639
+ defaultSupervisorTiming,
640
+ defaultLinzumiWebSocketUrl,
641
+ };
642
+ case 'isSupervisedChild':
643
+ return isSupervisedChild(input.env);
644
+ case 'withoutSuperviseFlags':
645
+ return withoutSuperviseFlags(input.args);
646
+ case 'hasSuperviseFlag':
647
+ return hasSuperviseFlag(input.args);
648
+ case 'fingerprint':
649
+ return (
650
+ supervisorCodeFingerprint(input.entryPath, (path) => {
651
+ const bytes = (input.files ?? {})[path];
652
+ return bytes === undefined ? undefined : bytes;
653
+ }) ?? null
654
+ );
655
+ case 'lockKey':
656
+ return supervisorLockKey({ workspace: input.workspace, linzumiUrl: input.linzumiUrl });
657
+ case 'lockPath':
658
+ return supervisorLockPath(
659
+ { workspace: input.workspace, linzumiUrl: input.linzumiUrl },
660
+ input.homeDir
661
+ );
662
+ case 'reexecStatePath':
663
+ return defaultSupervisorReexecStatePath(input.env);
664
+ case 'acquireLockRun':
665
+ return runAcquireLockCase(input);
666
+ case 'consoleLogger':
667
+ return runConsoleLoggerCase(input);
668
+ case 'signalHandlers':
669
+ return runSignalHandlersCase(input);
670
+ case 'ttyClassify':
671
+ return runTtyClassifyCase(input);
672
+ case 'ttyGuardRun':
673
+ return runTtyGuardCase(input);
674
+ case 'lockRefusalLoop':
675
+ return runLockRefusalCase(input);
676
+ case 'emptyEntryLoop':
677
+ return runEmptyEntryCase();
678
+ case 'supervisionRun':
679
+ return runSupervisionCase(input);
680
+ default:
681
+ return { error: 'unknown case kind ' + String(input.kind) };
682
+ }
683
+ }
684
+
685
+ async function runBatch() {
686
+ const chunks = [];
687
+ for await (const chunk of process.stdin) chunks.push(chunk);
688
+ const cases = JSON.parse(Buffer.concat(chunks).toString('utf8'));
689
+ const results = [];
690
+ for (const testCase of cases) {
691
+ results.push(await runCase(testCase));
692
+ }
693
+ process.stdout.write(JSON.stringify(results), () => {
694
+ process.exit(0);
695
+ });
696
+ }
697
+
698
+ runBatch().then(
699
+ () => {},
700
+ (error) => {
701
+ process.stderr.write(String(error && error.stack ? error.stack : error) + '\\n');
702
+ process.exit(1);
703
+ }
704
+ );
705
+ `;
706
+
707
+ const outDir = join(packageRoot, '.differential');
708
+ const outPath = join(outDir, 'core-supervisor-parity-oracle.mjs');
709
+
710
+ await mkdir(outDir, { recursive: true });
711
+
712
+ await build({
713
+ stdin: {
714
+ contents: driverSource,
715
+ resolveDir: packageRoot,
716
+ sourcefile: 'core-supervisor-parity-driver.ts',
717
+ loader: 'ts',
718
+ },
719
+ bundle: true,
720
+ platform: 'node',
721
+ target: 'node20',
722
+ format: 'esm',
723
+ outfile: outPath,
724
+ minify: false,
725
+ sourcemap: false,
726
+ legalComments: 'none',
727
+ logLevel: 'silent',
728
+ // supervisor.ts pulls the wider commander graph (updateNudge,
729
+ // workerEntryStability, runnerLogger); the same runtime externals as the
730
+ // differential entry build stay external.
731
+ external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
732
+ });
733
+
734
+ process.stdout.write(outPath + '\n');