@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.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/dist/impl-res/cloud-supervisor.mjs +69 -69
  3. package/dist/impl-res/index.js +355 -314
  4. package/dist/impl-res/mcp-server.mjs +34 -34
  5. package/dist/impl-ts/cloud-supervisor.mjs +69 -69
  6. package/dist/impl-ts/index.js +495 -495
  7. package/dist/impl-ts/mcp-server.mjs +1 -1
  8. package/dist/mcp-server.mjs +1 -1
  9. package/package.json +3 -2
  10. package/scripts/check-package-size-budget.mjs +9 -0
  11. package/scripts/build-auth-parity-oracle.mjs +0 -709
  12. package/scripts/build-canonical-codex-transpiler-oracle.mjs +0 -93
  13. package/scripts/build-config-identity-parity-oracle.mjs +0 -526
  14. package/scripts/build-core-commander-seams-parity-oracle.mjs +0 -799
  15. package/scripts/build-core-daemon-parity-oracle.mjs +0 -573
  16. package/scripts/build-core-dispatch-input-queue-parity-oracle.mjs +0 -225
  17. package/scripts/build-core-fate-ladder-parity-oracle.mjs +0 -350
  18. package/scripts/build-core-generation-overlap-parity-oracle.mjs +0 -292
  19. package/scripts/build-core-integration-parity-oracle.mjs +0 -453
  20. package/scripts/build-core-lifecycle-guards-parity-oracle.mjs +0 -443
  21. package/scripts/build-core-lock-parity-oracle.mjs +0 -462
  22. package/scripts/build-core-reconnect-resume-parity-oracle.mjs +0 -365
  23. package/scripts/build-core-startup-resume-scan-parity-oracle.mjs +0 -296
  24. package/scripts/build-core-supervisor-parity-oracle.mjs +0 -781
  25. package/scripts/build-cross-harness-failover-oracle.mjs +0 -349
  26. package/scripts/build-editor-parity-oracle.mjs +0 -1525
  27. package/scripts/build-forwarding-parity-oracle.mjs +0 -1390
  28. package/scripts/build-harness-claude-parity-oracle.mjs +0 -407
  29. package/scripts/build-harness-codex-parity-oracle.mjs +0 -479
  30. package/scripts/build-mcp-parity-oracle.mjs +0 -412
  31. package/scripts/build-mcp-selector-parity-oracle.mjs +0 -65
  32. package/scripts/build-onboarding-discovery-parity-oracle.mjs +0 -388
  33. package/scripts/build-onboarding-flow-parity-oracle.mjs +0 -562
  34. package/scripts/build-onboarding-gateway-parity-oracle.mjs +0 -313
  35. package/scripts/build-onboarding-support-parity-oracle.mjs +0 -519
  36. package/scripts/build-pipeline-parity-oracle.mjs +0 -614
  37. package/scripts/build-protocol-parity-oracle.mjs +0 -398
  38. package/scripts/build-queue-parity-oracle.mjs +0 -1012
  39. package/scripts/build-session-registry-parity-oracle.mjs +0 -582
  40. package/scripts/build-transport-parity-oracle.mjs +0 -694
  41. package/scripts/build-tui-parity-oracle.mjs +0 -577
  42. package/scripts/build-vm-sandbox-parity-oracle.mjs +0 -1281
  43. package/scripts/build-worker-entry-parity-oracle.mjs +0 -424
  44. package/scripts/build-worker-spawn-parity-oracle.mjs +0 -823
