Skip to content

Commit 1efa98a

Browse files
branchseerclaude
andcommitted
fix(cache): don't infer input reads when input auto is disabled
When `output_config.includes_auto` is true (the default), fspy is enabled for write tracking. Previously this caused fspy reads to flow into `PostRunFingerprint` even if the user set `input: []` or an explicit-only list, silently re-introducing inferred input dependencies and causing spurious cache misses from unrelated reads. Gate `inferred_reads` on `input_config.includes_auto`: when false, pass an empty map to the fingerprint and overlap check, while still keeping fspy writes available for output archiving. Adds an e2e test `explicit_input_ignores_fspy_reads` to cover this. Also updates three `input_cache_test` snapshots that were capturing the bug as expected behaviour (cache miss on unrelated file change) — they now correctly reflect cache hits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b5529aa commit 1efa98a

8 files changed

Lines changed: 96 additions & 13 deletions

File tree

crates/vite_task/src/session/execute/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -572,13 +572,14 @@ pub async fn execute_spawn(
572572
.as_ref()
573573
.map(|raw| TrackedPathAccesses::from_raw(raw, cache_base_path));
574574

575-
// Inferred input reads: filter path_reads by input negatives.
576-
// Separate from write filtering (which uses output negatives inside
577-
// `collect_and_archive_outputs`) so users can set `!dist/**` on
578-
// input without accidentally dropping writes to `dist`.
575+
// Inferred input reads: gated by `input_config.includes_auto` and
576+
// filtered by input negatives. When input auto is disabled, no reads
577+
// contribute to the fingerprint even if fspy was enabled for output
578+
// tracking.
579579
let empty_reads = HashMap::default();
580580
let inferred_reads: HashMap<RelativePathBuf, tracked_accesses::PathRead> =
581-
if let Some(pa) = path_accesses.as_ref()
581+
if metadata.input_config.includes_auto
582+
&& let Some(pa) = path_accesses.as_ref()
582583
&& let Some(negatives) = fspy_input_negatives.as_deref()
583584
{
584585
pa.path_reads

crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/empty_input___hit_despite_file_changes.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ export const main = 'initial';
1818
## `vt run empty-inputs`
1919

2020
```
21-
$ vtt print-file ./src/main.ts ○ cache miss: 'src/main.ts' modified, executing
22-
export const main = 'modified';
21+
$ vtt print-file ./src/main.ts ◉ cache hit, replaying
22+
export const main = 'initial';
23+
24+
---
25+
vt run: cache hit.
2326
```

crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/folder_input___hit_despite_file_changes_and_folder_deletion.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ export const main = 'initial';
1818
## `vt run folder-input`
1919

2020
```
21-
$ vtt print-file src/main.ts ○ cache miss: 'src/main.ts' modified, executing
22-
export const main = 'modified';
21+
$ vtt print-file src/main.ts ◉ cache hit, replaying
22+
export const main = 'initial';
23+
24+
---
25+
vt run: cache hit.
2326
```
2427

2528
## `vtt rm -rf src`
@@ -30,6 +33,9 @@ export const main = 'modified';
3033
## `vt run folder-input`
3134

3235
```
33-
$ vtt print-file src/main.ts ○ cache miss: 'main.ts' removed from 'src', executing
34-
src/main.ts: not found
36+
$ vtt print-file src/main.ts ◉ cache hit, replaying
37+
export const main = 'initial';
38+
39+
---
40+
vt run: cache hit.
3541
```

crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/positive_globs___hit_on_read_but_unmatched_file.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ export const utils = 'initial';
1919
## `vt run positive-globs-reads-unmatched`
2020

2121
```
22-
$ vtt print-file src/main.ts src/utils.ts cache miss: 'src/utils.ts' modified, executing
22+
$ vtt print-file src/main.ts src/utils.ts cache hit, replaying
2323
export const main = 'initial';
24-
export const utils = 'modified';
24+
export const utils = 'initial';
25+
26+
---
27+
vt run: cache hit.
2528
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v1

crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,29 @@ steps = [
129129
["vtt", "print-file", "dist/out.txt"],
130130
]
131131

132+
# 7. When input auto is disabled (explicit globs only), unrelated reads tracked
133+
# by fspy must NOT become inferred inputs. Default auto output still needs fspy
134+
# for write tracking, but reads outside `input: ["src/**"]` should be ignored.
135+
[[e2e]]
136+
name = "explicit_input_ignores_fspy_reads"
137+
steps = [
138+
[
139+
"vt",
140+
"run",
141+
"explicit-input-auto-output",
142+
],
143+
# Modify README.md (read by the task, NOT in input globs)
144+
[
145+
"vtt",
146+
"replace-file-content",
147+
"README.md",
148+
"v1",
149+
"v2",
150+
],
151+
# Should be a cache hit: README.md is not an input
152+
{ argv = [
153+
"vt",
154+
"run",
155+
"explicit-input-auto-output",
156+
], comment = "cache hit: README.md not in input globs" },
157+
]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# explicit_input_ignores_fspy_reads
2+
3+
## `vt run explicit-input-auto-output`
4+
5+
```
6+
$ vtt print-file README.md
7+
v1
8+
9+
$ vtt write-file dist/out.txt built
10+
11+
$ vtt print done
12+
done
13+
14+
---
15+
vt run: 0/3 cache hit (0%). (Run `vt run --last-details` for full details)
16+
```
17+
18+
## `vtt replace-file-content README.md v1 v2`
19+
20+
```
21+
```
22+
23+
## `vt run explicit-input-auto-output`
24+
25+
cache hit: README.md not in input globs
26+
27+
```
28+
$ vtt print-file README.md ◉ cache hit, replaying
29+
v1
30+
31+
$ vtt write-file dist/out.txt built ◉ cache hit, replaying
32+
33+
$ vtt print done ◉ cache hit, replaying
34+
done
35+
36+
---
37+
vt run: 3/3 cache hit (100%). (Run `vt run --last-details` for full details)
38+
```

crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
"command": "vtt write-file dist/out.txt built && vtt print done",
2929
"input": [{ "auto": true }, "!dist/**"],
3030
"cache": true
31+
},
32+
"explicit-input-auto-output": {
33+
"command": "vtt print-file README.md && vtt write-file dist/out.txt built && vtt print done",
34+
"input": ["src/**"],
35+
"cache": true
3136
}
3237
}
3338
}

0 commit comments

Comments
 (0)