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 }}
Repository navigation
Existence probes of pnpm-workspace.yaml become content inputs, so any manifest edit misses every task #860
In a pnpm workspace, every task that loads a Vite config records pnpm-workspace.yaml (and lerna.json) in every ancestor directory as a content input. An edit to an unrelated line of pnpm-workspace.yaml, for example a new catalog entry that no package uses, then misses the cache of every task. In our 199-task monorepo one such edit dropped a repeat run to 1 cache hit out of 184 tasks.
The reads come from Vite's searchForWorkspaceRoot (packages/vite/src/node/server/searchRoot.ts), which calls fs.existsSync on those names in each ancestor to find the root. fspy records access and stat as READ (crates/fspy_preload_unix/src/interceptions/access.rs, stat.rs; AccessMode in crates/fspy_shared/src/ipc/mod.rs has only READ, WRITE and READ_DIR), and the fingerprint then hashes the file content (crates/vt/src/session/execute/fingerprint.rs). So a probe that only asks "does this file exist" becomes a dependency on the file's bytes.
Repro with vite-plus 1.3.0:
A workspace with three packages, each with a vite.config.ts and a test task, and a root pnpm-workspace.yaml with packages: [packages/*] and a catalog: block.
vp run -r test twice. The second run is all cache hits.
Add an unused line to the catalog, for example left-pad: 1.3.0, and run vp run -r test again. Every task misses with 'pnpm-workspace.yaml' modified.
ignoreInput from vite-plus does not fix this correctly. It drops the path for the whole task, so a task whose own code reads the manifest (a catalog lint, for example) would replay a stale result, and creating or deleting a marker file, which can change the workspace root Vite selects, would no longer invalidate anything.
A fix that keeps both properties would record existence probes separately: fingerprint whether the path exists for a probe-only access, and promote the path to a content input when the same task also opens and reads it. stat may need care, because some callers use size or mtime.
I looked into this and the cause matches what you describe: fspy reports access/faccessat/stat* (and NtQueryAttributesFile on Windows) as Read, so tracked_accesses.rs turns the existence probe into a content input.
The redaction approach from #850/#824 would be small, but it drops content tracking for pnpm-workspace.yaml entirely, which breaks the catalog-lint case you mention. Doing it properly seems to need:
an Exists access mode in fspy_shared (wire format change),
emitting it from the unix preload, the Linux syscall handler and the Windows detours,
promoting exists-only paths to content reads in tracked_accesses.rs when the same task also reads the file,
a PathFingerprint::Exists(bool) variant in fingerprint.rs, which changes the cache entry schema,
an e2e fixture plus fspy tests.
Is this the direction you'd want, and would you take an outside PR for it? The cache schema change and how stat should be classified (some callers do use size/mtime) feel like your call, so I didn't want to start without checking.
Activity
tlq5l commentedon Oct 20, 2026
I looked into this and the cause matches what you describe: fspy reports
access/faccessat/stat*(andNtQueryAttributesFileon Windows) asRead, sotracked_accesses.rsturns the existence probe into a content input.The redaction approach from #850/#824 would be small, but it drops content tracking for
pnpm-workspace.yamlentirely, which breaks the catalog-lint case you mention. Doing it properly seems to need:Existsaccess mode infspy_shared(wire format change),tracked_accesses.rswhen the same task also reads the file,PathFingerprint::Exists(bool)variant infingerprint.rs, which changes the cache entry schema,Is this the direction you'd want, and would you take an outside PR for it? The cache schema change and how
statshould be classified (some callers do use size/mtime) feel like your call, so I didn't want to start without checking.