diff --git a/packages/cli/test/lint-per-package-authoring-parity.test.ts b/packages/cli/test/lint-per-package-authoring-parity.test.ts index 33d089f1624..fcfdccb4cfe 100644 --- a/packages/cli/test/lint-per-package-authoring-parity.test.ts +++ b/packages/cli/test/lint-per-package-authoring-parity.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 60 — spawns the real producer once per single-cause fixture: five CLI spawns in one beforeAll, each a distinct triple (`os build`, `os lint`, `os lint --strict` over the flip fixture; `os build`, `os lint` over the single-package control); slowest CI reading 43.77 s (run 40392443783), taken with nine spawns before the repeats were shared of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * #18778, the BEHAVIOURAL half — `os lint` and `os build` report the same @@ -211,6 +212,17 @@ export default defineStack({ const dirs = { flip: '', single: '' }; +/** A cold `tsx` spawn of the CLI source entry, the per-case allowance this file always gave one. */ +const SPAWN_TIMEOUT_MS = 180_000; + +/** + * One run per distinct (command, flags, fixture) triple. The cases below used + * to spawn `os build --json` on the flip fixture three times and `os lint + * --json` on it three times; every case now reads the one run of its triple, + * spawned in sequence in the `beforeAll` below. + */ +const runs = {} as Record<'buildFlip' | 'lintFlip' | 'lintStrictFlip' | 'buildSingle' | 'lintSingle', Run>; + function plant(config: string): string { const dir = mkdtempSync(join(tmpdir(), 'os-lintpp-')); mkdirSync(join(dir, 'src'), { recursive: true }); @@ -225,31 +237,36 @@ function plant(config: string): string { } describe('#18778 — `os lint` and `os build` report the same per-package finding set', () => { - beforeAll(() => { + beforeAll(async () => { dirs.flip = plant(CONFIG_FLIP); dirs.single = plant(CONFIG_SINGLE); - }); + runs.buildFlip = await runCli(['build', '--json'], dirs.flip); + runs.lintFlip = await runCli(['lint', '--json'], dirs.flip); + runs.lintStrictFlip = await runCli(['lint', '--json', '--strict'], dirs.flip); + runs.buildSingle = await runCli(['build', '--json'], dirs.single); + runs.lintSingle = await runCli(['lint', '--json'], dirs.single); + }, 5 * SPAWN_TIMEOUT_MS); afterAll(() => { for (const dir of Object.values(dirs)) if (dir) rmSync(dir, { recursive: true, force: true }); }); - it('the fixture reaches the pass at all, and the UNION sees nothing — `os build` raises exactly the survivor', async () => { + it('the fixture reaches the pass at all, and the UNION sees nothing — `os build` raises exactly the survivor', () => { // Asserted BEFORE any claim about parity: a fixture that never reaches the // per-package pass makes every comparison below vacuous, and a fixture whose // union run raises the same finding makes the comparison an echo count. - const build = await runCli(['build', '--json'], dirs.flip); + const build = runs.buildFlip; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); const warnings = payloadOf(build, 'os build --json').warnings as unknown[]; expect(buildPerPackage(warnings).length).toBeGreaterThan(0); // Nothing else: every warning on this fixture is a per-package survivor. expect(warnings.length).toBe(buildPerPackage(warnings).length); - }, 180_000); + }); - it('`os lint` reports every per-package finding `os build` does', async () => { + it('`os lint` reports every per-package finding `os build` does', () => { // The pin. On `origin/main` 7572329069 this read `build: 1, lint: 0`. - const build = await runCli(['build', '--json'], dirs.flip); - const lint = await runCli(['lint', '--json'], dirs.flip); + const build = runs.buildFlip; + const lint = runs.lintFlip; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); expect(lint.code, `os lint --json failed:\n${lint.stdout}${lint.stderr}`).toBe(0); @@ -260,25 +277,25 @@ describe('#18778 — `os lint` and `os build` report the same per-package findin missing, 'these per-package findings ride `os build` and `os lint` cannot see them — the #18778 false-clean set', ).toEqual([]); - }, 180_000); + }); - it('…and nothing per-package rides `os lint` that `os build` does not report either', async () => { + it('…and nothing per-package rides `os lint` that `os build` does not report either', () => { // Parity is an equality. A lint that over-reports is its own defect — an // author fixing a finding the command that SHIPS never raises. - const build = await runCli(['build', '--json'], dirs.flip); - const lint = await runCli(['lint', '--json'], dirs.flip); + const build = runs.buildFlip; + const lint = runs.lintFlip; const inBuild = new Set(buildPerPackage(payloadOf(build, 'os build --json').warnings as unknown[])); expect(lintPerPackage(payloadOf(lint, 'os lint --json').issues as unknown[]).filter((w) => !inBuild.has(w))).toEqual([]); - }, 180_000); + }); - it('⚠️ THE NARROWING — `os lint --strict` now EXITS 1 on a project it exited 0 for', async () => { + it('⚠️ THE NARROWING — `os lint --strict` now EXITS 1 on a project it exited 0 for', () => { // The Clause-② evidence, pinned so it can neither regress silently nor widen // silently. `--strict` is documented as "treat warnings as errors", and a // per-package advisory is a warning this door could not see before, so the // verdict moves with it. ⛔ The DEFAULT face is deliberately NOT asserted to // move: no `error`-severity per-package-only finding was exhibited on this // fixture, and a pin asserting one would be asserting something unmeasured. - const strict = await runCli(['lint', '--json', '--strict'], dirs.flip); + const strict = runs.lintStrictFlip; const payload = payloadOf(strict, 'os lint --json --strict'); expect(payload.strict).toBe(true); expect(payload.failing).toBe(1); @@ -287,21 +304,21 @@ describe('#18778 — `os lint` and `os build` report the same per-package findin // …and the same project without `--strict` still exits 0, so what moved is // the strict verdict and not the default one. - const plain = await runCli(['lint', '--json'], dirs.flip); + const plain = runs.lintFlip; expect(plain.code).toBe(0); expect(payloadOf(plain, 'os lint --json').passed).toBe(true); - }, 180_000); + }); - it('CONTROL — a single-package project raises NO per-package finding on either door', async () => { + it('CONTROL — a single-package project raises NO per-package finding on either door', () => { // "Present" must be distinguishable from "always present": the prefix this // file matches on is not something either command emits unconditionally, and // `os lint --strict` still exits 1 there for the ORDINARY warning, which is // how the case above is read as a change and not as a constant. - const build = await runCli(['build', '--json'], dirs.single); - const lint = await runCli(['lint', '--json'], dirs.single); + const build = runs.buildSingle; + const lint = runs.lintSingle; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); expect(lint.code, `os lint --json failed:\n${lint.stdout}${lint.stderr}`).toBe(0); expect(buildPerPackage(payloadOf(build, 'os build --json').warnings as unknown[])).toEqual([]); expect(lintPerPackage(payloadOf(lint, 'os lint --json').issues as unknown[])).toEqual([]); - }, 180_000); + }); }); diff --git a/packages/cli/test/package-union-readers.test.ts b/packages/cli/test/package-union-readers.test.ts index 1bf26c93133..f7b3928ddd5 100644 --- a/packages/cli/test/package-union-readers.test.ts +++ b/packages/cli/test/package-union-readers.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 50 — spawns the real producer once per single-cause fixture: nine CLI spawns across three beforeAll hooks, each a distinct triple (`os build`, `os validate`, `os lint --strict`, `os i18n check`, `os i18n extract` over five fixtures); slowest CI reading 32.22 s (run 40447801748) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * #22238 / #22189 — the CLI readers that judged only a multi-package diff --git a/packages/cli/test/picklist-reference-doors.test.ts b/packages/cli/test/picklist-reference-doors.test.ts index b451356a102..e202ea0d695 100644 --- a/packages/cli/test/picklist-reference-doors.test.ts +++ b/packages/cli/test/picklist-reference-doors.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 80 — spawns the real producer once per single-cause fixture: 11 CLI spawns over four fixtures, each a distinct command, face or fixture (`os validate` json and text, `os build`, `os lint`); slowest CI reading 57.37 s (run 40447801748) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * The `picklist` kind through the three authoring doors, over the real CLI. diff --git a/packages/cli/test/stack-conversion-record-door.test.ts b/packages/cli/test/stack-conversion-record-door.test.ts index 67d0548400e..1df1e5f8886 100644 --- a/packages/cli/test/stack-conversion-record-door.test.ts +++ b/packages/cli/test/stack-conversion-record-door.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 180 — spawns the real producer once per single-cause fixture: 24 CLI spawns, one per case leg, each a distinct (command, flags, fixture) triple across `os validate` / `os build` / `os lint` over eight fixtures; slowest CI reading 141.61 s (run 40392443783) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * The ADR-0087 conversions a stack PRODUCER applied reach `os validate` and diff --git a/packages/cli/test/stack-provenance-door.test.ts b/packages/cli/test/stack-provenance-door.test.ts index b1f1016ecc5..7f19af5b340 100644 --- a/packages/cli/test/stack-provenance-door.test.ts +++ b/packages/cli/test/stack-provenance-door.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 80 — spawns the real producer once per single-cause fixture: 12 CLI spawns, `os validate` and `os build` once each over six fixtures, every one a distinct triple; slowest CI reading 60.77 s (run 40392443783) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * `os validate` and `os build` accept one authoring shape (#20367 ruling B). diff --git a/packages/cli/test/union-fold-command-parity.test.ts b/packages/cli/test/union-fold-command-parity.test.ts index 3b0990ae5bb..c4f0c18f4fd 100644 --- a/packages/cli/test/union-fold-command-parity.test.ts +++ b/packages/cli/test/union-fold-command-parity.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 50 — spawns the real producer once per single-cause fixture: nine CLI spawns, `os validate` / `os lint` / `os build` once each over three fixtures, every one a distinct triple; slowest CI reading 33.65 s (run 40392443783) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * #17069 — the three authoring commands judge the SAME STACK, on the ADR-0130 diff --git a/packages/cli/test/validate-per-package-authoring-parity.test.ts b/packages/cli/test/validate-per-package-authoring-parity.test.ts index a97687e8732..e6445116d11 100644 --- a/packages/cli/test/validate-per-package-authoring-parity.test.ts +++ b/packages/cli/test/validate-per-package-authoring-parity.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 40 — spawns the real producer once per single-cause fixture: four CLI spawns in one beforeAll, each a distinct triple (`os build`, `os validate` over the multi-package fixture and over the single-package control); slowest CI reading 28.80 s (run 40392443783), taken with seven spawns before the repeats were shared of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * #18677, the BEHAVIOURAL half — `os validate` and `os build` report the same @@ -230,6 +231,17 @@ export default defineStack({ const dirs = { multi: '', single: '' }; +/** A cold `tsx` spawn of the CLI source entry, the per-case allowance this file always gave one. */ +const SPAWN_TIMEOUT_MS = 180_000; + +/** + * One run per distinct (command, flags, fixture) triple. The cases below used + * to spawn `os build --json` on the multi-package fixture three times and `os + * validate --json` on it twice; every case now reads the one run of its + * triple, spawned in sequence in the `beforeAll` below. + */ +const runs = {} as Record<'buildMulti' | 'validateMulti' | 'buildSingle' | 'validateSingle', Run>; + function plant(config: string): string { const dir = mkdtempSync(join(tmpdir(), 'os-ppparity-')); mkdirSync(join(dir, 'src'), { recursive: true }); @@ -244,20 +256,24 @@ function plant(config: string): string { } describe('#18677 — `os validate` and `os build` report the same per-package advisory set', () => { - beforeAll(() => { + beforeAll(async () => { dirs.multi = plant(CONFIG_MULTI); dirs.single = plant(CONFIG_SINGLE); - }); + runs.buildMulti = await runCli(['build', '--json'], dirs.multi); + runs.validateMulti = await runCli(['validate', '--json'], dirs.multi); + runs.buildSingle = await runCli(['build', '--json'], dirs.single); + runs.validateSingle = await runCli(['validate', '--json'], dirs.single); + }, 4 * SPAWN_TIMEOUT_MS); afterAll(() => { for (const dir of Object.values(dirs)) if (dir) rmSync(dir, { recursive: true, force: true }); }); - it('the multi-package fixture reaches the pass at all — and its survivor is NOT an echo', async () => { + it('the multi-package fixture reaches the pass at all — and its survivor is NOT an echo', () => { // Asserted BEFORE any claim about parity: a fixture that never reaches the // per-package pass makes every comparison below vacuous, which is the exact // way this defect stayed invisible. - const build = await runCli(['build', '--json'], dirs.multi); + const build = runs.buildMulti; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); const warnings = payloadOf(build, 'os build --json').warnings as unknown[]; expect(perPackageWarnings(warnings).length).toBeGreaterThan(0); @@ -276,12 +292,12 @@ describe('#18677 — `os validate` and `os build` report the same per-package ad PER_PACKAGE_WHERE.test(named(industryWarnings[0])), 'the `industry` finding is being raised by the UNION run — the survivor would be an echo', ).toBe(true); - }, 180_000); + }); - it('`os validate` reports every per-package advisory `os build` does', async () => { + it('`os validate` reports every per-package advisory `os build` does', () => { // The pin. On `origin/main` 09e16a574 this read `build: 1, validate: 0`. - const build = await runCli(['build', '--json'], dirs.multi); - const validate = await runCli(['validate', '--json'], dirs.multi); + const build = runs.buildMulti; + const validate = runs.validateMulti; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); expect(validate.code, `os validate --json failed:\n${validate.stdout}${validate.stderr}`).toBe(0); @@ -294,29 +310,29 @@ describe('#18677 — `os validate` and `os build` report the same per-package ad missingFromValidate, 'these per-package findings ride `os build` and `os validate` cannot see them — the #18677 false-clean set', ).toEqual([]); - }, 180_000); + }); - it('…and nothing per-package rides `os validate` that `os build` does not report either', async () => { + it('…and nothing per-package rides `os validate` that `os build` does not report either', () => { // The reverse end. Parity is an equality, and a validate that over-reports // is its own defect — an author fixing a finding the command that SHIPS // never raises. - const build = await runCli(['build', '--json'], dirs.multi); - const validate = await runCli(['validate', '--json'], dirs.multi); + const build = runs.buildMulti; + const validate = runs.validateMulti; const bw = payloadOf(build, 'os build --json').warnings as unknown[]; const vw = payloadOf(validate, 'os validate --json').warnings as unknown[]; const inBuild = new Set(perPackageWarnings(bw)); expect(perPackageWarnings(vw).filter((w) => !inBuild.has(w))).toEqual([]); - }, 180_000); + }); - it('CONTROL — a single-package project raises NO per-package finding on either door', async () => { + it('CONTROL — a single-package project raises NO per-package finding on either door', () => { // "Present" must be distinguishable from "always present": the prefix this // file matches on is not something either command emits unconditionally. - const build = await runCli(['build', '--json'], dirs.single); - const validate = await runCli(['validate', '--json'], dirs.single); + const build = runs.buildSingle; + const validate = runs.validateSingle; expect(build.code, `os build --json failed:\n${build.stdout}${build.stderr}`).toBe(0); expect(validate.code, `os validate --json failed:\n${validate.stdout}${validate.stderr}`).toBe(0); expect(perPackageWarnings(payloadOf(build, 'os build --json').warnings as unknown[])).toEqual([]); expect(perPackageWarnings(payloadOf(validate, 'os validate --json').warnings as unknown[])).toEqual([]); - }, 180_000); + }); }); diff --git a/packages/cli/test/validate-view-container-name.test.ts b/packages/cli/test/validate-view-container-name.test.ts index 4ae58d763f0..15ec45c5b8c 100644 --- a/packages/cli/test/validate-view-container-name.test.ts +++ b/packages/cli/test/validate-view-container-name.test.ts @@ -1,4 +1,5 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// test-budget: 30 — spawns the real producer once per single-cause fixture: four CLI spawns, `os validate` json and text over three fixtures, every one a distinct triple; slowest CI reading 20.34 s (run 40392443783) of the three scheduled CI runs after the oclif test manifest (PR #26256: 40392443783, 40424746941, 40447801748), x 1.25, rounded up /** * [#20331] `os validate` refuses a `views:` container whose own `name`