Skip to content

Commit ff0ca4c

Browse files
committed
test(cli): install-local chains stay sequential; budgets from CI readings
Seat review: running chains side by side packs work on CI's shared box and adds about 3.3 GB of peak RSS per file, so every chain runs in sequence again, as on main. Each file's budget is now its slowest CI reading of that sequential shape x 1.25, rounded up. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DcLzU9qErDBr5VydWEmHVM
1 parent db8bd85 commit ff0ca4c

7 files changed

Lines changed: 156 additions & 251 deletions

‎packages/cli/test/package-install-local-boot-steps.integration.test.ts‎

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2-
// test-budget: 70 — spawns the real producer once per single-cause fixture: three `os start` boots of the tsx source entry (install, restart on the same home, and the `--artifact` control on its own home, run beside the other two) and one `os package install` run; slowest of three local runs after the control ran beside them 49.1 s, x 1.11 (this file's CI-over-local ratio before: 68.2 s in hourly full battery run 40290659753 over a 61.3 s local median) x 1.25, rounded up; no CI reading of this shape yet
2+
// test-budget: 120 — spawns the real producer once per single-cause fixture: three `os start` boots of the tsx source entry in sequence (install, restart on the same home, and the `--artifact` control on its own home) and one `os package install` run; slowest CI reading of this shape 94.3 s (run 38222448090, the card's window; 68.2 s in hourly full battery run 40290659753) x 1.25, rounded up
33

44
/**
55
* #21322 — a hot install (`os package install <artifact>` into a RUNNING
@@ -301,17 +301,6 @@ async function probe(live: LiveStart, token: string): Promise<Phase> {
301301
return { permissionSet, created, updated, notes };
302302
}
303303

304-
/**
305-
* Run phases that share no state at once, and wait for EVERY one to settle
306-
* before reporting the first failure: a phase that rejects must not leave a
307-
* sibling still booting after `afterAll` has stopped the process groups.
308-
*/
309-
async function allPhases(chains: Array<() => Promise<void>>): Promise<void> {
310-
const settled = await Promise.allSettled(chains.map((chain) => chain()));
311-
const failed = settled.find((s): s is PromiseRejectedResult => s.status === 'rejected');
312-
if (failed) throw failed.reason;
313-
}
314-
315304
const phases: Record<'install' | 'restart' | 'control', Phase | undefined> = {
316305
install: undefined, restart: undefined, control: undefined,
317306
};
@@ -331,33 +320,24 @@ beforeAll(async () => {
331320
writeFileSync(hostArtifact, JSON.stringify(HOST_ARTIFACT, null, 2), 'utf8');
332321
const home = join(runtimeDir, 'home');
333322

334-
// Boots 1 and 2 share one home and run in order. Boot 3, the CONTROL, has
335-
// its own cwd and home and only reads the package file, so it runs beside
336-
// them; every boot binds a kernel-assigned port.
337-
await allPhases([
338-
// ── boot 1: the host, hot install, probe ───────────────────────────────
339-
async () => {
340-
const first = await bootStart(runtimeDir, home, ['--artifact', hostArtifact]);
341-
const token = await authenticate(first);
342-
installs.push(await packageInstall(appDir, first));
343-
phases.install = await probe(first, token);
344-
await stopGroup(first.child);
323+
// ── boot 1: the host, hot install, probe ───────────────────────────────
324+
const first = await bootStart(runtimeDir, home, ['--artifact', hostArtifact]);
325+
const token = await authenticate(first);
326+
installs.push(await packageInstall(appDir, first));
327+
phases.install = await probe(first, token);
328+
await stopGroup(first.child);
345329

346-
// ── boot 2: same host, home and cwd — the ledger rehydrates on kernel:ready ──
347-
const second = await bootStart(runtimeDir, home, ['--artifact', hostArtifact]);
348-
phases.restart = await probe(second, await authenticate(second));
349-
await stopGroup(second.child);
350-
},
330+
// ── boot 2: same host, home and cwd — the ledger rehydrates on kernel:ready ──
331+
const second = await bootStart(runtimeDir, home, ['--artifact', hostArtifact]);
332+
phases.restart = await probe(second, await authenticate(second));
333+
await stopGroup(second.child);
351334

352-
// ── boot 3: the CONTROL — the same file as the boot artifact ───────────
353-
async () => {
354-
const controlDir = join(root, 'control');
355-
mkdirSync(controlDir, { recursive: true });
356-
const third = await bootStart(controlDir, join(controlDir, 'home'), ['--artifact', join(appDir, 'dist', 'objectstack.json')]);
357-
phases.control = await probe(third, await authenticate(third));
358-
await stopGroup(third.child);
359-
},
360-
]);
335+
// ── boot 3: the CONTROL — the same file as the boot artifact ───────────
336+
const controlDir = join(root, 'control');
337+
mkdirSync(controlDir, { recursive: true });
338+
const third = await bootStart(controlDir, join(controlDir, 'home'), ['--artifact', join(appDir, 'dist', 'objectstack.json')]);
339+
phases.control = await probe(third, await authenticate(third));
340+
await stopGroup(third.child);
361341
}, 4 * BOOT_TIMEOUT_MS);
362342

