You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
turbo test inputs have the same out-of-package hole #3514 closed for type-check — the root vitest.config.mts every package re-exports is not hashed #4178
Found while implementing #3514 (PR #4176). Filed unassigned; not fixed there because that card is scoped to the type-check task.
The gap
#3514 established the mechanism: turbo hashes a task from its inputs, $TURBO_DEFAULT$ covers only files inside the package directory, and globalDependencies is unset — so any file a task reads from elsewhere in the repo is invisible to the cache key, and turbo replays the previous verdict instead of re-running. CI persists .turbo/cache through actions/cache, so the stale result travels.
The test task has exactly that shape, and every entry in its list is package-relative:
vitest.config.* and vitest.setup.* look like they cover the Vitest configuration, but they resolve inside the package. The files that actually decide how a package's tests run live at the repo root, and every package reaches them:
$ cat packages/core/vitest.config.ts
import rootConfig from '../../vitest.config.mts';
export default rootConfig;
The root vitest.config.mts owns the unit / dom / dom-heavy project split, sharedExclude, the domTsTests and heavyDomTests lists, and the alias table. The four root vitest.setup.* files decide which package graphs are registered before a test renders. None of them is hashed by any package's test task.
Measured
On claude/issue-3514-turbo-inputs-guard, @object-ui/core:
$ npx turbo run test --filter @object-ui/core --dry=json
baseline 2e2087e2c30ef125
after touching root vitest.config.mts 2e2087e2c30ef125 <- frozen
after touching root vitest.setup.base.ts 2e2087e2c30ef125 <- frozen
The cache key does not move. The equivalent measurement on type-check before #4176 produced a FULL TURBO replay in 44ms over a real TS2688, with --force on the same tree exiting 2 — so this is the same defect, not a theoretical one.
Arguably worse than the type-check instance: a package's type-check reaches out only where a tsconfig says so, whereas every package's test run goes through the root Vitest config by construction.
Suggested shape
Symmetric with what #4176 landed, plus the guard question:
Add the root files to the test task's inputs ($TURBO_ROOT$/vitest.config.mts, $TURBO_ROOT$/vitest.setup.*).
cloud#1133 — the same family one repo over: turbo testinputs covering only the package's own src/test while repo-level assertion tests read from outside it. Worth reading alongside this.
Claim: PM loop round 6 (rolling slot refill; the #3514 successor — same cache-poisoning class, test task side)
Session: session_017Qqyix2QcnpUC9XeYVDzx3 · Branch: claude/issue-4178-turbo-test-inputs · Worktree: objectui-issue-4178
File surface: turbo.json (test task inputs) + a derivation extension in scripts/__tests__/ (sibling or extension of #4176's guard — read its architecture first; the filing notes the derivation is DIFFERENT IN KIND: vitest re-export chains, not tsconfig includes). Serial constraints: PR #4176 (armed, unmerged) owns turbo.json + the guard file — stack on claude/issue-3514-turbo-inputs-guard if it has not merged at start; disjoint from #4167/#4145/#2794/#2627 in flight.
Container & model: S, mode:subagent, model: opus
Direction (the #3514 ruling's logic carries over): the measured entries ship (root vitest.config.mts + the four root vitest.setup.* files the per-package configs re-export) AND the derivation guard extends to the test task — walking each package's vitest config import chain (the filing says every per-package config literally import rootConfig from '../../vitest.config.mts'; derive the chain, don't hardcode the observation). Reproduce the frozen-hash baseline (@object-ui/core#test at the filing's hash after touching both files) → fix flips it to a moving hash + cache miss, per #4176's evidence-chain shape. If chain-walking proves brittle (dynamic imports, non-literal paths), the honest fallback is pinned entries + a docblock narrowing, reported as such.
Measurement corrected the filing twice (10 out-of-package files, not 5; the "every config re-exports" claim false for 16 of 39) and the derivation is built where the reality is: Vitest's own config resolution mirrored and verified against the real binary, transitive relative imports, AND file-valued options — the last being load-bearing since two packages reach out ONLY via setupFiles, which the card's proposed import-chain walk would have missed. The shared turbo-side plumbing extracted so #4176's guard and this one cannot drift (its unchanged 43 the preservation evidence). The end-to-end run has the full evidence ladder including turbo replaying a PREVIOUS run's captured output timestamp-and-all — the stale-green mechanism made visible. The decisive reverse case (a probe file in a zero-derivation package, named by the guard with nothing in the PR mentioning it) proves derivation over enumeration. The blast-radius narrowing (ci.yml doesn't run turbo run test today — local + future CI only) is honestly stated where the two sibling holes are NOT so limited.
Which is why the siblings move NOW: #4184 (lint: NO inputs, LIVE in CI with persisted cache) and #4185 (build: NO inputs, dist feeding every downstream task) are packed into one stacked dispatch on this branch. The plugin-editor red (alias gap, independent of this card) gets its own card referencing #3240's ruled direction. Flipping ready + auto-merge.
Activity
yinlianghui commentedon Aug 10, 2026
Claim: PM loop round 6 (rolling slot refill; the #3514 successor — same cache-poisoning class,
testtask side)Session:
session_017Qqyix2QcnpUC9XeYVDzx3· Branch:claude/issue-4178-turbo-test-inputs· Worktree:objectui-issue-4178File surface:
turbo.json(test task inputs) + a derivation extension inscripts/__tests__/(sibling or extension of #4176's guard — read its architecture first; the filing notes the derivation is DIFFERENT IN KIND: vitest re-export chains, not tsconfig includes). Serial constraints: PR #4176 (armed, unmerged) owns turbo.json + the guard file — stack onclaude/issue-3514-turbo-inputs-guardif it has not merged at start; disjoint from #4167/#4145/#2794/#2627 in flight.Container & model: S,
mode:subagent,model: opusDirection (the #3514 ruling's logic carries over): the measured entries ship (root
vitest.config.mts+ the four rootvitest.setup.*files the per-package configs re-export) AND the derivation guard extends to the test task — walking each package's vitest config import chain (the filing says every per-package config literallyimport rootConfig from '../../vitest.config.mts'; derive the chain, don't hardcode the observation). Reproduce the frozen-hash baseline (@object-ui/core#testat the filing's hash after touching both files) → fix flips it to a moving hash + cache miss, per #4176's evidence-chain shape. If chain-walking proves brittle (dynamic imports, non-literal paths), the honest fallback is pinned entries + a docblock narrowing, reported as such.Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
ACCEPT (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4188.Measurement corrected the filing twice (10 out-of-package files, not 5; the "every config re-exports" claim false for 16 of 39) and the derivation is built where the reality is: Vitest's own config resolution mirrored and verified against the real binary, transitive relative imports, AND file-valued options — the last being load-bearing since two packages reach out ONLY via
setupFiles, which the card's proposed import-chain walk would have missed. The shared turbo-side plumbing extracted so #4176's guard and this one cannot drift (its unchanged 43 the preservation evidence). The end-to-end run has the full evidence ladder including turbo replaying a PREVIOUS run's captured output timestamp-and-all — the stale-green mechanism made visible. The decisive reverse case (a probe file in a zero-derivation package, named by the guard with nothing in the PR mentioning it) proves derivation over enumeration. The blast-radius narrowing (ci.yml doesn't runturbo run testtoday — local + future CI only) is honestly stated where the two sibling holes are NOT so limited.Which is why the siblings move NOW: #4184 (lint: NO inputs, LIVE in CI with persisted cache) and #4185 (build: NO inputs, dist feeding every downstream task) are packed into one stacked dispatch on this branch. The plugin-editor red (alias gap, independent of this card) gets its own card referencing #3240's ruled direction. Flipping ready + auto-merge.
Generated by Claude Code
ci(turbo): derive the test inputs guard from each package's Vitest co…