@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.
- package/README.md +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/scripts/build-core-commander-seams-parity-oracle.mjs +586 -0
- package/scripts/build-core-daemon-parity-oracle.mjs +573 -0
- package/scripts/build-core-dispatch-input-queue-parity-oracle.mjs +219 -0
- package/scripts/build-core-fate-ladder-parity-oracle.mjs +250 -0
- package/scripts/build-core-generation-overlap-parity-oracle.mjs +288 -0
- package/scripts/build-core-integration-parity-oracle.mjs +361 -0
- package/scripts/build-core-lifecycle-guards-parity-oracle.mjs +443 -0
- package/scripts/build-core-lock-parity-oracle.mjs +455 -0
- package/scripts/build-core-reconnect-resume-parity-oracle.mjs +256 -0
- package/scripts/build-core-startup-resume-scan-parity-oracle.mjs +296 -0
- package/scripts/build-core-supervisor-parity-oracle.mjs +734 -0
- package/scripts/build-pipeline-parity-oracle.mjs +610 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
// Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
|
|
2
|
+
// (M3 cluster 10, commander core).
|
|
3
|
+
// Relationship: Builds the TS-side PARITY ORACLE for the startup
|
|
4
|
+
// resurrection scan of the ReScript commander port, the sibling of
|
|
5
|
+
// build-queue-parity-oracle.mjs (cluster 5). The oracle bundles the REAL
|
|
6
|
+
// TS module (src/startupResumeScan.ts - the 2026-07-11
|
|
7
|
+
// lease-adopted-no-resurrection incident fix; dossier:
|
|
8
|
+
// kandan/server_v2/test/fixtures/prod-failures/
|
|
9
|
+
// runner_restart_lease_adopted_no_resurrection_2026-07-11.md) behind the
|
|
10
|
+
// cluster 1/2 one-shot batch driver: a JSON array of cases on stdin, a
|
|
11
|
+
// JSON array of results on stdout. The ReScript package's
|
|
12
|
+
// CoreStartupResumeScanParityConformance drives the SAME inputs through
|
|
13
|
+
// the ported module and asserts:
|
|
14
|
+
// - constants parity (terminal statuses, age gate, concurrency /
|
|
15
|
+
// stagger / retry-backoff ladders);
|
|
16
|
+
// - fold parity (foldOutboxTurnSignals over raw journal bytes, encoded
|
|
17
|
+
// in map-insertion order so even the fold's internal ordering is
|
|
18
|
+
// pinned);
|
|
19
|
+
// - classification parity (classifyUnfinishedThreadWork matrices);
|
|
20
|
+
// - scripted SCAN RUNS: runStartupResumeScan with every effect
|
|
21
|
+
// (inspect/drain/respawn/publish/seq-in-flight/shutdown/sleep/log)
|
|
22
|
+
// scripted, a virtual clock advanced only by the scripted sleep, and
|
|
23
|
+
// ONE shared trace of effect calls + log events in order - compared
|
|
24
|
+
// byte-for-byte across impls, so the bounded scheduler's interleaving
|
|
25
|
+
// itself (worker pool, shared stagger chain, retry ladders, shutdown
|
|
26
|
+
// aborts) is the contract.
|
|
27
|
+
//
|
|
28
|
+
// Determinism: nothing in a scan case touches the real clock or timers -
|
|
29
|
+
// sleep records the requested delay, advances the virtual clock, and
|
|
30
|
+
// resolves immediately; scripted effect outcomes resolve in order;
|
|
31
|
+
// shutdown flips on a scripted effect-call count. The driver's effect
|
|
32
|
+
// functions return plain resolved/rejected promises (never async
|
|
33
|
+
// functions) so both impls award identical microtask hops.
|
|
34
|
+
//
|
|
35
|
+
// SECRETS: the oracle only ever sees the conformance suite's synthetic
|
|
36
|
+
// fixtures; nothing here logs case contents.
|
|
37
|
+
//
|
|
38
|
+
// The output is a local test artifact (.differential/ is gitignored,
|
|
39
|
+
// never published) and stays unminified for debuggability.
|
|
40
|
+
import { mkdir } from 'node:fs/promises';
|
|
41
|
+
import { dirname, join } from 'node:path';
|
|
42
|
+
import { fileURLToPath } from 'node:url';
|
|
43
|
+
import { build } from 'esbuild';
|
|
44
|
+
|
|
45
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
46
|
+
|
|
47
|
+
const driverSource = `
|
|
48
|
+
import {
|
|
49
|
+
classifyUnfinishedThreadWork,
|
|
50
|
+
defaultResumeSignalMaxAgeMs,
|
|
51
|
+
defaultStartupResumeConcurrency,
|
|
52
|
+
defaultStartupResumeRetryBackoffMs,
|
|
53
|
+
defaultStartupResumeStaggerMs,
|
|
54
|
+
defaultStartupRespawnRetryBackoffMs,
|
|
55
|
+
foldOutboxTurnSignals,
|
|
56
|
+
runStartupResumeScan,
|
|
57
|
+
terminalMessageStateStatuses,
|
|
58
|
+
} from './src/startupResumeScan';
|
|
59
|
+
|
|
60
|
+
// --- Encoding helpers -------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
// Signals encoded in MAP-INSERTION ORDER: the fold's internal ordering is
|
|
63
|
+
// part of the parity contract (classification iterates the map).
|
|
64
|
+
function encodeSignals(map) {
|
|
65
|
+
return Array.from(map.values()).map((signal) => ({
|
|
66
|
+
sourceSeq: signal.sourceSeq,
|
|
67
|
+
sawActivity: signal.sawActivity,
|
|
68
|
+
...(signal.lastMessageStateStatus === undefined
|
|
69
|
+
? {}
|
|
70
|
+
: { lastMessageStateStatus: signal.lastMessageStateStatus }),
|
|
71
|
+
...(signal.newestAtMs === undefined ? {} : { newestAtMs: signal.newestAtMs }),
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function signalMapOf(spec) {
|
|
76
|
+
if (typeof spec.journalRaw === 'string') {
|
|
77
|
+
return foldOutboxTurnSignals(spec.journalRaw);
|
|
78
|
+
}
|
|
79
|
+
const map = new Map();
|
|
80
|
+
for (const signal of spec.signals ?? []) {
|
|
81
|
+
map.set(signal.sourceSeq, {
|
|
82
|
+
sourceSeq: signal.sourceSeq,
|
|
83
|
+
sawActivity: signal.sawActivity ?? false,
|
|
84
|
+
lastMessageStateStatus: signal.lastMessageStateStatus ?? undefined,
|
|
85
|
+
newestAtMs: signal.newestAtMs ?? undefined,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return map;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function inputsOf(spec) {
|
|
92
|
+
return {
|
|
93
|
+
pendingInboundSeqs: spec.pendingInboundSeqs ?? [],
|
|
94
|
+
ackedInboundSeqs: spec.ackedInboundSeqs ?? [],
|
|
95
|
+
inboundHighWaterSeq: spec.inboundHighWaterSeq ?? undefined,
|
|
96
|
+
appliedFloorSeq: spec.appliedFloorSeq ?? undefined,
|
|
97
|
+
outboxTurnSignals: signalMapOf(spec),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function encodeWork(work) {
|
|
102
|
+
return {
|
|
103
|
+
unfinished: work.unfinished,
|
|
104
|
+
seqs: work.seqs.map((entry) => ({ sourceSeq: entry.sourceSeq, shape: entry.shape })),
|
|
105
|
+
hasPendingInbound: work.hasPendingInbound,
|
|
106
|
+
loudTerminalSeqs: [...work.loudTerminalSeqs],
|
|
107
|
+
watermarkGapOnly: work.watermarkGapOnly,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// --- Case handlers ----------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
function handleConstants() {
|
|
114
|
+
return {
|
|
115
|
+
terminalMessageStateStatuses: Array.from(terminalMessageStateStatuses),
|
|
116
|
+
defaultResumeSignalMaxAgeMs,
|
|
117
|
+
defaultStartupResumeConcurrency,
|
|
118
|
+
defaultStartupResumeStaggerMs,
|
|
119
|
+
defaultStartupResumeRetryBackoffMs: [...defaultStartupResumeRetryBackoffMs],
|
|
120
|
+
defaultStartupRespawnRetryBackoffMs: [...defaultStartupRespawnRetryBackoffMs],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function handleFold(testCase) {
|
|
125
|
+
return { signals: encodeSignals(foldOutboxTurnSignals(testCase.raw ?? '')) };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function handleClassify(testCase) {
|
|
129
|
+
return encodeWork(
|
|
130
|
+
classifyUnfinishedThreadWork(inputsOf(testCase.inputs ?? {}), {
|
|
131
|
+
nowMs: testCase.nowMs ?? 0,
|
|
132
|
+
maxSignalAgeMs: testCase.maxSignalAgeMs ?? undefined,
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// One scripted scan run. Every effect resolves from the case script; the
|
|
138
|
+
// shared events array is the trace both impls must reproduce byte for
|
|
139
|
+
// byte (virtual-time stamps included).
|
|
140
|
+
async function handleScan(testCase) {
|
|
141
|
+
const options = testCase.options ?? {};
|
|
142
|
+
const threads = testCase.threads ?? [];
|
|
143
|
+
const events = [];
|
|
144
|
+
let vnow = 0;
|
|
145
|
+
let effectOps = 0;
|
|
146
|
+
const shutdownAfterOps = options.shutdownAfterOps ?? undefined;
|
|
147
|
+
const scripts = new Map(
|
|
148
|
+
threads.map((thread) => [
|
|
149
|
+
thread.threadId,
|
|
150
|
+
{
|
|
151
|
+
drain: [...(thread.drainScript ?? [])],
|
|
152
|
+
respawn: [...(thread.respawnScript ?? [])],
|
|
153
|
+
publish: [...(thread.publishScript ?? [])],
|
|
154
|
+
inFlight: new Set(thread.inFlightSeqs ?? []),
|
|
155
|
+
},
|
|
156
|
+
])
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const summary = await runStartupResumeScan({
|
|
160
|
+
records: threads,
|
|
161
|
+
threadId: (record) => record.threadId,
|
|
162
|
+
inspect: (record) => {
|
|
163
|
+
events.push({ e: 'inspect', vt: vnow, thread: record.threadId });
|
|
164
|
+
const spec = record.inspect ?? {};
|
|
165
|
+
if (typeof spec.throw === 'string') {
|
|
166
|
+
throw new Error(spec.throw);
|
|
167
|
+
}
|
|
168
|
+
return inputsOf(spec);
|
|
169
|
+
},
|
|
170
|
+
resumePendingInbound: (record) => {
|
|
171
|
+
effectOps += 1;
|
|
172
|
+
const step = scripts.get(record.threadId).drain.shift() ?? 'clear';
|
|
173
|
+
if (typeof step === 'object' && step !== null) {
|
|
174
|
+
events.push({
|
|
175
|
+
e: 'drain',
|
|
176
|
+
vt: vnow,
|
|
177
|
+
thread: record.threadId,
|
|
178
|
+
outcome: 'throw:' + step.throw,
|
|
179
|
+
});
|
|
180
|
+
return Promise.reject(new Error(step.throw));
|
|
181
|
+
}
|
|
182
|
+
events.push({ e: 'drain', vt: vnow, thread: record.threadId, outcome: step });
|
|
183
|
+
return Promise.resolve(step);
|
|
184
|
+
},
|
|
185
|
+
respawnWorker: (record) => {
|
|
186
|
+
effectOps += 1;
|
|
187
|
+
const step = scripts.get(record.threadId).respawn.shift() ?? true;
|
|
188
|
+
if (typeof step === 'object' && step !== null) {
|
|
189
|
+
events.push({
|
|
190
|
+
e: 'respawn',
|
|
191
|
+
vt: vnow,
|
|
192
|
+
thread: record.threadId,
|
|
193
|
+
outcome: 'throw:' + step.throw,
|
|
194
|
+
});
|
|
195
|
+
return Promise.reject(new Error(step.throw));
|
|
196
|
+
}
|
|
197
|
+
events.push({ e: 'respawn', vt: vnow, thread: record.threadId, outcome: step });
|
|
198
|
+
return Promise.resolve(step);
|
|
199
|
+
},
|
|
200
|
+
seqInFlight: (record, sourceSeq) => scripts.get(record.threadId).inFlight.has(sourceSeq),
|
|
201
|
+
publishInterruptedTurnState: (record, sourceSeq, shape) => {
|
|
202
|
+
effectOps += 1;
|
|
203
|
+
const step = scripts.get(record.threadId).publish.shift() ?? 'ok';
|
|
204
|
+
if (typeof step === 'object' && step !== null) {
|
|
205
|
+
events.push({
|
|
206
|
+
e: 'publish',
|
|
207
|
+
vt: vnow,
|
|
208
|
+
thread: record.threadId,
|
|
209
|
+
seq: sourceSeq,
|
|
210
|
+
shape,
|
|
211
|
+
outcome: 'throw:' + step.throw,
|
|
212
|
+
});
|
|
213
|
+
return Promise.reject(new Error(step.throw));
|
|
214
|
+
}
|
|
215
|
+
events.push({
|
|
216
|
+
e: 'publish',
|
|
217
|
+
vt: vnow,
|
|
218
|
+
thread: record.threadId,
|
|
219
|
+
seq: sourceSeq,
|
|
220
|
+
shape,
|
|
221
|
+
outcome: step,
|
|
222
|
+
});
|
|
223
|
+
return Promise.resolve(undefined);
|
|
224
|
+
},
|
|
225
|
+
shuttingDown: () => shutdownAfterOps !== undefined && effectOps >= shutdownAfterOps,
|
|
226
|
+
log: (event, fields) => {
|
|
227
|
+
events.push({ e: 'log', vt: vnow, event, fields });
|
|
228
|
+
},
|
|
229
|
+
nowMs: options.nowMs ?? 0,
|
|
230
|
+
maxSignalAgeMs: options.maxSignalAgeMs ?? undefined,
|
|
231
|
+
concurrency: options.concurrency ?? undefined,
|
|
232
|
+
staggerMs: options.staggerMs ?? undefined,
|
|
233
|
+
retryBackoffMs: options.retryBackoffMs ?? undefined,
|
|
234
|
+
respawnRetryBackoffMs: options.respawnRetryBackoffMs ?? undefined,
|
|
235
|
+
sleep: (ms) => {
|
|
236
|
+
effectOps += 1;
|
|
237
|
+
events.push({ e: 'sleep', vt: vnow, ms });
|
|
238
|
+
vnow += ms;
|
|
239
|
+
return Promise.resolve(undefined);
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return { summary, events };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function handle(testCase) {
|
|
247
|
+
switch (testCase.op) {
|
|
248
|
+
case 'constants':
|
|
249
|
+
return handleConstants();
|
|
250
|
+
case 'fold':
|
|
251
|
+
return handleFold(testCase);
|
|
252
|
+
case 'classify':
|
|
253
|
+
return handleClassify(testCase);
|
|
254
|
+
case 'scan':
|
|
255
|
+
return await handleScan(testCase);
|
|
256
|
+
default:
|
|
257
|
+
return { threw: true, message: 'unknown op ' + String(testCase.op) };
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let stdin = '';
|
|
262
|
+
process.stdin.setEncoding('utf8');
|
|
263
|
+
for await (const chunk of process.stdin) {
|
|
264
|
+
stdin += chunk;
|
|
265
|
+
}
|
|
266
|
+
const cases = JSON.parse(stdin);
|
|
267
|
+
const results = [];
|
|
268
|
+
for (const testCase of cases) {
|
|
269
|
+
results.push(await handle(testCase));
|
|
270
|
+
}
|
|
271
|
+
// Exit after stdout is fully flushed (the cluster 5 lesson: a bare
|
|
272
|
+
// process.exit(0) truncates large result arrays mid-pipe).
|
|
273
|
+
process.stdout.write(JSON.stringify(results), () => {
|
|
274
|
+
process.exit(0);
|
|
275
|
+
});
|
|
276
|
+
`;
|
|
277
|
+
|
|
278
|
+
await mkdir(join(packageRoot, '.differential'), { recursive: true });
|
|
279
|
+
|
|
280
|
+
await build({
|
|
281
|
+
stdin: {
|
|
282
|
+
contents: driverSource,
|
|
283
|
+
resolveDir: packageRoot,
|
|
284
|
+
sourcefile: 'core-startup-resume-scan-parity-driver.ts',
|
|
285
|
+
loader: 'ts',
|
|
286
|
+
},
|
|
287
|
+
bundle: true,
|
|
288
|
+
platform: 'node',
|
|
289
|
+
target: 'node20',
|
|
290
|
+
format: 'esm',
|
|
291
|
+
outfile: join(packageRoot, '.differential/core-startup-resume-scan-parity-oracle.mjs'),
|
|
292
|
+
minify: false,
|
|
293
|
+
sourcemap: false,
|
|
294
|
+
legalComments: 'none',
|
|
295
|
+
external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
|
|
296
|
+
});
|