363343
afterAll(async () => {

‎packages/cli/test/package-install-local-handlers.integration.test.ts‎

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2-
// test-budget: 100 — spawns the real producer once per single-cause fixture: three `os start` boots of the tsx source entry (install and reinstall, restart on the same home, and the `--artifact` control on its own home, run beside the other two) and two `os package install` runs; slowest of three local runs after the control ran beside them 57.5 s, x 1.35 (this file's CI-over-local ratio before: 97.8 s in hourly full battery run 40290659753 over a 72.7 s local median) x 1.25, rounded up; no CI reading of this shape yet
2+
// test-budget: 130 — spawns the real producer once per single-cause fixture: three `os start` boots of the tsx source entry in sequence (install and reinstall, restart on the same home, and the `--artifact` control on its own home) and two `os package install` runs; slowest CI reading of this shape 99.4 s (run 38332198724, the card's window; 97.8 s in hourly full battery run 40290659753) x 1.25, rounded up
33

44
/**
55
* #21321 — an app installed with `os package install <artifact>` runs its
@@ -311,17 +311,6 @@ async function probe(live: LiveStart, token: string): Promise<Phase> {
311311

312312
const rec = (a: Answer) => a.body?.data ?? a.body?.record ?? a.body;
313313

314-
/**
315-
* Run phases that share no state at once, and wait for EVERY one to settle
316-
* before reporting the first failure: a phase that rejects must not leave a
317-
* sibling still booting after `afterAll` has stopped the process groups.
318-
*/
319-
async function allPhases(chains: Array<() => Promise<void>>): Promise<void> {
320-
const settled = await Promise.allSettled(chains.map((chain) => chain()));
321-
const failed = settled.find((s): s is PromiseRejectedResult => s.status === 'rejected');
322-
if (failed) throw failed.reason;
323-
}
324-
325314
const phases: Record<'install' | 'reinstall' | 'restart' | 'control', Phase | undefined> = {
326315
install: undefined, reinstall: undefined, restart: undefined, control: undefined,
327316
};
@@ -338,35 +327,26 @@ beforeAll(async () => {
338327
mkdirSync(runtimeDir, { recursive: true });
339328
const home = join(runtimeDir, 'home');
340329

341-
// Boots 1 and 2 share one home and run in order. Boot 3, the CONTROL, has
342-
// its own cwd and home and only reads the package file, so it runs beside
343-
// them; every boot binds a kernel-assigned port.
344-
await allPhases([
345-
// ── boot 1: empty `os start`, install, probe, reinstall, probe ─────────
346-
async () => {
347-
const first = await bootStart(runtimeDir, home);
348-
const token = await authenticate(first);
349-
installs.push(await packageInstall(appDir, first));
350-
phases.install = await probe(first, token);
351-
installs.push(await packageInstall(appDir, first));
352-
phases.reinstall = await probe(first, token);
353-
await stopGroup(first.child);
354-
355-
// ── boot 2: same home and cwd — the ledger rehydrates on kernel:ready ──
356-
const second = await bootStart(runtimeDir, home);
357-
phases.restart = await probe(second, await authenticate(second));
358-
await stopGroup(second.child);
359-
},
360-
361-
// ── boot 3: the CONTROL — the same file as the boot artifact ───────────
362-
async () => {
363-
const controlDir = join(root, 'control');
364-
mkdirSync(controlDir, { recursive: true });
365-
const third = await bootStart(controlDir, join(controlDir, 'home'), ['--artifact', join(appDir, 'dist', 'objectstack.json')]);
366-
phases.control = await probe(third, await authenticate(third));
367-
await stopGroup(third.child);
368-
},
369-
]);
330+
// ── boot 1: empty `os start`, install, probe, reinstall, probe ─────────
331+
const first = await bootStart(runtimeDir, home);
332+
const token = await authenticate(first);
333+
installs.push(await packageInstall(appDir, first));
334+
phases.install = await probe(first, token);
335+
installs.push(await packageInstall(appDir, first));
336+
phases.reinstall = await probe(first, token);
337+
await stopGroup(first.child);
338+
339+
// ── boot 2: same home and cwd — the ledger rehydrates on kernel:ready ──
340+
const second = await bootStart(runtimeDir, home);
341+
phases.restart = await probe(second, await authenticate(second));
342+
await stopGroup(second.child);
343+
344+
// ── boot 3: the CONTROL — the same file as the boot artifact ───────────
345+
const controlDir = join(root, 'control');
346+
mkdirSync(controlDir, { recursive: true });
347+
const third = await bootStart(controlDir, join(controlDir, 'home'), ['--artifact', join(appDir, 'dist', 'objectstack.json')]);
348+
phases.control = await probe(third, await authenticate(third));
349+
await stopGroup(third.child);
370350
}, 4 * BOOT_TIMEOUT_MS);
371351

372352
afterAll(async () => {

‎packages/cli/test/package-install-local-hooks.integration.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2-
// test-budget: 150 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs, then the rehydrate of an entry an earlier build wrote) and five `os package install` runs, one per package under test; slowest CI reading 114.4 s (hourly full battery run 40290659753, 2026-10-26) x 1.25, rounded up
2+
// test-budget: 150 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs, then the rehydrate of an entry an earlier build wrote) and five `os package install` runs, one per package under test; slowest CI reading 117.1 s (run 38332198724, the card's window; 114.4 s in hourly full battery run 40290659753) x 1.25, rounded up
33

44
/**
55
* #21585 — install-local refuses the code it cannot run: a hook with no `body`,

‎packages/cli/test/package-install-local-jobs-pull.integration.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2-
// test-budget: 140 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs, then the rehydrate of an entry an earlier build wrote) and four `os package install` runs, one per package under test; slowest CI reading 107.9 s (run 38335967790, the card's window; the job logs of run 40290659753 read here carry no line for this file) x 1.25, rounded up
2+
// test-budget: 140 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs, then the rehydrate of an entry an earlier build wrote) and four `os package install` runs, one per package under test; slowest CI reading 107.9 s (run 38335967790, the card's window; the job logs of hourly full battery run 40290659753 read here carry no line for this file) x 1.25, rounded up
33

44
/**
55
* install-local refuses an enabled job whose `pull` cannot bind, as it refuses

‎packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2-
// test-budget: 140 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs and an uninstall, then the rehydrate and a second uninstall) and three `os package install` runs, one per package sharing the job name; slowest CI reading 107.1 s (hourly full battery run 40290659753, 2026-10-26) x 1.25, rounded up
2+
// test-budget: 140 — spawns the real producer once per single-cause fixture: two `os start` boots of the tsx source entry on one home (the hot installs and an uninstall, then the rehydrate and a second uninstall) and three `os package install` runs, one per package sharing the job name; slowest CI reading 110.4 s (run 38332198724, the card's window; 107.1 s in hourly full battery run 40290659753) x 1.25, rounded up
33

44
/**
55
* #21602 — two install-local packages that declare the SAME job name both keep

0 commit comments

Comments
 (0)