feat(cache): restore output files on cache hit#321
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79f428a501
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let needs_fspy = cache_metadata.input_config.includes_auto | ||
| || cache_metadata.output_config.includes_auto; |
There was a problem hiding this comment.
Separate input/output negative filters for auto tracking
This now enables fspy whenever output_config.includes_auto is true, but the filter passed to path tracking is still derived only from input_config.negative_globs, so writes that match input negatives are dropped before output archiving. In execute_spawn, a config like input: [{auto:true}, "!dist/**"] with default auto output will never record dist/** writes in path_writes, causing cache hits to replay logs but fail to restore expected output files.
Useful? React with 👍 / 👎.
| sorted_files.sort(); | ||
|
|
||
| // Create archive with UUID filename | ||
| let archive_name: Str = vite_str::format!("{}.tar.zst", uuid::Uuid::new_v4()); |
There was a problem hiding this comment.
Clean up superseded output archives on cache overwrite
A fresh UUID archive filename is generated on every successful cache write, but the previous archive file is never removed when the same cache key is updated, so old tarballs become orphaned. Re-running tasks over time will continuously accumulate stale *.tar.zst files in the cache directory and can cause unbounded disk growth even though only the latest archive is reachable from cache.db.
Useful? React with 👍 / 👎.
Archives output files after a successful run and restores them on cache hit. Defaults to automatically tracking files the task writes; accepts globs (e.g. `"dist/**"`), `{ "auto": true }`, and negative patterns (`"!dist/cache/**"`).
Squashed rebase of #321 onto main after the spawn decompose refactor and wincode migration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9de20eb to
b020bf5
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b020bf53ba
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| pub input_config: ResolvedGlobConfig, | ||
| /// Resolved output configuration that affects cache restoration. | ||
| /// Glob patterns are workspace-root-relative. | ||
| pub output_config: ResolvedGlobConfig, |
There was a problem hiding this comment.
Bump cache schema version after key/value layout change
Adding output_config to CacheEntryKey and output_archive to CacheEntryValue changes the serialized blob format, but load_from_path still treats schema version 11 as current. On upgrade with an existing cache.db, old rows are deserialized with the new schema in get_cache_key_by_execution_key/get_by_cache_key, which can fail and surface as a cache lookup error that fails task execution instead of cleanly missing. Please version-bump and reset/migrate old cache rows.
Useful? React with 👍 / 👎.
| if metadata.input_config.includes_auto || metadata.output_config.includes_auto { | ||
| // Resolve input negative globs for fspy path filtering |
There was a problem hiding this comment.
Avoid inferring input reads when only output auto is enabled
This enables fspy whenever output auto-tracking is on (which is the default when output is omitted), even if input auto-tracking is disabled. The later post-run fingerprint path still consumes path_reads, so tasks that set input: [] or explicit-only inputs unexpectedly regain inferred input dependencies and can miss cache hits due to unrelated reads. Read fingerprinting should remain gated by input_config.includes_auto.
Useful? React with 👍 / 👎.
| .input_config | ||
| .negative_globs | ||
| .iter() |
There was a problem hiding this comment.
Stop filtering output auto writes with input negatives
The fspy filter is built from input_config.negative_globs, but TrackedPathAccesses::from_raw applies that filter to writes as well as reads. If a task excludes dist/** from inputs (a common pattern) and relies on default output auto-tracking, writes under dist are dropped before archiving, so cache hits won't restore those outputs. Output write collection needs filtering based on output_config negatives, not input negatives.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds output file archiving/restoration to the task execution cache so cache hits can restore build artifacts (e.g., dist/) in addition to replaying stdout/stderr.
Changes:
- Introduces an
outputcache config (same glob/auto/negative semantics asinput) and includes it in cache keys/metadata. - Archives resolved output files into
tar.zston successful cache updates and extracts them on cache hits. - Updates docs and regenerates plan/e2e snapshots to reflect the new cache behavior and schema.
Reviewed changes
Copilot reviewed 102 out of 103 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| docs/output-restoration.md | New user-facing documentation for output restoration. |
| docs/output-restoration-research.md | Research notes on build-tool compatibility/edge cases. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc | Snapshot updated to include output_config. |
| crates/vite_task_plan/src/plan.rs | Plumbs output_config into planned cache metadata. |
| crates/vite_task_plan/src/cache_metadata.rs | Adds output_config to CacheMetadata. |
| crates/vite_task_graph/src/config/user.rs | Adds user-facing output field to cache config. |
| crates/vite_task_graph/src/config/mod.rs | Resolves output_config; renames to ResolvedGlobConfig. |
| crates/vite_task_graph/run-config.ts | Updates TS run-config schema to include output. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json | New e2e fixture covering output restoration modes. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/src/main.ts | Fixture source file for cache invalidation tests. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_config_change_invalidates_cache.md | New snapshot: output config change invalidates cache. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/negative_output___excluded_files_not_restored.md | New snapshot: negative output globs exclude restoration. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/glob_output___only_matched_files_restored.md | New snapshot: glob outputs restore matched files only. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output_with_non_auto_input.md | New snapshot: auto output with explicit input globs. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output___files_restored_on_cache_hit.md | New snapshot: auto output restored on cache hit. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml | Adds e2e scenarios for output restoration. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/package.json | Adds fixture package manifest. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/positive_globs___hit_on_read_but_unmatched_file.md | Snapshot updated for new cache behavior. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/fspy_env___not_set_when_auto_inference_disabled.md | Snapshot updated for new FSPY behavior. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/folder_input___hit_despite_file_changes_and_folder_deletion.md | Snapshot updated for new cache behavior. |
| crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/empty_input___hit_despite_file_changes.md | Snapshot updated for new cache behavior. |
| crates/vite_task_bin/src/vtt/write_file.rs | Ensures parent dirs exist before writing fixture files. |
| crates/vite_task_bin/src/lib.rs | Adds output: None to default task cache config. |
| crates/vite_task/src/session/reporter/summary.rs | Treats OutputConfig mismatch as config-changed in summary. |
| crates/vite_task/src/session/mod.rs | Passes cache directory path into execution layer. |
| crates/vite_task/src/session/execute/mod.rs | Implements archive creation/extraction and output collection. |
| crates/vite_task/src/session/execute/glob_inputs.rs | Adds helper to collect globbed paths for outputs. |
| crates/vite_task/src/session/cache/mod.rs | Adds output_config to cache keys; stores output_archive. |
| crates/vite_task/src/session/cache/display.rs | Displays output-config cache-miss reason inline. |
| crates/vite_task/src/session/cache/archive.rs | New tar+zstd archive create/extract helpers. |
| crates/vite_task/docs/task-cache.md | Partially updates cache docs for ResolvedGlobConfig. |
| crates/vite_task/Cargo.toml | Adds dependencies for archiving (tar/uuid/zstd). |
| Cargo.toml | Adds workspace dependency for zstd. |
| Cargo.lock | Updates lockfile for new deps and version bumps. |
| CHANGELOG.md | Notes new output field and output restoration behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let fspy = | ||
| if metadata.input_config.includes_auto || metadata.output_config.includes_auto { | ||
| // Resolve input negative globs for fspy path filtering | ||
| // (already workspace-root-relative). Output negatives are applied | ||
| // later in `collect_and_archive_outputs`. | ||
| match metadata | ||
| .input_config | ||
| .negative_globs | ||
| .iter() | ||
| .map(|p| Ok(wax::Glob::new(p.as_str())?.into_owned())) | ||
| .collect::<anyhow::Result<Vec<_>>>() | ||
| { | ||
| Ok(negs) => Some(negs), | ||
| Err(err) => { | ||
| leaf_reporter.finish( | ||
| None, | ||
| CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), | ||
| Some(ExecutionError::PostRunFingerprint(err)), | ||
| ); | ||
| return SpawnOutcome::Failed; | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| None | ||
| }; | ||
| } else { | ||
| None | ||
| }; |
There was a problem hiding this comment.
fspy is enabled when either input_config.includes_auto or output_config.includes_auto is true, but the cache update path still fingerprints all fspy reads. This makes "output auto" implicitly re-enable inferred input tracking even when the user disabled input auto, causing unexpected cache misses (and contradicting the stated input/output independence). Consider only using fspy reads for post-run fingerprinting when input_config.includes_auto is true, while still using fspy writes for output archiving.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Archives output files after a successful run and restores them on cache hit. Defaults to automatically tracking files the task writes; accepts globs (e.g. `"dist/**"`), `{ "auto": true }`, and negative patterns (`"!dist/cache/**"`).
Squashed rebase of #321 onto main after the spawn decompose refactor and wincode migration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Output writes were being dropped before archiving when paths matched
an input-side negative glob. `TrackedPathAccesses::from_raw` applied one
shared negatives list to both reads and writes, so a common config like
`input: [{auto:true}, "!dist/**"]` with default auto output left
`dist/**` out of the archive and the cache-hit replay failed to restore
output files.
Move user-configured negative filtering out of `from_raw` (which now
only normalises paths and skips `.git`). Reads are filtered by input
negatives inside the cache-update path; writes are filtered by output
negatives inside `collect_and_archive_outputs` as before. Adds an e2e
test `input_negative_does_not_drop_output_writes` to cover the regression.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
`CacheEntryKey` now carries `output_config` and `CacheEntryValue` now carries `output_archive`, so the serialized blob layout changed. Bump `PRAGMA user_version` to 12 and extend the reset range to include 11 so existing databases are wiped cleanly on upgrade instead of failing deserialization mid-lookup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the `&& vtt print done` tail from every task — it was padding to make cache-hit replay visible (write-only tasks have silent stdout) and to give the summary multiple items. Neither is load-bearing: each task already asserts restoration via an external `vtt print-file`. Restructure `explicit_input_ignores_fspy_reads` to a single `vtt print-file README.md` task. The second run captures "v1" replayed from the cache even after README.md has been changed to "v2" — a direct, self-evident assertion that the read was ignored instead of relying on partial-hit counters like `2/3 cache hit`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follows the convention introduced in main (#347): per-`[[e2e]]` and per- step descriptions use the TOML `comment` field instead of bare `#` lines, so they render under the snapshot headings and inside each step's block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_test - The three-line module-level header in `tracked_accesses.rs` was written as `///` followed by a blank line, which newer clippy flags as `empty_line_after_doc_comments` (the `///` attached itself to `PathRead` below). Switch it to `//` so it is a plain comment. - Apply oxfmt to `output_cache_test/snapshots.toml` to unblock the Format and Check Deps CI step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0008bd7 to
994624a
Compare

Previously, a cache hit only replayed terminal output (stdout/stderr). Build artifacts like
dist/were not restored, so downstream tasks or users had to re-run even on a cache hit.Now, output files written during task execution are archived and restored automatically. The
outputfield reuses the same config types and resolution logic asinput(renamedResolvedInputConfig→ResolvedGlobConfigto reflect this).Config examples:
Test plan
cargo clippy -- -D warningsclean🤖 Generated with Claude Code