@linzumi/cli 1.0.113 → 1.0.115
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 +135 -135
- package/package.json +1 -1
- package/scripts/build-tui-demo-evidence.mjs +107 -0
- package/scripts/build-tui-parity-oracle.mjs +577 -0
- package/scripts/build-worker-entry-parity-oracle.mjs +424 -0
- package/scripts/build-worker-spawn-parity-oracle.mjs +814 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
// Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
|
|
2
|
+
// (M3 cluster 12, worker-spawn / the I153 stable-entry machinery).
|
|
3
|
+
// Relationship: Builds the TS-side PARITY ORACLE for the worker-entry
|
|
4
|
+
// stability + harness-pin modules of the ReScript commander port, the
|
|
5
|
+
// sibling of build-config-identity-parity-oracle.mjs (cluster 2). The
|
|
6
|
+
// oracle bundles the REAL workerEntryStability.ts (pinWorkerEntryAtBoot /
|
|
7
|
+
// resolveWorkerEntryForSpawn / installVersionToStableDir /
|
|
8
|
+
// entryPathLooksEphemeral / workerEntryMissingMessage - the I153 machinery)
|
|
9
|
+
// and bundledCodexBin.ts (the #3102/#3129 harness version gate:
|
|
10
|
+
// resolveBundledCodexBinary / pinnedHarnessVersion /
|
|
11
|
+
// assessPathFallbackHarness / resolveRequestedCodexBin /
|
|
12
|
+
// revalidateCodexBinForSpawn) behind the cluster 1/2 one-shot BATCH driver
|
|
13
|
+
// (a JSON array of cases on stdin, a JSON array of results on stdout).
|
|
14
|
+
//
|
|
15
|
+
// Determinism + normalization: every case runs in its own realpath'd
|
|
16
|
+
// scratch dir; paths normalize through the "$DIR" placeholder in both
|
|
17
|
+
// directions; wall-clock material (marker mirroredAt/installedAt, event
|
|
18
|
+
// durationMs, `.building-<pid>-<ts>` staging suffixes) normalizes through
|
|
19
|
+
// fixed placeholders so two runs - and two impls - compare byte-identical.
|
|
20
|
+
// File-tree snapshots after every lifecycle are part of the result: the
|
|
21
|
+
// mirror layout under ~/.linzumi/worker-entry and ~/.linzumi/versions is a
|
|
22
|
+
// CROSS-IMPL contract (both commanders share ~/.linzumi through M4).
|
|
23
|
+
//
|
|
24
|
+
// SECRETS: the oracle only ever sees the conformance suite's synthetic
|
|
25
|
+
// trees. The output is a local test artifact (.differential/ is gitignored,
|
|
26
|
+
// 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
|
+
existsSync,
|
|
37
|
+
mkdirSync,
|
|
38
|
+
mkdtempSync,
|
|
39
|
+
readdirSync,
|
|
40
|
+
readFileSync,
|
|
41
|
+
realpathSync,
|
|
42
|
+
rmSync,
|
|
43
|
+
statSync,
|
|
44
|
+
symlinkSync,
|
|
45
|
+
utimesSync,
|
|
46
|
+
writeFileSync,
|
|
47
|
+
} from 'node:fs';
|
|
48
|
+
import { tmpdir } from 'node:os';
|
|
49
|
+
import { dirname as pathDirname, join, relative } from 'node:path';
|
|
50
|
+
import {
|
|
51
|
+
entryPathLooksEphemeral,
|
|
52
|
+
installVersionToStableDir,
|
|
53
|
+
pinWorkerEntryAtBoot,
|
|
54
|
+
resolveWorkerEntryForSpawn,
|
|
55
|
+
workerEntryMissingMessage,
|
|
56
|
+
} from './src/workerEntryStability';
|
|
57
|
+
import {
|
|
58
|
+
assessPathFallbackHarness,
|
|
59
|
+
codexPlatformTarget,
|
|
60
|
+
pinnedHarnessVersion,
|
|
61
|
+
resolveBundledCodexBinary,
|
|
62
|
+
resolveRequestedCodexBin,
|
|
63
|
+
resetBundledCodexWarningForTests,
|
|
64
|
+
revalidateCodexBinForSpawn,
|
|
65
|
+
} from './src/bundledCodexBin';
|
|
66
|
+
|
|
67
|
+
// --- Placeholder + snapshot plumbing --------------------------------------------
|
|
68
|
+
|
|
69
|
+
const dirPlaceholder = '$DIR';
|
|
70
|
+
|
|
71
|
+
function scratch() {
|
|
72
|
+
// realpath so macOS /var -> /private/var never splits the two impls'
|
|
73
|
+
// placeholder substitution.
|
|
74
|
+
return realpathSync(mkdtempSync(join(tmpdir(), 'linzumi-worker-entry-oracle-')));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function substitute(value, from, to) {
|
|
78
|
+
if (typeof value === 'string') {
|
|
79
|
+
return value.split(from).join(to);
|
|
80
|
+
}
|
|
81
|
+
if (Array.isArray(value)) {
|
|
82
|
+
return value.map((entry) => substitute(entry, from, to));
|
|
83
|
+
}
|
|
84
|
+
if (typeof value === 'object' && value !== null) {
|
|
85
|
+
return Object.fromEntries(
|
|
86
|
+
Object.entries(value).map(([key, entry]) => [
|
|
87
|
+
substitute(key, from, to),
|
|
88
|
+
substitute(entry, from, to),
|
|
89
|
+
])
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Wall-clock normalization: marker timestamps, event durations, staging
|
|
96
|
+
// suffixes.
|
|
97
|
+
function normalizeClock(value) {
|
|
98
|
+
if (typeof value === 'string') {
|
|
99
|
+
return value
|
|
100
|
+
.replaceAll(/\\.building-\\d+-\\d+(?:\\.\\d+)?/g, '.building-X')
|
|
101
|
+
.replaceAll(
|
|
102
|
+
/"(mirroredAt|installedAt)":"[^"]*"/g,
|
|
103
|
+
'"$1":"<at>"'
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
return value.map((entry) => normalizeClock(entry));
|
|
108
|
+
}
|
|
109
|
+
if (typeof value === 'object' && value !== null) {
|
|
110
|
+
return Object.fromEntries(
|
|
111
|
+
Object.entries(value).map(([key, entry]) => [
|
|
112
|
+
normalizeClock(key),
|
|
113
|
+
key === 'durationMs' ? '<duration>' : normalizeClock(entry),
|
|
114
|
+
])
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function snapshotFiles(dir) {
|
|
121
|
+
const files = {};
|
|
122
|
+
const walk = (current) => {
|
|
123
|
+
let names;
|
|
124
|
+
try {
|
|
125
|
+
names = readdirSync(current).sort();
|
|
126
|
+
} catch {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for (const name of names) {
|
|
130
|
+
const full = join(current, name);
|
|
131
|
+
if (statSync(full).isDirectory()) {
|
|
132
|
+
files[relative(dir, full) + '/'] = '<dir>';
|
|
133
|
+
walk(full);
|
|
134
|
+
} else {
|
|
135
|
+
files[relative(dir, full)] = readFileSync(full, 'utf8');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
walk(dir);
|
|
140
|
+
return files;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function buildTree(root, files) {
|
|
144
|
+
for (const [relPath, spec] of Object.entries(files ?? {})) {
|
|
145
|
+
const full = join(root, relPath);
|
|
146
|
+
if (spec !== null && typeof spec === 'object' && spec.symlinkTo !== undefined) {
|
|
147
|
+
mkdirSync(pathDirname(full), { recursive: true });
|
|
148
|
+
symlinkSync(join(root, spec.symlinkTo), full);
|
|
149
|
+
} else if (relPath.endsWith('/')) {
|
|
150
|
+
mkdirSync(full, { recursive: true });
|
|
151
|
+
} else {
|
|
152
|
+
mkdirSync(pathDirname(full), { recursive: true });
|
|
153
|
+
writeFileSync(full, String(spec), 'utf8');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// --- The worker-entry lifecycle op ------------------------------------------------
|
|
159
|
+
|
|
160
|
+
async function handleEntryLifecycle(testCase) {
|
|
161
|
+
const dir = scratch();
|
|
162
|
+
const homeDir = join(dir, 'home');
|
|
163
|
+
mkdirSync(homeDir, { recursive: true });
|
|
164
|
+
const sub = (value) => substitute(value, dirPlaceholder, dir);
|
|
165
|
+
buildTree(dir, sub(testCase.files ?? {}));
|
|
166
|
+
|
|
167
|
+
const events = [];
|
|
168
|
+
const onEvent = (event, data) => {
|
|
169
|
+
events.push({ event, data });
|
|
170
|
+
};
|
|
171
|
+
const pinnedRef = { value: undefined };
|
|
172
|
+
const trace = [];
|
|
173
|
+
|
|
174
|
+
for (const action of testCase.actions ?? []) {
|
|
175
|
+
const act = sub(action);
|
|
176
|
+
switch (act.act) {
|
|
177
|
+
case 'buildTree': {
|
|
178
|
+
buildTree(dir, act.files ?? {});
|
|
179
|
+
trace.push({ act: 'buildTree' });
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'rm': {
|
|
183
|
+
rmSync(act.path, { recursive: true, force: true });
|
|
184
|
+
trace.push({ act: 'rm' });
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case 'touch': {
|
|
188
|
+
const when = new Date(act.epochMs);
|
|
189
|
+
utimesSync(act.path, when, when);
|
|
190
|
+
trace.push({ act: 'touch' });
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case 'pin': {
|
|
194
|
+
const pinned = pinWorkerEntryAtBoot({
|
|
195
|
+
argv1: act.argv1 ?? undefined,
|
|
196
|
+
cwd: act.cwd ?? dir,
|
|
197
|
+
homeDir,
|
|
198
|
+
onEvent,
|
|
199
|
+
// Deterministic lost-race injection: materialize the "winner's"
|
|
200
|
+
// complete mirror between the staging build and the rename, so
|
|
201
|
+
// the loser branch is provable from a plain JSON case.
|
|
202
|
+
beforeMirrorRenameForTest:
|
|
203
|
+
act.raceWinnerFiles === undefined
|
|
204
|
+
? undefined
|
|
205
|
+
: () => buildTree(dir, act.raceWinnerFiles),
|
|
206
|
+
});
|
|
207
|
+
pinnedRef.value = pinned;
|
|
208
|
+
trace.push({
|
|
209
|
+
act: 'pin',
|
|
210
|
+
pinned:
|
|
211
|
+
pinned === undefined
|
|
212
|
+
? null
|
|
213
|
+
: {
|
|
214
|
+
kind: pinned.kind,
|
|
215
|
+
entryPath: pinned.entryPath,
|
|
216
|
+
originalEntryPath:
|
|
217
|
+
pinned.kind === 'mirrored' ? pinned.originalEntryPath : null,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case 'resolveSpawn': {
|
|
223
|
+
try {
|
|
224
|
+
const resolved = resolveWorkerEntryForSpawn({
|
|
225
|
+
pinnedRef,
|
|
226
|
+
argv1: act.argv1 ?? undefined,
|
|
227
|
+
cwd: act.cwd ?? dir,
|
|
228
|
+
homeDir,
|
|
229
|
+
onEvent,
|
|
230
|
+
});
|
|
231
|
+
trace.push({ act: 'resolveSpawn', resolved });
|
|
232
|
+
} catch (error) {
|
|
233
|
+
trace.push({
|
|
234
|
+
act: 'resolveSpawn',
|
|
235
|
+
threw: error instanceof Error ? error.message : String(error),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
case 'installVersion': {
|
|
241
|
+
const install = act.install ?? {};
|
|
242
|
+
try {
|
|
243
|
+
const result = await installVersionToStableDir({
|
|
244
|
+
version: act.version,
|
|
245
|
+
homeDir,
|
|
246
|
+
onEvent,
|
|
247
|
+
runInstall: async ({ prefixDir, packageSpec }) => {
|
|
248
|
+
buildTree(prefixDir, install.files ?? {});
|
|
249
|
+
trace.push({ act: 'runInstall', packageSpec });
|
|
250
|
+
return install.ok === false
|
|
251
|
+
? { ok: false, message: install.message }
|
|
252
|
+
: { ok: true };
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
trace.push({ act: 'installVersion', result });
|
|
256
|
+
} catch (error) {
|
|
257
|
+
trace.push({
|
|
258
|
+
act: 'installVersion',
|
|
259
|
+
threw: error instanceof Error ? error.message : String(error),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
default:
|
|
265
|
+
trace.push({ act: 'unknown', name: String(act.act) });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const result = {
|
|
270
|
+
trace,
|
|
271
|
+
events,
|
|
272
|
+
home: snapshotFiles(homeDir),
|
|
273
|
+
};
|
|
274
|
+
return normalizeClock(substitute(result, dir, dirPlaceholder));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// --- The harness-pin ops ----------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
function harnessDeps(dir, spec) {
|
|
280
|
+
const resolvable = spec.resolvable ?? {};
|
|
281
|
+
return {
|
|
282
|
+
platform: spec.platform ?? process.platform,
|
|
283
|
+
arch: spec.arch ?? process.arch,
|
|
284
|
+
fileExists: existsSync,
|
|
285
|
+
listDirectory: (path) => {
|
|
286
|
+
try {
|
|
287
|
+
return readdirSync(path);
|
|
288
|
+
} catch {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
resolveModulePath: (name) =>
|
|
293
|
+
resolvable[name] === undefined ? undefined : join(dir, resolvable[name]),
|
|
294
|
+
moduleDir: spec.moduleDir === undefined ? join(dir, 'module') : join(dir, spec.moduleDir),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function handleHarnessPin(testCase) {
|
|
299
|
+
const dir = scratch();
|
|
300
|
+
const sub = (value) => substitute(value, dirPlaceholder, dir);
|
|
301
|
+
buildTree(dir, sub(testCase.files ?? {}));
|
|
302
|
+
const deps = harnessDeps(dir, sub(testCase.deps ?? {}));
|
|
303
|
+
resetBundledCodexWarningForTests();
|
|
304
|
+
const warnings = [];
|
|
305
|
+
const writeWarning = (message) => warnings.push(message);
|
|
306
|
+
const probe = () => (testCase.probeVersion === undefined ? undefined : testCase.probeVersion);
|
|
307
|
+
const env = testCase.env ?? {};
|
|
308
|
+
|
|
309
|
+
const run = () => {
|
|
310
|
+
switch (testCase.fn) {
|
|
311
|
+
case 'platformTarget': {
|
|
312
|
+
// Project the TYPED contract surface ({triple, packageName}): the
|
|
313
|
+
// runtime row object carries platform/arch too, which the TS type
|
|
314
|
+
// deliberately hides.
|
|
315
|
+
const target = codexPlatformTarget(testCase.platform, testCase.arch);
|
|
316
|
+
return target === undefined
|
|
317
|
+
? null
|
|
318
|
+
: { triple: target.triple, packageName: target.packageName };
|
|
319
|
+
}
|
|
320
|
+
case 'resolveBundled': {
|
|
321
|
+
const resolved = resolveBundledCodexBinary(deps);
|
|
322
|
+
return resolved === undefined ? null : resolved;
|
|
323
|
+
}
|
|
324
|
+
case 'pinnedVersion': {
|
|
325
|
+
const version = pinnedHarnessVersion(deps);
|
|
326
|
+
return version === undefined ? null : version;
|
|
327
|
+
}
|
|
328
|
+
case 'assess':
|
|
329
|
+
return assessPathFallbackHarness({
|
|
330
|
+
pathVersion: testCase.pathVersion ?? undefined,
|
|
331
|
+
pinnedVersion: testCase.pinnedVersion ?? undefined,
|
|
332
|
+
});
|
|
333
|
+
case 'resolveRequested': {
|
|
334
|
+
const request = resolveRequestedCodexBin(testCase.explicitCodexBin ?? undefined, {
|
|
335
|
+
...deps,
|
|
336
|
+
writeWarning,
|
|
337
|
+
probeHarnessVersion: probe,
|
|
338
|
+
env,
|
|
339
|
+
});
|
|
340
|
+
return { request, warnings };
|
|
341
|
+
}
|
|
342
|
+
case 'revalidate': {
|
|
343
|
+
const outcome = revalidateCodexBinForSpawn({
|
|
344
|
+
codexBin: sub(testCase.codexBin),
|
|
345
|
+
source: testCase.source ?? undefined,
|
|
346
|
+
deps,
|
|
347
|
+
probeHarnessVersion: probe,
|
|
348
|
+
env,
|
|
349
|
+
});
|
|
350
|
+
return outcome;
|
|
351
|
+
}
|
|
352
|
+
default:
|
|
353
|
+
throw new Error('unknown harness fn ' + String(testCase.fn));
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
try {
|
|
358
|
+
return substitute({ value: run(), warnings }, dir, dirPlaceholder);
|
|
359
|
+
} catch (error) {
|
|
360
|
+
return substitute(
|
|
361
|
+
{
|
|
362
|
+
threw: error instanceof Error ? error.message : String(error),
|
|
363
|
+
warnings,
|
|
364
|
+
},
|
|
365
|
+
dir,
|
|
366
|
+
dirPlaceholder
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// --- Dispatch -----------------------------------------------------------------------
|
|
372
|
+
|
|
373
|
+
async function handle(testCase) {
|
|
374
|
+
switch (testCase.op) {
|
|
375
|
+
case 'entryLifecycle':
|
|
376
|
+
return handleEntryLifecycle(testCase);
|
|
377
|
+
case 'looksEphemeral':
|
|
378
|
+
return { value: entryPathLooksEphemeral(testCase.path) };
|
|
379
|
+
case 'missingMessage':
|
|
380
|
+
return {
|
|
381
|
+
value: workerEntryMissingMessage({
|
|
382
|
+
attemptedPaths: testCase.attemptedPaths,
|
|
383
|
+
ephemeral: testCase.ephemeral,
|
|
384
|
+
}),
|
|
385
|
+
};
|
|
386
|
+
case 'harnessPin':
|
|
387
|
+
return handleHarnessPin(testCase);
|
|
388
|
+
default:
|
|
389
|
+
return { threw: true, message: 'unknown op ' + String(testCase.op) };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
let stdin = '';
|
|
394
|
+
process.stdin.setEncoding('utf8');
|
|
395
|
+
for await (const chunk of process.stdin) {
|
|
396
|
+
stdin += chunk;
|
|
397
|
+
}
|
|
398
|
+
const cases = JSON.parse(stdin);
|
|
399
|
+
const results = [];
|
|
400
|
+
for (const testCase of cases) {
|
|
401
|
+
results.push(await handle(testCase));
|
|
402
|
+
}
|
|
403
|
+
process.stdout.write(JSON.stringify(results));
|
|
404
|
+
`;
|
|
405
|
+
|
|
406
|
+
await mkdir(join(packageRoot, '.differential'), { recursive: true });
|
|
407
|
+
|
|
408
|
+
await build({
|
|
409
|
+
stdin: {
|
|
410
|
+
contents: driverSource,
|
|
411
|
+
resolveDir: packageRoot,
|
|
412
|
+
sourcefile: 'worker-entry-parity-driver.ts',
|
|
413
|
+
loader: 'ts',
|
|
414
|
+
},
|
|
415
|
+
bundle: true,
|
|
416
|
+
platform: 'node',
|
|
417
|
+
target: 'node20',
|
|
418
|
+
format: 'esm',
|
|
419
|
+
outfile: join(packageRoot, '.differential/worker-entry-parity-oracle.mjs'),
|
|
420
|
+
minify: false,
|
|
421
|
+
sourcemap: false,
|
|
422
|
+
legalComments: 'none',
|
|
423
|
+
external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
|
|
424
|
+
});
|