@linzumi/cli 1.0.272 → 1.0.274
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/impl-res/cloud-supervisor.mjs +69 -69
- package/dist/impl-res/index.js +355 -314
- package/dist/impl-res/mcp-server.mjs +34 -34
- package/dist/impl-ts/cloud-supervisor.mjs +69 -69
- package/dist/impl-ts/index.js +495 -495
- package/dist/impl-ts/mcp-server.mjs +1 -1
- package/dist/mcp-server.mjs +1 -1
- package/package.json +3 -2
- package/scripts/check-package-size-budget.mjs +9 -0
- package/scripts/build-auth-parity-oracle.mjs +0 -709
- package/scripts/build-canonical-codex-transpiler-oracle.mjs +0 -93
- package/scripts/build-config-identity-parity-oracle.mjs +0 -526
- package/scripts/build-core-commander-seams-parity-oracle.mjs +0 -799
- package/scripts/build-core-daemon-parity-oracle.mjs +0 -573
- package/scripts/build-core-dispatch-input-queue-parity-oracle.mjs +0 -225
- package/scripts/build-core-fate-ladder-parity-oracle.mjs +0 -350
- package/scripts/build-core-generation-overlap-parity-oracle.mjs +0 -292
- package/scripts/build-core-integration-parity-oracle.mjs +0 -453
- package/scripts/build-core-lifecycle-guards-parity-oracle.mjs +0 -443
- package/scripts/build-core-lock-parity-oracle.mjs +0 -462
- package/scripts/build-core-reconnect-resume-parity-oracle.mjs +0 -365
- package/scripts/build-core-startup-resume-scan-parity-oracle.mjs +0 -296
- package/scripts/build-core-supervisor-parity-oracle.mjs +0 -781
- package/scripts/build-cross-harness-failover-oracle.mjs +0 -349
- package/scripts/build-editor-parity-oracle.mjs +0 -1525
- package/scripts/build-forwarding-parity-oracle.mjs +0 -1390
- package/scripts/build-harness-claude-parity-oracle.mjs +0 -407
- package/scripts/build-harness-codex-parity-oracle.mjs +0 -479
- package/scripts/build-mcp-parity-oracle.mjs +0 -412
- package/scripts/build-mcp-selector-parity-oracle.mjs +0 -65
- package/scripts/build-onboarding-discovery-parity-oracle.mjs +0 -388
- package/scripts/build-onboarding-flow-parity-oracle.mjs +0 -562
- package/scripts/build-onboarding-gateway-parity-oracle.mjs +0 -313
- package/scripts/build-onboarding-support-parity-oracle.mjs +0 -519
- package/scripts/build-pipeline-parity-oracle.mjs +0 -614
- package/scripts/build-protocol-parity-oracle.mjs +0 -398
- package/scripts/build-queue-parity-oracle.mjs +0 -1012
- package/scripts/build-session-registry-parity-oracle.mjs +0 -582
- package/scripts/build-transport-parity-oracle.mjs +0 -694
- package/scripts/build-tui-parity-oracle.mjs +0 -577
- package/scripts/build-vm-sandbox-parity-oracle.mjs +0 -1281
- package/scripts/build-worker-entry-parity-oracle.mjs +0 -424
- package/scripts/build-worker-spawn-parity-oracle.mjs +0 -823
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
// Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
|
|
2
|
-
// (M3 cluster 10, commander core - the reconnect-resume recovery arm).
|
|
3
|
-
// Relationship: Builds the TS-side PARITY ORACLE for the reconnect-path
|
|
4
|
-
// resume orchestration of the ReScript commander port, the sibling of
|
|
5
|
-
// build-pipeline-parity-oracle.mjs (cluster 9) and
|
|
6
|
-
// build-harness-codex-parity-oracle.mjs (cluster 7). The oracle bundles
|
|
7
|
-
// the REAL runner.ts reconnect-resume exports - the I200 resume decision
|
|
8
|
-
// ladder (resumeCodexThreadForReconnect, transitively
|
|
9
|
-
// unarchiveAndResumeCodexThread, the archived/missing recognizers, and
|
|
10
|
-
// channelSession.ts's withCodexStartRequestTimeout) and the two rehydration
|
|
11
|
-
// fetch legs (fetchThreadRehydrationMessagesForTest /
|
|
12
|
-
// fetchThreadTranscriptForRehydrationForTest, transitively the
|
|
13
|
-
// reconnectContext.ts message parser and the transcriptCompiler.ts
|
|
14
|
-
// canonical-page parser) - behind the cluster 1/2 one-shot BATCH driver (a
|
|
15
|
-
// JSON array of cases on stdin, a JSON array of results on stdout).
|
|
16
|
-
//
|
|
17
|
-
// Scripting: the codex JSON-RPC request seam and the Phoenix push seam are
|
|
18
|
-
// per-case scripted reply queues (result / json-rpc error / rejection /
|
|
19
|
-
// never-settle hang); the rehydration builders are scripted
|
|
20
|
-
// (return/undefined/throw). Timeouts: the REAL withCodexStartRequestTimeout
|
|
21
|
-
// runs inside the bundle, bounded per case through its own
|
|
22
|
-
// LINZUMI_CODEX_START_REQUEST_TIMEOUT_MS knob (set from the case input
|
|
23
|
-
// before each run), so a scripted hang fails with the genuine sentinel
|
|
24
|
-
// bytes after a genuinely elapsed (small) bound. The batch loop holds a
|
|
25
|
-
// keepAlive interval while awaiting - the sentinel timer is unref'd by
|
|
26
|
-
// design and node would otherwise exit mid-hang (the cluster 7 lesson).
|
|
27
|
-
//
|
|
28
|
-
// Byte parity: every request (with params), push (with payload), log
|
|
29
|
-
// event (with payload), builder invocation, and the final
|
|
30
|
-
// outcome/thrown-message ride the returned trace VERBATIM (the TS
|
|
31
|
-
// objects' own key order rides JSON.stringify), so the ReScript side's
|
|
32
|
-
// trace serialization must reproduce field presence AND insertion order
|
|
33
|
-
// exactly.
|
|
34
|
-
//
|
|
35
|
-
// Import-time side effects: runner.ts's graph resolves assets/ relative
|
|
36
|
-
// to the bundle at import time (the hello-project scaffold's inlined
|
|
37
|
-
// logo), so the asset is copied next to the emitted oracle - the
|
|
38
|
-
// build-harness-codex-parity-oracle precedent. No other stubs are needed;
|
|
39
|
-
// the externals list matches the other oracles.
|
|
40
|
-
//
|
|
41
|
-
// SECRETS: the oracle only ever sees the conformance suite's synthetic
|
|
42
|
-
// payloads. The output is a local test artifact (.differential/ is
|
|
43
|
-
// gitignored, never published) and stays unminified for debuggability.
|
|
44
|
-
import { copyFile, mkdir } from 'node:fs/promises';
|
|
45
|
-
import { dirname, join } from 'node:path';
|
|
46
|
-
import { fileURLToPath } from 'node:url';
|
|
47
|
-
import { build } from 'esbuild';
|
|
48
|
-
|
|
49
|
-
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
50
|
-
|
|
51
|
-
const driverSource = `
|
|
52
|
-
import {
|
|
53
|
-
fetchThreadRehydrationMessagesForTest,
|
|
54
|
-
fetchThreadTranscriptForRehydrationForTest,
|
|
55
|
-
resumeCodexThreadForReconnect,
|
|
56
|
-
} from './src/runner';
|
|
57
|
-
import {
|
|
58
|
-
resumeOrRehydrateCodexThread,
|
|
59
|
-
withCodexCompletionSnapshotRequestTimeout,
|
|
60
|
-
} from './src/channelSession';
|
|
61
|
-
|
|
62
|
-
// Scripted codex JSON-RPC request seam: replies are consumed in call
|
|
63
|
-
// order; every call is traced with its params. An exhausted script
|
|
64
|
-
// REJECTS loudly (mirrored byte-for-byte by the ReScript scripted seam).
|
|
65
|
-
function scriptedRequest(script, trace) {
|
|
66
|
-
let index = 0;
|
|
67
|
-
return (method, params) => {
|
|
68
|
-
trace.push({ t: 'request', method, params: params ?? null });
|
|
69
|
-
const step = script[index];
|
|
70
|
-
index += 1;
|
|
71
|
-
if (step === undefined) {
|
|
72
|
-
return Promise.reject(new Error('unscripted request: ' + method));
|
|
73
|
-
}
|
|
74
|
-
if (step.hang === true) {
|
|
75
|
-
return new Promise(() => {});
|
|
76
|
-
}
|
|
77
|
-
if (step.reject !== undefined) {
|
|
78
|
-
return Promise.reject(new Error(step.reject));
|
|
79
|
-
}
|
|
80
|
-
if (step.error !== undefined) {
|
|
81
|
-
return Promise.resolve({ error: step.error });
|
|
82
|
-
}
|
|
83
|
-
return Promise.resolve({ result: step.result ?? {} });
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function runResumeCase(input) {
|
|
88
|
-
// The REAL wrapper resolves its bound per call through this knob.
|
|
89
|
-
process.env.LINZUMI_CODEX_START_REQUEST_TIMEOUT_MS = String(
|
|
90
|
-
input.timeoutMs
|
|
91
|
-
);
|
|
92
|
-
const trace = [];
|
|
93
|
-
const request = scriptedRequest(input.requestScript ?? [], trace);
|
|
94
|
-
const rehydration = {
|
|
95
|
-
forceRehydrate: input.forceRehydrate === true,
|
|
96
|
-
buildRehydrationText: async (resumeFailure) => {
|
|
97
|
-
trace.push({ t: 'buildText', resumeFailure });
|
|
98
|
-
const script = input.textScript ?? {};
|
|
99
|
-
if (script.throw !== undefined) {
|
|
100
|
-
throw new Error(script.throw);
|
|
101
|
-
}
|
|
102
|
-
return script.text;
|
|
103
|
-
},
|
|
104
|
-
buildRehydrationItems:
|
|
105
|
-
input.itemsScript === undefined
|
|
106
|
-
? undefined
|
|
107
|
-
: async (resumeFailure) => {
|
|
108
|
-
trace.push({ t: 'buildItems', resumeFailure });
|
|
109
|
-
const script = input.itemsScript;
|
|
110
|
-
if (script.throw !== undefined) {
|
|
111
|
-
throw new Error(script.throw);
|
|
112
|
-
}
|
|
113
|
-
return script.items;
|
|
114
|
-
},
|
|
115
|
-
log: (event, payload) => trace.push({ t: 'log', event, payload }),
|
|
116
|
-
};
|
|
117
|
-
const outcome = await resumeCodexThreadForReconnect(
|
|
118
|
-
{ request },
|
|
119
|
-
input.codexThreadId,
|
|
120
|
-
input.resumeOverrides ?? {},
|
|
121
|
-
rehydration
|
|
122
|
-
).then(
|
|
123
|
-
(value) => ({ ok: true, value }),
|
|
124
|
-
(error) => ({
|
|
125
|
-
ok: false,
|
|
126
|
-
message: error instanceof Error ? error.message : String(error),
|
|
127
|
-
})
|
|
128
|
-
);
|
|
129
|
-
trace.push({ t: 'outcome', outcome });
|
|
130
|
-
return { trace };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// I200 hosted-agent narrow resume: the same shared core as reconnect, but
|
|
134
|
-
// with the deliberately narrow missing-rollout-only recovery gate and the
|
|
135
|
-
// path-specific loud error prefix/final log used by
|
|
136
|
-
// narrowExistingLinzumiAgentThread.
|
|
137
|
-
async function runNarrowCase(input) {
|
|
138
|
-
process.env.LINZUMI_CODEX_START_REQUEST_TIMEOUT_MS = String(
|
|
139
|
-
input.timeoutMs
|
|
140
|
-
);
|
|
141
|
-
const trace = [];
|
|
142
|
-
const request = scriptedRequest(input.requestScript ?? [], trace);
|
|
143
|
-
const rehydration = {
|
|
144
|
-
forceRehydrate: false,
|
|
145
|
-
buildRehydrationText: async (resumeFailure) => {
|
|
146
|
-
trace.push({ t: 'buildText', resumeFailure });
|
|
147
|
-
return input.textScript?.text;
|
|
148
|
-
},
|
|
149
|
-
buildRehydrationItems:
|
|
150
|
-
input.itemsScript === undefined
|
|
151
|
-
? undefined
|
|
152
|
-
: async (resumeFailure) => {
|
|
153
|
-
trace.push({ t: 'buildItems', resumeFailure });
|
|
154
|
-
return input.itemsScript.items;
|
|
155
|
-
},
|
|
156
|
-
log: (event, payload) => trace.push({ t: 'log', event, payload }),
|
|
157
|
-
};
|
|
158
|
-
const outcome = await resumeOrRehydrateCodexThread({
|
|
159
|
-
codex: { request },
|
|
160
|
-
codexThreadId: input.codexThreadId,
|
|
161
|
-
resumeOverrides: input.resumeOverrides ?? {},
|
|
162
|
-
rebuildWhen: 'missing-rollout-only',
|
|
163
|
-
rehydration,
|
|
164
|
-
}).then(
|
|
165
|
-
(value) => {
|
|
166
|
-
trace.push({
|
|
167
|
-
t: 'log',
|
|
168
|
-
event: 'linzumi.agent_thread_narrowed',
|
|
169
|
-
payload: {
|
|
170
|
-
codex_thread_id: input.codexThreadId,
|
|
171
|
-
approval_policy: 'never',
|
|
172
|
-
sandbox: 'read-only',
|
|
173
|
-
rehydrated: value.mode === 'rehydrated',
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
return { ok: true, value };
|
|
177
|
-
},
|
|
178
|
-
(error) => ({
|
|
179
|
-
ok: false,
|
|
180
|
-
message:
|
|
181
|
-
'failed to narrow existing @linzumi Codex thread: ' +
|
|
182
|
-
(error instanceof Error ? error.message : String(error)),
|
|
183
|
-
})
|
|
184
|
-
);
|
|
185
|
-
trace.push({ t: 'outcome', outcome });
|
|
186
|
-
return { trace };
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Scripted Phoenix push seam shared by the two fetch legs.
|
|
190
|
-
function scriptedPush(script, trace) {
|
|
191
|
-
let index = 0;
|
|
192
|
-
return {
|
|
193
|
-
push: async (topic, event, payload) => {
|
|
194
|
-
trace.push({ t: 'push', topic, event, payload });
|
|
195
|
-
const step = script[index];
|
|
196
|
-
index += 1;
|
|
197
|
-
if (step === undefined) {
|
|
198
|
-
throw new Error('unscripted push: ' + event);
|
|
199
|
-
}
|
|
200
|
-
if (step.throw !== undefined) {
|
|
201
|
-
throw new Error(step.throw);
|
|
202
|
-
}
|
|
203
|
-
return step.reply;
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function fetchTarget(input) {
|
|
209
|
-
return {
|
|
210
|
-
workspace: input.target.workspace ?? undefined,
|
|
211
|
-
channel: input.target.channel ?? undefined,
|
|
212
|
-
threadId: input.target.threadId ?? undefined,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
async function runFetchMessagesCase(input) {
|
|
217
|
-
const trace = [];
|
|
218
|
-
const client = scriptedPush(input.pushScript ?? [], trace);
|
|
219
|
-
const messages = await fetchThreadRehydrationMessagesForTest(
|
|
220
|
-
client,
|
|
221
|
-
input.topic,
|
|
222
|
-
fetchTarget(input),
|
|
223
|
-
(event, payload) => trace.push({ t: 'log', event, payload })
|
|
224
|
-
);
|
|
225
|
-
trace.push({ t: 'messages', messages });
|
|
226
|
-
return { trace };
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
async function runFetchTranscriptCase(input) {
|
|
230
|
-
const trace = [];
|
|
231
|
-
const client = scriptedPush(input.pushScript ?? [], trace);
|
|
232
|
-
const transcript = await fetchThreadTranscriptForRehydrationForTest(
|
|
233
|
-
client,
|
|
234
|
-
input.topic,
|
|
235
|
-
fetchTarget(input),
|
|
236
|
-
(event, payload) => trace.push({ t: 'log', event, payload })
|
|
237
|
-
);
|
|
238
|
-
trace.push({ t: 'transcript', value: transcript ?? null });
|
|
239
|
-
return { trace };
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// The completion-snapshot bound (channelSession.ts
|
|
243
|
-
// withCodexCompletionSnapshotRequestTimeout - the 2026-07-28 impl-res
|
|
244
|
-
// silent-wedge law): the REAL wrapper runs against a scripted request
|
|
245
|
-
// (result / rejection / never-settle hang). When the case carries an
|
|
246
|
-
// explicit boundMs, it is passed as the third argument (the non-positive
|
|
247
|
-
// unbounded guard); otherwise the wrapper resolves its bound through the
|
|
248
|
-
// SAME LINZUMI_CODEX_START_REQUEST_TIMEOUT_MS knob as the start bound
|
|
249
|
-
// (codexCompletionSnapshotRequestTimeoutMs delegates to it), set per case
|
|
250
|
-
// - a hang genuinely waits the (small) bound out.
|
|
251
|
-
async function runSnapshotTimeoutCase(input) {
|
|
252
|
-
process.env.LINZUMI_CODEX_START_REQUEST_TIMEOUT_MS = String(
|
|
253
|
-
input.timeoutMs
|
|
254
|
-
);
|
|
255
|
-
const trace = [];
|
|
256
|
-
const step = input.requestStep ?? {};
|
|
257
|
-
const request =
|
|
258
|
-
step.hang === true
|
|
259
|
-
? new Promise(() => {})
|
|
260
|
-
: step.reject !== undefined
|
|
261
|
-
? Promise.reject(new Error(step.reject))
|
|
262
|
-
: Promise.resolve({ result: step.result ?? {} });
|
|
263
|
-
const outcome = await (input.boundMs === undefined
|
|
264
|
-
? withCodexCompletionSnapshotRequestTimeout(input.method, request)
|
|
265
|
-
: withCodexCompletionSnapshotRequestTimeout(
|
|
266
|
-
input.method,
|
|
267
|
-
request,
|
|
268
|
-
input.boundMs
|
|
269
|
-
)
|
|
270
|
-
).then(
|
|
271
|
-
(value) => ({ ok: true, value }),
|
|
272
|
-
(error) => ({
|
|
273
|
-
ok: false,
|
|
274
|
-
message: error instanceof Error ? error.message : String(error),
|
|
275
|
-
})
|
|
276
|
-
);
|
|
277
|
-
trace.push({ t: 'outcome', outcome });
|
|
278
|
-
return { trace };
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async function runCase(input) {
|
|
282
|
-
switch (input.kind) {
|
|
283
|
-
case 'resumeRun':
|
|
284
|
-
return runResumeCase(input);
|
|
285
|
-
case 'narrowRun':
|
|
286
|
-
return runNarrowCase(input);
|
|
287
|
-
case 'fetchMessagesRun':
|
|
288
|
-
return runFetchMessagesCase(input);
|
|
289
|
-
case 'fetchTranscriptRun':
|
|
290
|
-
return runFetchTranscriptCase(input);
|
|
291
|
-
case 'snapshotTimeoutRun':
|
|
292
|
-
return runSnapshotTimeoutCase(input);
|
|
293
|
-
default:
|
|
294
|
-
return { error: 'unknown case kind ' + String(input.kind) };
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
async function runBatch() {
|
|
299
|
-
const chunks = [];
|
|
300
|
-
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
301
|
-
const cases = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
302
|
-
const results = [];
|
|
303
|
-
for (const testCase of cases) {
|
|
304
|
-
// The sentinel timer is unref'd by design; hold the event loop open
|
|
305
|
-
// while a hang case waits it out or node would exit mid-await.
|
|
306
|
-
const keepAlive = setInterval(() => {}, 1000);
|
|
307
|
-
try {
|
|
308
|
-
results.push(await runCase(testCase));
|
|
309
|
-
} finally {
|
|
310
|
-
clearInterval(keepAlive);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
process.stdout.write(JSON.stringify(results), () => {
|
|
314
|
-
process.exit(0);
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
runBatch().then(
|
|
319
|
-
() => {},
|
|
320
|
-
(error) => {
|
|
321
|
-
process.stderr.write(String(error && error.stack ? error.stack : error) + '\\n');
|
|
322
|
-
process.exit(1);
|
|
323
|
-
}
|
|
324
|
-
);
|
|
325
|
-
`;
|
|
326
|
-
|
|
327
|
-
const outDir = join(packageRoot, '.differential');
|
|
328
|
-
const outPath = join(outDir, 'core-reconnect-resume-parity-oracle.mjs');
|
|
329
|
-
|
|
330
|
-
await mkdir(outDir, { recursive: true });
|
|
331
|
-
// runner.ts's graph resolves assets/ relative to the bundle at import time
|
|
332
|
-
// (the hello-project scaffold's inlined logo), so the asset must sit next
|
|
333
|
-
// to the emitted oracle - the build-harness-codex-parity-oracle precedent.
|
|
334
|
-
await mkdir(join(outDir, 'assets'), { recursive: true });
|
|
335
|
-
await copyFile(
|
|
336
|
-
join(packageRoot, 'src/assets/linzumi-logo.svg'),
|
|
337
|
-
join(outDir, 'assets/linzumi-logo.svg')
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
await build({
|
|
341
|
-
stdin: {
|
|
342
|
-
contents: driverSource,
|
|
343
|
-
resolveDir: packageRoot,
|
|
344
|
-
sourcefile: 'core-reconnect-resume-parity-driver.ts',
|
|
345
|
-
loader: 'ts',
|
|
346
|
-
},
|
|
347
|
-
bundle: true,
|
|
348
|
-
// Spec: plans/2026-09-09-ts-native-account-continuation.md. Match the
|
|
349
|
-
// production/auth-oracle ESM bridge for reachable CJS runtime dependencies;
|
|
350
|
-
// the distinct banner binding cannot collide with bundled createRequire.
|
|
351
|
-
banner: {
|
|
352
|
-
js: "import { createRequire as __coreReconnectResumeOracleCreateRequire } from 'node:module';\nconst require = __coreReconnectResumeOracleCreateRequire(import.meta.url);",
|
|
353
|
-
},
|
|
354
|
-
platform: 'node',
|
|
355
|
-
target: 'node20',
|
|
356
|
-
format: 'esm',
|
|
357
|
-
outfile: outPath,
|
|
358
|
-
minify: false,
|
|
359
|
-
sourcemap: false,
|
|
360
|
-
legalComments: 'none',
|
|
361
|
-
logLevel: 'silent',
|
|
362
|
-
external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
process.stdout.write(outPath + '\n');
|
|
@@ -1,296 +0,0 @@
|
|
|
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
|
-
});
|