Skip to content

Commit d890f2f

Browse files
claude[bot]claude
andauthored
test: repo-wide vitest console-intercept disarm + arrival gate (#10374) (#13522)
* test(infra): gate every vitest-running package on disableConsoleIntercept (#10374) The late-console teardown race (#10374) is removed per suite by disableConsoleIntercept: true; this gate makes the invariant hold for the whole moving population — 38 vitest configs on 2026-08-21 were 43 by 2026-08-30, every arrival with the intercept armed, and 29 more packages run vitest with no config file at all. The sweep that applies the setting to all of them follows in this branch; the gate is what keeps the next arrival from undoing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC * fix(gate): put check-console-intercept-disarm's dispatch behind isEntrypoint (check:entry-guard) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC * test(repo-wide): disarm vitest console interception in all 72 vitest-running packages (#10374) Measured across the whole population (8,066 intercepted console RPCs per full-repo run carrying 61,086 lines, every one discarded by the non-TTY default reporter): 33/72 suites emit nothing and are disarmed for free; dogfood alone carries 67% of the volume; and the one suite that actually flaked (showcase) sits mid-tail at 340 lines — volume does not predict the trigger, so the mechanism is removed everywhere rather than the trigger narrowed anywhere. 42 configs edited, 29 created for packages that ran vitest with no config; dogfood's setting is per-project because inline projects do not inherit the root value (measured on vitest 4.1.10). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 57827b6 commit d890f2f

73 files changed

Lines changed: 1413 additions & 4 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/lint.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,26 @@ jobs:
27092709
- name: Cross-package test inputs
27102710
run: pnpm check:cross-package-test-inputs
27112711

2712+
# Console-intercept disarm (#10374). vitest's worker forwards every
2713+
# console.* write to the main thread over RPC and DISCARDS the promise;
2714+
# a write that lands after teardown's `rpcDone()` snapshot is rejected
2715+
# into an unhandled error, failing a fully green suite (signature:
2716+
# `EnvironmentTeardownError: [vitest-worker]: Closing rpc while
2717+
# "onUserConsoleLog" was pending` — the file it names is where the
2718+
# worker WAS, not where the bug is). The window is load-width, so it
2719+
# presents as a merge-queue flake nobody can reproduce. The one general
2720+
# defence is `disableConsoleIntercept: true` in every package-root
2721+
# vitest config — it removes the mechanism (no RPC, nothing to reject)
2722+
# — and the population it must cover MOVES: five new vitest configs
2723+
# arrived in the nine days before this gate, every one with the
2724+
# intercept armed. This asserts every vitest-running package carries
2725+
# the disarm; the mechanism docblock lives in
2726+
# examples/app-showcase/vitest.config.ts and the teardown-race pin in
2727+
# that app proves the defect is still live in the installed vitest.
2728+
# Self-test first, then the real scan; reads ~72 manifests; sub-second.
2729+
- name: Console-intercept disarm
2730+
run: node scripts/check-console-intercept-disarm.mjs --self-test && node scripts/check-console-intercept-disarm.mjs
2731+
27122732
# Live-server database isolation (#10382). CI provisions ONE Postgres and
27132733
# ONE MySQL for the whole temporal-conformance job and points every live
27142734
# leg at them, and every live suite in the repo issues a `drop` when it

examples/app-crm/vitest.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import { defineConfig } from 'vitest/config';
44
import path from 'node:path';
55

66
export default defineConfig({
7+
test: {
8+
// A late console.* must not redden a green suite (#10374): vitest's worker
9+
// forwards console output over RPC and discards the promise, and a write
10+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
11+
// error — a fully green run that exits 1. Disarming removes the mechanism.
12+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
13+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
14+
disableConsoleIntercept: true,
15+
},
716
resolve: {
817
// `action-predicate-sparse-face.test.ts` (#8990) drives this app's row
918
// action predicate through the CEL engine itself, because the whole point

examples/app-todo/vitest.config.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
// This config exists for exactly one setting; everything else stays on
4+
// vitest's defaults, deliberately — a key added here re-specifies behaviour
5+
// for every test file in the package (packages/cli/vitest.config.ts's header
6+
// records the incident that taught that).
7+
import { defineConfig } from 'vitest/config';
8+
9+
export default defineConfig({
10+
test: {
11+
// A late console.* must not redden a green suite (#10374): vitest's worker
12+
// forwards console output over RPC and discards the promise, and a write
13+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
14+
// error — a fully green run that exits 1. Disarming removes the mechanism.
15+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
16+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
17+
disableConsoleIntercept: true,
18+
},
19+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
// This config exists for exactly one setting; everything else stays on
4+
// vitest's defaults, deliberately — a key added here re-specifies behaviour
5+
// for every test file in the package (packages/cli/vitest.config.ts's header
6+
// records the incident that taught that).
7+
import { defineConfig } from 'vitest/config';
8+
9+
export default defineConfig({
10+
test: {
11+
// A late console.* must not redden a green suite (#10374): vitest's worker
12+
// forwards console output over RPC and discards the promise, and a write
13+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
14+
// error — a fully green run that exits 1. Disarming removes the mechanism.
15+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
16+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
17+
disableConsoleIntercept: true,
18+
},
19+
});

packages/adapters/hono/vitest.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ import path from 'node:path';
55

66
export default defineConfig({
77
test: {
8+
// A late console.* must not redden a green suite (#10374): vitest's worker
9+
// forwards console output over RPC and discards the promise, and a write
10+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
11+
// error — a fully green run that exits 1. Disarming removes the mechanism.
12+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
13+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
14+
disableConsoleIntercept: true,
815
globals: true,
916
environment: 'node',
1017
},

packages/cli/vitest.config.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
// This package had NO vitest config until #9832, and that is the fact this
44
// header exists to keep visible: adding one changes how every test file in
55
// `packages/cli` is configured, not just the file that needed it. So the
6-
// config is deliberately minimal — anchored `resolve.alias` entries and no
7-
// `test` block at all, because the test files here run on vitest's defaults
8-
// (`globals: false`, `environment: 'node'`) and a `test` block would silently
9-
// re-specify them. Sibling configs in this repo do carry
6+
// config is deliberately minimal — anchored `resolve.alias` entries and a
7+
// `test` block that only carries keys with a recorded warrant (`server.deps`,
8+
// and the #10374 console-intercept disarm), because the test files here run on
9+
// vitest's defaults (`globals: false`, `environment: 'node'`) and re-specifying
10+
// THOSE keys would silently flip them. Sibling configs in this repo do carry
1011
// `test: { globals: true, … }`; copying that shape here would have flipped
1112
// `globals` for every existing file in the package.
1213
//
@@ -378,6 +379,13 @@ export default defineConfig({
378379
],
379380
},
380381
test: {
382+
// A late console.* must not redden a green suite (#10374): vitest's worker
383+
// forwards console output over RPC and discards the promise, and a write
384+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
385+
// error — a fully green run that exits 1. Disarming removes the mechanism.
386+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
387+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
388+
disableConsoleIntercept: true,
381389
server: {
382390
deps: {
383391
external: [/packages[\/]types[\/]dist/],

packages/client-react/vitest.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import { defineConfig } from 'vitest/config';
22

33
export default defineConfig({
44
test: {
5+
// A late console.* must not redden a green suite (#10374): vitest's worker
6+
// forwards console output over RPC and discards the promise, and a write
7+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
8+
// error — a fully green run that exits 1. Disarming removes the mechanism.
9+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
10+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
11+
disableConsoleIntercept: true,
512
// The only DOM environment in the workspace, and deliberately so (#4682):
613
// these hooks are exercised through React's real renderer, so `document`
714
// and friends must exist. Every other package here runs `environment:

packages/client/vitest.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ import path from 'path';
33

44
export default defineConfig({
55
test: {
6+
// A late console.* must not redden a green suite (#10374): vitest's worker
7+
// forwards console output over RPC and discards the promise, and a write
8+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
9+
// error — a fully green run that exits 1. Disarming removes the mechanism.
10+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
11+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
12+
disableConsoleIntercept: true,
613
// Exclude integration tests that require a running server
714
exclude: [
815
'**/node_modules/**',

packages/cloud-connection/vitest.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import { defineConfig } from 'vitest/config';
44
import path from 'node:path';
55

66
export default defineConfig({
7+
test: {
8+
// A late console.* must not redden a green suite (#10374): vitest's worker
9+
// forwards console output over RPC and discards the promise, and a write
10+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
11+
// error — a fully green run that exits 1. Disarming removes the mechanism.
12+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
13+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
14+
disableConsoleIntercept: true,
15+
},
716
resolve: {
817
// One entry, for `canonical-expression-envelopes.test.ts` (#11480) — the
918
// only suite here that imports `@objectstack/lint` as a VALUE. It runs the
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
// This config exists for exactly one setting; everything else stays on
4+
// vitest's defaults, deliberately — a key added here re-specifies behaviour
5+
// for every test file in the package (packages/cli/vitest.config.ts's header
6+
// records the incident that taught that).
7+
import { defineConfig } from 'vitest/config';
8+
9+
export default defineConfig({
10+
test: {
11+
// A late console.* must not redden a green suite (#10374): vitest's worker
12+
// forwards console output over RPC and discards the promise, and a write
13+
// landing after teardown's rpcDone() snapshot is rejected into an unhandled
14+
// error — a fully green run that exits 1. Disarming removes the mechanism.
15+
// Mechanism + measured costs: examples/app-showcase/vitest.config.ts.
16+
// Enforced repo-wide by scripts/check-console-intercept-disarm.mjs.
17+
disableConsoleIntercept: true,
18+
},
19+
});

0 commit comments

Comments
 (0)