@@ -1,614 +0,0 @@
1
- // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
2
- // (M3 cluster 9, pipeline).
3
- // Relationship: Builds the TS-side PARITY ORACLE for the pipeline cluster
4
- // of the ReScript commander port, the sibling of
5
- // build-queue-parity-oracle.mjs (cluster 5) and
6
- // build-harness-codex-parity-oracle.mjs (cluster 7). The oracle bundles
7
- // the REAL TS pipeline surface - the pure transition core
8
- // (src/pipeline/transition.ts + contracts + itemProjection, transitively
9
- // the item-output rendering slice), the thread event-loop driver
10
- // (threadEventLoop.ts), the stats reporter + turn-stall detector
11
- // (statsReporter.ts), and the two recovery watchdog primitives
12
- // (claudeCodeTurnStallWatchdog.ts / claudeCodeDispatchLivenessWatchdog.ts)
13
- // - behind the cluster 1/2 one-shot BATCH driver (a JSON array of cases on
14
- // stdin, a JSON array of results on stdout).
15
- //
16
- // Byte parity: transition effects are returned VERBATIM (the TS effect
17
- // objects' own key order rides JSON.stringify), so the ReScript side's
18
- // effectToJson must reproduce field presence AND insertion order exactly.
19
- // Determinism: clocks are injected per case (now()/scripted advance ops),
20
- // the driver's sweep interval is disabled (0) in loop cases, and watchdog
21
- // timers ride a scripted timer seam fired in scheduling order - nothing
22
- // here reads wall time.
23
- //
24
- // SECRETS: the oracle only ever sees the conformance suite's synthetic
25
- // payloads. The output is a local test artifact (.differential/ is
26
- // gitignored, never published) and stays unminified for debuggability.
27
- import { mkdir } from 'node:fs/promises';
28
- import { dirname, join } from 'node:path';
29
- import { fileURLToPath } from 'node:url';
30
- import { build } from 'esbuild';
31
-
32
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
33
-
34
- const driverSource = `
35
- import {
36
- classifyRejectionRetry,
37
- classifyStallWindowEvidence,
38
- createInitialLoopState,
39
- idleStreamStallDisposition,
40
- isUpstreamTerminal4xxHttpStatus,
41
- maxConsecutiveEmptyTurns,
42
- maxEmptyTurnAutoRetries,
43
- maxIsolatedRejectionRetries,
44
- maxReasoningStepsWithoutProgress,
45
- maxTerminalTurnIds,
46
- agentNarrationOnlyCompletionReason,
47
- agentNarrationOnlyEmptyTurnCause,
48
- autoRetriesBurnedSuffix,
49
- completedWithoutAssistantOutputReason,
50
- costCapAutoRetrySuppressedSuffix,
51
- emptyTurnLoopGuardReason,
52
- linzumiAgentReplyToolName,
53
- midStreamResumeIncompleteSuffix,
54
- midStreamResumeRateLimitSuppressedSuffix,
55
- midStreamResumeStalledAgainSuffix,
56
- reasoningLoopBreakerReason,
57
- stallWindowEvidenceSignalClasses,
58
- stallWindowRateLimited,
59
- transition,
60
- turnMappingFailedMethod,
61
- turnMappingReadyMethod,
62
- unsupportedCodexToolCallReasonPrefix,
63
- upstreamHttpStatusRetryClass,
64
- upstreamTurnErrorSummary,
65
- } from './src/pipeline/transition';
66
- import { pipelineItemKey, outboxEntryKinds } from './src/pipeline/contracts';
67
- import {
68
- explicitNotificationItemId,
69
- notificationTurnId,
70
- pipelineClientMessageId,
71
- projectSnapshotItems,
72
- } from './src/pipeline/itemProjection';
73
- import {
74
- createThreadEventLoop,
75
- defaultBufferedTurnMaxAgeMs,
76
- defaultBufferedTurnMaxEvents,
77
- defaultBufferedTurnSweepIntervalMs,
78
- } from './src/pipeline/threadEventLoop';
79
- import {
80
- createPipelineStatsReporter,
81
- defaultPipelineStatsIntervalMs,
82
- defaultPipelineTurnStalledThresholdMs,
83
- openItemTurnStalledThresholdMultiplier,
84
- } from './src/pipeline/statsReporter';
85
- import {
86
- createClaudeCodeTurnStallWatchdog,
87
- defaultClaudeCodeTurnStallThresholdMs,
88
- } from './src/claudeCodeTurnStallWatchdog';
89
- import {
90
- armClaudeCodeDispatchLivenessWatchdog,
91
- defaultClaudeCodeDispatchLivenessWindowMs,
92
- } from './src/claudeCodeDispatchLivenessWatchdog';
93
-
94
- // Scripted deps table shared by transition + loop runs. sourceSeq
95
- // mappings, burned-retry counts, resume attempts, and ladder receipts are
96
- // mutated by ops so terminal-time reads see the scripted values.
97
- function scriptedDeps(caseInput, tables) {
98
- return {
99
- threadKey: caseInput.threadKey ?? 'thread-parity',
100
- instanceId: caseInput.instanceId ?? 'instance-parity',
101
- sourceSeqForTurn: (turnId) => tables.turnSeqs.get(turnId),
102
- autoRetryAttemptsForSeq: (seq) => tables.retryAttempts.get(seq) ?? 0,
103
- midStreamResumeAttemptAtMsForSeq: (seq) => tables.resumeAttempts.get(seq),
104
- ladderHistoryForSeq: (seq, fate) => tables.ladders.get(seq + ':' + fate),
105
- linzumiAgentSession: caseInput.linzumiAgentSession === true,
106
- };
107
- }
108
-
109
- function applyTableOp(tables, op) {
110
- if (op.op === 'mapTurn') tables.turnSeqs.set(op.turnId, op.seq);
111
- if (op.op === 'unmapTurn') tables.turnSeqs.delete(op.turnId);
112
- if (op.op === 'retryAttempts') tables.retryAttempts.set(op.seq, op.attempts);
113
- if (op.op === 'resumeAttemptAt') tables.resumeAttempts.set(op.seq, op.atMs);
114
- if (op.op === 'ladder') tables.ladders.set(op.seq + ':' + op.fate, op.ladder);
115
- }
116
-
117
- function newTables() {
118
- return {
119
- turnSeqs: new Map(),
120
- retryAttempts: new Map(),
121
- resumeAttempts: new Map(),
122
- ladders: new Map(),
123
- };
124
- }
125
-
126
- function runTransitionCase(caseInput) {
127
- const tables = newTables();
128
- const state = createInitialLoopState();
129
- const deps = scriptedDeps(caseInput, tables);
130
- const steps = [];
131
- for (const op of caseInput.ops ?? []) {
132
- if (op.op === 'event') {
133
- steps.push(transition(state, op.event, deps));
134
- } else {
135
- applyTableOp(tables, op);
136
- }
137
- }
138
- return { steps };
139
- }
140
-
141
- function runLoopCase(caseInput) {
142
- const tables = newTables();
143
- let nowMs = caseInput.startMs ?? 0;
144
- const trace = [];
145
- const outbox = {
146
- enqueue: (entry) => {
147
- trace.push({
148
- t: 'enqueue',
149
- kind: entry.kind,
150
- data: entry.data,
151
- coalesceKey: entry.coalesceKey ?? null,
152
- resolution: entry.resolution,
153
- });
154
- return 0;
155
- },
156
- flush: async () => {
157
- if (caseInput.flushFails === true) {
158
- throw new Error('scripted flush failure');
159
- }
160
- trace.push({ t: 'flushed' });
161
- },
162
- pause: () => {},
163
- resume: () => {},
164
- metrics: () => {
165
- throw new Error('not used');
166
- },
167
- close: async () => {},
168
- };
169
- const loop = createThreadEventLoop({
170
- threadKey: caseInput.threadKey ?? 'thread-parity',
171
- outbox,
172
- sourceSeqForTurn: (turnId) => tables.turnSeqs.get(turnId),
173
- autoRetryAttemptsForSeq: (seq) => tables.retryAttempts.get(seq) ?? 0,
174
- midStreamResumeAttemptAtMsForSeq: (seq) => tables.resumeAttempts.get(seq),
175
- ladderHistoryForSeq: (seq, fate) => tables.ladders.get(seq + ':' + fate),
176
- onTurnTerminal: (turnId, outcome, reason, retryableEmptyTurn, autoResume, fate) => {
177
- trace.push({
178
- t: 'terminal',
179
- turnId,
180
- outcome,
181
- reason: reason ?? null,
182
- retryableEmptyTurn: retryableEmptyTurn === true,
183
- autoResumeMidStreamStall: autoResume === true,
184
- fate: fate ?? null,
185
- });
186
- },
187
- requestSnapshot: (turnId) => {
188
- trace.push({ t: 'requestSnapshot', turnId });
189
- },
190
- instanceId: caseInput.instanceId ?? 'instance-parity',
191
- log: (event, fields) => {
192
- trace.push({ t: 'log', event, fields });
193
- },
194
- linzumiAgentSession: caseInput.linzumiAgentSession === true,
195
- now: () => nowMs,
196
- bufferedTurnMaxAgeMs: caseInput.bufferedTurnMaxAgeMs,
197
- bufferedTurnMaxEvents: caseInput.bufferedTurnMaxEvents,
198
- // Determinism: the quiet-period sweep timer is disabled; the age cap
199
- // still applies on every processed event.
200
- bufferedTurnSweepIntervalMs: 0,
201
- });
202
- const metricsJson = () => {
203
- const metrics = loop.metrics();
204
- return {
205
- queueDepth: metrics.queueDepth,
206
- phase: metrics.phase,
207
- activeTurns: metrics.activeTurns.map((turn) => ({
208
- turnId: turn.turnId,
209
- sourceSeq: turn.sourceSeq,
210
- startedAtMs: turn.startedAtMs,
211
- lastActivityAtMs: turn.lastActivityAtMs ?? null,
212
- lastActivityKind: turn.lastActivityKind ?? null,
213
- openItems: (turn.openItems ?? []).map((item) => ({
214
- kind: item.kind,
215
- startedAtMs: item.startedAtMs,
216
- })),
217
- })),
218
- bufferedTurns: metrics.bufferedTurns.map((turn) => ({
219
- turnId: turn.turnId,
220
- bufferedEventCount: turn.bufferedEventCount,
221
- firstBufferedAtMs: turn.firstBufferedAtMs,
222
- lastActivityAtMs: turn.lastActivityAtMs ?? null,
223
- lastActivityKind: turn.lastActivityKind ?? null,
224
- openItems: (turn.openItems ?? []).map((item) => ({
225
- kind: item.kind,
226
- startedAtMs: item.startedAtMs,
227
- })),
228
- })),
229
- };
230
- };
231
- const run = async () => {
232
- for (const op of caseInput.ops ?? []) {
233
- if (op.op === 'submit') loop.submit(op.event);
234
- else if (op.op === 'advance') nowMs = op.toMs;
235
- else if (op.op === 'metrics') trace.push({ t: 'metrics', value: metricsJson() });
236
- else if (op.op === 'noteActivity') loop.noteTurnActivity(op.turnId, op.kind);
237
- else if (op.op === 'drainAndClose') {
238
- await loop.drainAndClose(op.timeoutMs);
239
- trace.push({ t: 'drained' });
240
- } else applyTableOp(tables, op);
241
- }
242
- };
243
- return run().then(() => ({ trace }));
244
- }
245
-
246
- function runStatsCase(caseInput) {
247
- let nowMs = caseInput.startMs ?? 0;
248
- let outboxMetrics = caseInput.outbox;
249
- let loopMetrics = caseInput.loop;
250
- let waits = caseInput.waits ?? [];
251
- const trace = [];
252
- const reporter = createPipelineStatsReporter({
253
- threadKey: caseInput.threadKey ?? 'thread-parity',
254
- outboxMetrics: () => ({
255
- ...outboxMetrics,
256
- oldestEntryAgeMs: outboxMetrics.oldestEntryAgeMs ?? undefined,
257
- pushLatency: outboxMetrics.pushLatency ?? undefined,
258
- }),
259
- loopMetrics: () => ({
260
- queueDepth: loopMetrics.queueDepth,
261
- phase: loopMetrics.phase,
262
- activeTurns: loopMetrics.activeTurns.map((turn) => ({
263
- ...turn,
264
- lastActivityAtMs: turn.lastActivityAtMs ?? undefined,
265
- lastActivityKind: turn.lastActivityKind ?? undefined,
266
- openItems: turn.openItems ?? [],
267
- })),
268
- bufferedTurns: loopMetrics.bufferedTurns.map((turn) => ({
269
- ...turn,
270
- lastActivityAtMs: turn.lastActivityAtMs ?? undefined,
271
- lastActivityKind: turn.lastActivityKind ?? undefined,
272
- openItems: turn.openItems ?? [],
273
- })),
274
- }),
275
- log: (event, fields) => trace.push({ t: 'log', event, fields }),
276
- intervalMs: 0,
277
- turnStalledThresholdMs: caseInput.thresholdMs,
278
- turnWaitStates: () => waits.map((wait) => ({ turnId: wait.turnId, kind: wait.kind })),
279
- now: () => nowMs,
280
- });
281
- for (const op of caseInput.ops ?? []) {
282
- if (op.op === 'set') {
283
- if (op.outbox !== undefined) outboxMetrics = op.outbox;
284
- if (op.loop !== undefined) loopMetrics = op.loop;
285
- if (op.waits !== undefined) waits = op.waits;
286
- } else if (op.op === 'sample') {
287
- nowMs = op.nowMs ?? nowMs;
288
- reporter.sample();
289
- } else if (op.op === 'stop') {
290
- reporter.stop();
291
- }
292
- }
293
- return { trace };
294
- }
295
-
296
- // Scripted timer seam shared by the watchdog runs: timers fire in
297
- // scheduling order once the scripted clock passes their due instant.
298
- function scriptedTimers(clock, trace, label) {
299
- let nextId = 1;
300
- const pending = [];
301
- return {
302
- setTimer: (callback, delayMs) => {
303
- const id = nextId;
304
- nextId += 1;
305
- trace.push({ t: label + '.set', id, delayMs, dueAtMs: clock.nowMs + delayMs });
306
- pending.push({ id, dueAtMs: clock.nowMs + delayMs, callback });
307
- return id;
308
- },
309
- clearTimer: (handle) => {
310
- const index = pending.findIndex((timer) => timer.id === handle);
311
- if (index >= 0) {
312
- trace.push({ t: label + '.clear', id: pending[index].id });
313
- pending.splice(index, 1);
314
- }
315
- },
316
- fireDue: () => {
317
- let fired = true;
318
- while (fired) {
319
- fired = false;
320
- const index = pending.findIndex((timer) => timer.dueAtMs <= clock.nowMs);
321
- if (index >= 0) {
322
- const timer = pending.splice(index, 1)[0];
323
- trace.push({ t: label + '.fire', id: timer.id });
324
- timer.callback();
325
- fired = true;
326
- }
327
- }
328
- },
329
- };
330
- }
331
-
332
- function runTurnStallWatchdogCase(caseInput) {
333
- const clock = { nowMs: caseInput.startMs ?? 0 };
334
- const trace = [];
335
- const timers = scriptedTimers(clock, trace, 'timer');
336
- let turnActive = caseInput.turnActive === true;
337
- let watchdog;
338
- const outcome = (() => {
339
- try {
340
- watchdog = createClaudeCodeTurnStallWatchdog({
341
- thresholdMs: caseInput.thresholdMs,
342
- sdkRequestDeadlineMs: caseInput.sdkRequestDeadlineMs ?? undefined,
343
- isTurnActive: () => turnActive,
344
- onStall: (info) => trace.push({ t: 'stall', ...info }),
345
- now: () => clock.nowMs,
346
- setTimer: timers.setTimer,
347
- clearTimer: timers.clearTimer,
348
- });
349
- return { ok: true };
350
- } catch (error) {
351
- return { ok: false, message: error instanceof Error ? error.message : String(error) };
352
- }
353
- })();
354
- if (outcome.ok) {
355
- for (const op of caseInput.ops ?? []) {
356
- if (op.op === 'advance') {
357
- clock.nowMs = op.toMs;
358
- timers.fireDue();
359
- } else if (op.op === 'transcriptVisible') watchdog.kick({ kind: 'transcript_visible' });
360
- else if (op.op === 'sdkBookkeeping') watchdog.kick({ kind: 'sdk_bookkeeping' });
361
- else if (op.op === 'sdkRequestStarted') watchdog.kick({ kind: 'sdk_request_started' });
362
- else if (op.op === 'sdkRequestFinished') watchdog.kick({ kind: 'sdk_request_finished' });
363
- else if (op.op === 'stop') watchdog.stop();
364
- else if (op.op === 'setActive') turnActive = op.active === true;
365
- }
366
- }
367
- return { outcome, trace };
368
- }
369
-
370
- function runDispatchWatchdogCase(caseInput) {
371
- const clock = { nowMs: caseInput.startMs ?? 0 };
372
- const trace = [];
373
- const timers = scriptedTimers(clock, trace, 'timer');
374
- let delivered = caseInput.delivered === true;
375
- let sessionClosed = caseInput.sessionClosed === true;
376
- let lastActivityMs = caseInput.lastActivityMs ?? 0;
377
- let pendingBlocking = caseInput.pendingBlocking === true;
378
- let watchdog;
379
- const outcome = (() => {
380
- try {
381
- watchdog = armClaudeCodeDispatchLivenessWatchdog({
382
- windowMs: caseInput.windowMs,
383
- isDelivered: () => delivered,
384
- isSessionClosed: () => sessionClosed,
385
- lastSdkActivityMs: () => lastActivityMs,
386
- hasPendingBlockingRequest: () => pendingBlocking,
387
- onWedged: (info) => trace.push({ t: 'wedged', waitedMs: info.waitedMs, cause: info.cause }),
388
- now: () => clock.nowMs,
389
- setTimer: timers.setTimer,
390
- clearTimer: timers.clearTimer,
391
- });
392
- return { ok: true };
393
- } catch (error) {
394
- return { ok: false, message: error instanceof Error ? error.message : String(error) };
395
- }
396
- })();
397
- if (outcome.ok) {
398
- for (const op of caseInput.ops ?? []) {
399
- if (op.op === 'advance') {
400
- clock.nowMs = op.toMs;
401
- timers.fireDue();
402
- } else if (op.op === 'setDelivered') delivered = op.value === true;
403
- else if (op.op === 'setSessionClosed') sessionClosed = op.value === true;
404
- else if (op.op === 'setActivity') lastActivityMs = op.atMs;
405
- else if (op.op === 'setPendingBlocking') pendingBlocking = op.value === true;
406
- else if (op.op === 'stop') watchdog.stop();
407
- }
408
- }
409
- return { outcome, trace };
410
- }
411
-
412
- async function runCase(input) {
413
- switch (input.kind) {
414
- case 'constants':
415
- return {
416
- outboxEntryKinds,
417
- turnMappingReadyMethod,
418
- turnMappingFailedMethod,
419
- maxTerminalTurnIds,
420
- maxEmptyTurnAutoRetries,
421
- maxConsecutiveEmptyTurns,
422
- maxReasoningStepsWithoutProgress,
423
- maxIsolatedRejectionRetries,
424
- completedWithoutAssistantOutputReason,
425
- linzumiAgentReplyToolName,
426
- agentNarrationOnlyCompletionReason,
427
- agentNarrationOnlyEmptyTurnCause,
428
- emptyTurnLoopGuardReason,
429
- unsupportedCodexToolCallReasonPrefix,
430
- midStreamResumeRateLimitSuppressedSuffix,
431
- costCapAutoRetrySuppressedSuffix,
432
- stallWindowEvidenceSignalClasses,
433
- defaultBufferedTurnMaxAgeMs,
434
- defaultBufferedTurnMaxEvents,
435
- defaultBufferedTurnSweepIntervalMs,
436
- defaultPipelineStatsIntervalMs,
437
- defaultPipelineTurnStalledThresholdMs,
438
- openItemTurnStalledThresholdMultiplier,
439
- defaultClaudeCodeTurnStallThresholdMs,
440
- defaultClaudeCodeDispatchLivenessWindowMs,
441
- };
442
- case 'reasoningLoopBreakerReason':
443
- return reasoningLoopBreakerReason(input.steps);
444
- case 'autoRetriesBurnedSuffix':
445
- return autoRetriesBurnedSuffix(input.attempts);
446
- case 'midStreamResumeStalledAgainSuffix':
447
- return midStreamResumeStalledAgainSuffix(input.attemptAtMs);
448
- case 'midStreamResumeIncompleteSuffix':
449
- return midStreamResumeIncompleteSuffix(input.attemptAtMs);
450
- case 'upstreamHttpStatusRetryClass':
451
- return upstreamHttpStatusRetryClass(input.status);
452
- case 'isUpstreamTerminal4xxHttpStatus':
453
- return isUpstreamTerminal4xxHttpStatus(input.status ?? undefined);
454
- case 'classifyStallWindowEvidence':
455
- return classifyStallWindowEvidence({
456
- lastUpstreamErrorReason: input.turn.lastUpstreamErrorReason ?? undefined,
457
- lastErrorDiagnosticText: input.turn.lastErrorDiagnosticText ?? undefined,
458
- lastUpstreamErrorHttpStatus: input.turn.lastUpstreamErrorHttpStatus ?? undefined,
459
- upstreamRejectedSeen: input.turn.upstreamRejectedSeen === true,
460
- providerOutageFlaggedSeen: input.turn.providerOutageFlaggedSeen === true,
461
- toolFatalSeen: input.turn.toolFatalSeen === true,
462
- errorNotificationCount: input.turn.errorNotificationCount ?? 0,
463
- unattributedErrorNotificationCount:
464
- input.turn.unattributedErrorNotificationCount ?? 0,
465
- modelInteractionSeen: input.turn.modelInteractionSeen === true,
466
- });
467
- case 'stallWindowRateLimited':
468
- return stallWindowRateLimited({
469
- lastUpstreamErrorReason: input.turn.lastUpstreamErrorReason ?? undefined,
470
- lastErrorDiagnosticText: input.turn.lastErrorDiagnosticText ?? undefined,
471
- lastUpstreamErrorHttpStatus: input.turn.lastUpstreamErrorHttpStatus ?? undefined,
472
- upstreamRejectedSeen: input.turn.upstreamRejectedSeen === true,
473
- providerOutageFlaggedSeen: input.turn.providerOutageFlaggedSeen === true,
474
- toolFatalSeen: input.turn.toolFatalSeen === true,
475
- errorNotificationCount: input.turn.errorNotificationCount ?? 0,
476
- unattributedErrorNotificationCount:
477
- input.turn.unattributedErrorNotificationCount ?? 0,
478
- modelInteractionSeen: input.turn.modelInteractionSeen === true,
479
- });
480
- case 'idleStreamStallDisposition': {
481
- const disposition = idleStreamStallDisposition(
482
- input.method,
483
- input.params,
484
- {
485
- lastUpstreamErrorReason: input.turn.lastUpstreamErrorReason ?? undefined,
486
- lastErrorDiagnosticText: input.turn.lastErrorDiagnosticText ?? undefined,
487
- lastUpstreamErrorHttpStatus: input.turn.lastUpstreamErrorHttpStatus ?? undefined,
488
- upstreamRejectedSeen: input.turn.upstreamRejectedSeen === true,
489
- providerOutageFlaggedSeen: input.turn.providerOutageFlaggedSeen === true,
490
- toolFatalSeen: input.turn.toolFatalSeen === true,
491
- errorNotificationCount: input.turn.errorNotificationCount ?? 0,
492
- unattributedErrorNotificationCount:
493
- input.turn.unattributedErrorNotificationCount ?? 0,
494
- modelInteractionSeen: input.turn.modelInteractionSeen === true,
495
- },
496
- {
497
- costCap402Seen: input.session.costCap402Seen === true,
498
- midStreamResumeAttemptAtMs: input.session.midStreamResumeAttemptAtMs ?? undefined,
499
- }
500
- );
501
- return {
502
- autoRetryPreFirstByteStall: disposition.autoRetryPreFirstByteStall,
503
- messageStateRetryable: disposition.messageStateRetryable,
504
- costCapAutoRetrySuppressed: disposition.costCapAutoRetrySuppressed,
505
- messageStateFate: disposition.messageStateFate ?? null,
506
- autoResumeMidStreamStall: disposition.autoResumeMidStreamStall,
507
- midStreamResumeRateLimitSuppressed: disposition.midStreamResumeRateLimitSuppressed,
508
- midStreamResumeAttemptBurnedAtMs:
509
- disposition.midStreamResumeAttemptBurnedAtMs ?? null,
510
- };
511
- }
512
- case 'classifyRejectionRetry': {
513
- const disposition = classifyRejectionRetry({
514
- providerOutageFlagged: input.providerOutageFlagged === true,
515
- priorConsecutiveIsolatedRejections: input.priorConsecutiveIsolatedRejections,
516
- stormDetail: input.stormDetail ?? undefined,
517
- rejectionDetail: input.rejectionDetail ?? undefined,
518
- });
519
- return {
520
- kind: disposition.kind,
521
- retryable: disposition.retryable,
522
- reason: disposition.reason,
523
- };
524
- }
525
- case 'upstreamTurnErrorSummary':
526
- return upstreamTurnErrorSummary(input.params) ?? null;
527
- case 'itemKey':
528
- return pipelineItemKey({
529
- turnId: input.identity.turnId,
530
- itemId: input.identity.itemId ?? undefined,
531
- itemIndex: input.identity.itemIndex,
532
- streamKind: input.identity.streamKind,
533
- });
534
- case 'clientMessageId':
535
- return pipelineClientMessageId(
536
- input.instanceId,
537
- input.turnId,
538
- input.streamKind,
539
- input.wireItemKey
540
- );
541
- case 'notificationTurnId':
542
- return notificationTurnId(input.params) ?? null;
543
- case 'explicitItemId':
544
- return explicitNotificationItemId(input.params) ?? null;
545
- case 'projectSnapshotItems':
546
- return projectSnapshotItems(input.items).map((proj) => ({
547
- snapshotIndex: proj.snapshotIndex,
548
- itemId: proj.itemId ?? null,
549
- streamKind: proj.streamKind,
550
- body: proj.body,
551
- structured: proj.structured,
552
- }));
553
- case 'transitionRun':
554
- return runTransitionCase(input);
555
- case 'loopRun':
556
- return runLoopCase(input);
557
- case 'statsRun':
558
- return runStatsCase(input);
559
- case 'turnStallWatchdogRun':
560
- return runTurnStallWatchdogCase(input);
561
- case 'dispatchWatchdogRun':
562
- return runDispatchWatchdogCase(input);
563
- default:
564
- return { error: 'unknown case kind ' + String(input.kind) };
565
- }
566
- }
567
-
568
- async function runBatch() {
569
- const chunks = [];
570
- for await (const chunk of process.stdin) chunks.push(chunk);
571
- const cases = JSON.parse(Buffer.concat(chunks).toString('utf8'));
572
- const results = [];
573
- for (const testCase of cases) {
574
- results.push(await runCase(testCase));
575
- }
576
- process.stdout.write(JSON.stringify(results), () => {
577
- process.exit(0);
578
- });
579
- }
580
-
581
- runBatch().then(
582
- () => {},
583
- (error) => {
584
- process.stderr.write(String(error && error.stack ? error.stack : error) + '\\n');
585
- process.exit(1);
586
- }
587
- );
588
- `;
589
-
590
- const outDir = join(packageRoot, '.differential');
591
- const outPath = join(outDir, 'pipeline-parity-oracle.mjs');
592
-
593
- await mkdir(outDir, { recursive: true });
594
-
595
- await build({
596
- stdin: {
597
- contents: driverSource,
598
- resolveDir: packageRoot,
599
- sourcefile: 'pipeline-parity-driver.ts',
600
- loader: 'ts',
601
- },
602
- bundle: true,
603
- platform: 'node',
604
- target: 'node20',
605
- format: 'esm',
606
- outfile: outPath,
607
- minify: false,
608
- sourcemap: false,
609
- legalComments: 'none',
610
- logLevel: 'silent',
611
- external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
612
- });
613
-
614
- process.stdout.write(outPath + '\n');