Skip to content

feat(cache): restore output files on cache hit#321

Draft
branchseer wants to merge 7 commits intomainfrom
feat/output-restoration
Draft

feat(cache): restore output files on cache hit#321
branchseer wants to merge 7 commits intomainfrom
feat/output-restoration

Conversation

@branchseer
Copy link
Copy Markdown
Member

@branchseer branchseer commented Apr 6, 2026

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 output field reuses the same config types and resolution logic as input (renamed ResolvedInputConfigResolvedGlobConfig to reflect this).

Config examples:

// Default: auto-detect written files (same as input default)
{ "command": "tsc --outDir dist" }

// Explicit globs
{ "command": "tsc", "output": ["dist/**"] }

// Auto with exclusions
{ "command": "webpack", "output": [{ "auto": true }, "!dist/cache/**"] }

// Disable output restoration
{ "command": "vitest run", "output": [] }

Test plan

  • E2E: auto output detection restores files on cache hit
  • E2E: glob output only restores matched files
  • E2E: auto output works with non-auto input
  • E2E: negative output globs exclude files from restoration
  • E2E: changing output config invalidates cache
  • All existing E2E and plan snapshot tests pass
  • cargo clippy -- -D warnings clean

🤖 Generated with Claude Code

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +410 to +411
let needs_fspy = cache_metadata.input_config.includes_auto
|| cache_metadata.output_config.includes_auto;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@branchseer branchseer marked this pull request as draft April 13, 2026 07:25
branchseer added a commit that referenced this pull request Apr 19, 2026
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>
@branchseer branchseer force-pushed the feat/output-restoration branch from 9de20eb to b020bf5 Compare April 19, 2026 14:38
@branchseer
Copy link
Copy Markdown
Member Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +48 to +51
pub input_config: ResolvedGlobConfig,
/// Resolved output configuration that affects cache restoration.
/// Glob patterns are workspace-root-relative.
pub output_config: ResolvedGlobConfig,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +433 to +434
if metadata.input_config.includes_auto || metadata.output_config.includes_auto {
// Resolve input negative globs for fspy path filtering
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +438 to +440
.input_config
.negative_globs
.iter()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 output cache config (same glob/auto/negative semantics as input) and includes it in cache keys/metadata.
  • Archives resolved output files into tar.zst on 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.

Comment on lines +432 to +456
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
};
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@branchseer branchseer mentioned this pull request Apr 20, 2026
9 tasks
branchseer and others added 7 commits April 20, 2026 11:55
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>
@branchseer branchseer force-pushed the feat/output-restoration branch from 0008bd7 to 994624a Compare April 20, 2026 04:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants