From 6d03bc009bcbe70aa9010e56d90d78358cfb9c13 Mon Sep 17 00:00:00 2001 From: branchseer Date: Thu, 7 May 2026 15:00:26 +0800 Subject: [PATCH 1/2] feat(cache): add output globs for cache restoration Adds an `output` field to cached tasks: archives files matching the configured globs after a successful run and restores them on cache hit. Supports glob patterns, negative patterns, and `{pattern, base}` form with explicit base directory. When `output` is omitted or empty, no output archiving happens (matches prior behavior). Schema version bumped to 12 (CacheEntryKey carries output_config, CacheEntryValue carries output_archive). Old caches are reset on upgrade. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 1 + Cargo.lock | 43 +++++++ Cargo.toml | 1 + crates/vite_task/Cargo.toml | 3 + crates/vite_task/src/session/cache/archive.rs | 61 ++++++++++ crates/vite_task/src/session/cache/display.rs | 1 + crates/vite_task/src/session/cache/mod.rs | 60 +++++++-- .../src/session/execute/glob_inputs.rs | 52 ++++++++ crates/vite_task/src/session/execute/mod.rs | 81 +++++++++++- crates/vite_task/src/session/mod.rs | 1 + .../vite_task/src/session/reporter/summary.rs | 4 +- crates/vite_task_bin/src/lib.rs | 1 + crates/vite_task_bin/src/vtt/write_file.rs | 6 +- .../fixtures/output_cache_test/package.json | 4 + .../fixtures/output_cache_test/snapshots.toml | 38 ++++++ ...put_globs___files_restored_on_cache_hit.md | 37 ++++++ ...___negative_excludes_files_from_archive.md | 49 ++++++++ .../fixtures/output_cache_test/src/main.ts | 1 + .../fixtures/output_cache_test/vite-task.json | 16 +++ crates/vite_task_graph/run-config.ts | 11 +- crates/vite_task_graph/src/config/mod.rs | 105 ++++++++++++---- crates/vite_task_graph/src/config/user.rs | 28 +++++ crates/vite_task_plan/src/cache_metadata.rs | 8 +- crates/vite_task_plan/src/plan.rs | 41 ++++++- ...ery_tool_synthetic_task_in_user_task.jsonc | 5 + .../additional_env/snapshots/task_graph.jsonc | 10 ++ ...query___cache_enables_script_caching.jsonc | 5 + ...ching_even_when_cache_tasks_is_false.jsonc | 5 + ..._per_task_cache_true_enables_caching.jsonc | 5 + .../snapshots/task_graph.jsonc | 20 +++ .../query_echo_and_lint_with_extra_args.jsonc | 5 + .../query_lint_and_echo_with_extra_args.jsonc | 5 + .../query_normal_task_with_extra_args.jsonc | 5 + .../query_synthetic_task_in_user_task.jsonc | 5 + ...synthetic_task_in_user_task_with_cwd.jsonc | 5 + ...ic_task_with_extra_args_in_user_task.jsonc | 5 + .../cache_keys/snapshots/task_graph.jsonc | 20 +++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 10 ++ ...query_another_task_cached_by_default.jsonc | 5 + .../query_task_cached_by_default.jsonc | 5 + .../snapshots/task_graph.jsonc | 15 +++ .../cache_sharing/snapshots/task_graph.jsonc | 15 +++ .../snapshots/task_graph.jsonc | 5 + .../snapshots/task_graph.jsonc | 15 +++ ...script_cached_when_global_cache_true.jsonc | 5 + ...y_task_cached_when_global_cache_true.jsonc | 5 + .../snapshots/task_graph.jsonc | 10 ++ ..._should_put_synthetic_task_under_cwd.jsonc | 5 + ..._should_not_affect_expanded_task_cwd.jsonc | 5 + .../cd_in_scripts/snapshots/task_graph.jsonc | 15 +++ .../snapshots/task_graph.jsonc | 115 ++++++++++++++++++ .../conflict_test/snapshots/task_graph.jsonc | 15 +++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 40 ++++++ .../snapshots/task_graph.jsonc | 50 ++++++++ ...extra_args_only_reach_requested_task.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 65 ++++++++++ .../snapshots/task_graph.jsonc | 5 + .../snapshots/task_graph.jsonc | 5 + ...d___cache_enables_inner_task_caching.jsonc | 5 + ...opagates_to_nested_run_without_flags.jsonc | 5 + ...es_not_propagate_into_nested___cache.jsonc | 5 + .../snapshots/task_graph.jsonc | 20 +++ .../nested_tasks/snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 5 + .../snapshots/task_graph.jsonc | 25 ++++ .../snapshots/task_graph.jsonc | 5 + .../snapshots/task_graph.jsonc | 40 ++++++ .../script_hooks/snapshots/task_graph.jsonc | 30 +++++ .../snapshots/task_graph.jsonc | 15 +++ .../snapshots/task_graph.jsonc | 20 +++ .../snapshots/task_graph.jsonc | 10 ++ ...uery_shell_fallback_for_pipe_command.jsonc | 5 + .../shell_fallback/snapshots/task_graph.jsonc | 5 + ...does_not_affect_expanded_query_tasks.jsonc | 5 + ..._not_affect_expanded_synthetic_cache.jsonc | 5 + ..._untrackedEnv_inherited_by_synthetic.jsonc | 5 + ...h_cache_true_enables_synthetic_cache.jsonc | 5 + .../snapshots/task_graph.jsonc | 25 ++++ .../query_synthetic_in_subpackage.jsonc | 5 + .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 15 +++ .../vpr_shorthand/snapshots/task_graph.jsonc | 10 ++ .../query_dev_filter_from_root.jsonc | 5 + .../snapshots/query_dev_in_subpackage.jsonc | 5 + .../snapshots/task_graph.jsonc | 5 + .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 20 +++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 20 +++ .../snapshots/task_graph.jsonc | 10 ++ .../snapshots/task_graph.jsonc | 15 +++ 96 files changed, 1570 insertions(+), 43 deletions(-) create mode 100644 crates/vite_task/src/session/cache/archive.rs create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/package.json create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___files_restored_on_cache_hit.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___negative_excludes_files_from_archive.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/src/main.ts create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json diff --git a/CHANGELOG.md b/CHANGELOG.md index c437fce5a..8b9d75801 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +- **Added** `output` field for cached tasks: archives output files matching the configured globs after a successful run and restores them on cache hit. Patterns are relative to the package directory; supports negative patterns (e.g. `"!dist/cache/**"`) and `{pattern, base}` form for explicit base. ([#321](https://github.com/voidzero-dev/vite-task/pull/321)) - **Fixed** Windows cached tasks can now run package shims rewritten through PowerShell; default env passthrough now preserves `PATHEXT` ([#366](https://github.com/voidzero-dev/vite-task/pull/366)) - **Added** Platform support for targets without `input` auto-inference (e.g. Android). Tasks still run; those relying on auto-inference run uncached, with the summary noting that `input` must be configured manually to enable caching ([#352](https://github.com/voidzero-dev/vite-task/pull/352)) - **Fixed** `vp run` no longer aborts with `failed to prepare the command for injection: Invalid argument` when the user environment already has `LD_PRELOAD` (Linux) or `DYLD_INSERT_LIBRARIES` (macOS) set. The tracer shim is now appended to any existing value and placed last, so user preloads keep their symbol-interposition precedence ([#340](https://github.com/voidzero-dev/vite-task/issues/340)) diff --git a/Cargo.lock b/Cargo.lock index 324f0a6ad..179a9470e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -421,6 +421,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -1686,6 +1688,16 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.85" @@ -4098,12 +4110,14 @@ dependencies = [ "rustc-hash", "serde", "serde_json", + "tar", "tempfile", "thiserror 2.0.18", "tokio", "tokio-util", "tracing", "twox-hash", + "uuid", "vite_path", "vite_select", "vite_str", @@ -4113,6 +4127,7 @@ dependencies = [ "wax", "winapi", "wincode", + "zstd", ] [[package]] @@ -4876,3 +4891,31 @@ name = "zmij" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 9e11f099b..5583f09b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -163,6 +163,7 @@ winsafe = { version = "0.0.27", features = ["kernel"] } xxhash-rust = { version = "0.8.15", features = ["const_xxh3"] } ntest = "0.9.5" terminal_size = "0.4" +zstd = "0.13" [workspace.metadata.cargo-shear] ignored = [ diff --git a/crates/vite_task/Cargo.toml b/crates/vite_task/Cargo.toml index 2286b9dc7..f5d77780b 100644 --- a/crates/vite_task/Cargo.toml +++ b/crates/vite_task/Cargo.toml @@ -29,6 +29,7 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } serde_json = { workspace = true } thiserror = { workspace = true } +tar = { workspace = true } tokio = { workspace = true, features = [ "rt-multi-thread", "io-std", @@ -40,6 +41,7 @@ tokio = { workspace = true, features = [ tokio-util = { workspace = true } tracing = { workspace = true } twox-hash = { workspace = true } +uuid = { workspace = true, features = ["v4"] } vite_path = { workspace = true } vite_select = { workspace = true } vite_str = { workspace = true } @@ -47,6 +49,7 @@ vite_task_graph = { workspace = true } vite_task_plan = { workspace = true } vite_workspace = { workspace = true } wax = { workspace = true } +zstd = { workspace = true } [dev-dependencies] tempfile = { workspace = true } diff --git a/crates/vite_task/src/session/cache/archive.rs b/crates/vite_task/src/session/cache/archive.rs new file mode 100644 index 000000000..9a4982ae2 --- /dev/null +++ b/crates/vite_task/src/session/cache/archive.rs @@ -0,0 +1,61 @@ +//! Output archive creation and extraction using tar + zstd compression. + +use std::fs::File; + +use vite_path::{AbsolutePath, RelativePathBuf}; + +/// Create a tar.zst archive from workspace-relative output file paths. +/// +/// Files that no longer exist are silently skipped (the task may delete +/// temporary files during execution). +/// +/// # Errors +/// +/// Returns an error if creating the archive file or adding entries fails. +pub fn create_output_archive( + workspace_root: &AbsolutePath, + output_files: &[RelativePathBuf], + archive_path: &AbsolutePath, +) -> anyhow::Result<()> { + let file = File::create(archive_path.as_path())?; + let encoder = zstd::Encoder::new(file, 0)?.auto_finish(); + let mut builder = tar::Builder::new(encoder); + + for rel_path in output_files { + let abs_path = workspace_root.join(rel_path); + // Skip files that no longer exist (task may delete temp files) + if !abs_path.as_path().exists() { + continue; + } + let metadata = std::fs::metadata(abs_path.as_path())?; + if metadata.is_file() { + let mut file = File::open(abs_path.as_path())?; + let mut header = tar::Header::new_gnu(); + header.set_metadata(&metadata); + header.set_cksum(); + builder.append_data(&mut header, rel_path.as_str(), &mut file)?; + } + } + + builder.finish()?; + Ok(()) +} + +/// Extract a tar.zst archive, restoring files relative to workspace root. +/// +/// Parent directories are created automatically. Existing files are overwritten. +/// +/// # Errors +/// +/// Returns an error if opening the archive or extracting entries fails. +pub fn extract_output_archive( + workspace_root: &AbsolutePath, + archive_path: &AbsolutePath, +) -> anyhow::Result<()> { + let file = File::open(archive_path.as_path())?; + let decoder = zstd::Decoder::new(file)?; + let mut archive = tar::Archive::new(decoder); + + archive.unpack(workspace_root.as_path())?; + Ok(()) +} diff --git a/crates/vite_task/src/session/cache/display.rs b/crates/vite_task/src/session/cache/display.rs index ec6bf3d3d..9dbcabd59 100644 --- a/crates/vite_task/src/session/cache/display.rs +++ b/crates/vite_task/src/session/cache/display.rs @@ -174,6 +174,7 @@ pub fn format_cache_status_inline(cache_status: &CacheStatus) -> Option { } } FingerprintMismatch::InputConfig => "input configuration changed", + FingerprintMismatch::OutputConfig => "output configuration changed", FingerprintMismatch::InputChanged { kind, path } => { let desc = format_input_change_str(*kind, path.as_str()); return Some(vite_str::format!("○ cache miss: {desc}, executing")); diff --git a/crates/vite_task/src/session/cache/mod.rs b/crates/vite_task/src/session/cache/mod.rs index 690d50d43..6d1ee6a9c 100644 --- a/crates/vite_task/src/session/cache/mod.rs +++ b/crates/vite_task/src/session/cache/mod.rs @@ -1,5 +1,6 @@ //! Execution cache for storing and retrieving cached command results. +pub mod archive; pub mod display; use std::{collections::BTreeMap, fmt::Display, fs::File, io::Write, sync::Arc, time::Duration}; @@ -14,7 +15,8 @@ use rusqlite::{Connection, OptionalExtension as _, config::DbConfig}; use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; use vite_path::{AbsolutePath, RelativePathBuf}; -use vite_task_graph::config::ResolvedInputConfig; +use vite_str::Str; +use vite_task_graph::config::ResolvedGlobConfig; use vite_task_plan::cache_metadata::{CacheMetadata, ExecutionCacheKey, SpawnFingerprint}; use wincode::{ SchemaRead, SchemaReadOwned, SchemaWrite, @@ -43,7 +45,10 @@ pub struct CacheEntryKey { pub spawn_fingerprint: SpawnFingerprint, /// Resolved input configuration that affects cache behavior. /// Glob patterns are workspace-root-relative. - pub input_config: ResolvedInputConfig, + pub input_config: ResolvedGlobConfig, + /// Resolved output configuration that affects cache restoration. + /// Glob patterns are workspace-root-relative. + pub output_config: ResolvedGlobConfig, } impl CacheEntryKey { @@ -51,6 +56,7 @@ impl CacheEntryKey { Self { spawn_fingerprint: cache_metadata.spawn_fingerprint.clone(), input_config: cache_metadata.input_config.clone(), + output_config: cache_metadata.output_config.clone(), } } } @@ -103,6 +109,9 @@ pub struct CacheEntryValue { /// Path is relative to workspace root, value is `xxHash3_64` of file content. /// Stored in the value (not the key) so changes can be detected and reported. pub globbed_inputs: BTreeMap, + /// Filename of the output archive (e.g. `{uuid}.tar.zst`) stored alongside + /// `cache.db` in the cache directory. `None` if no output files were produced. + pub output_archive: Option, } #[derive(Debug)] @@ -142,6 +151,8 @@ pub enum FingerprintMismatch { }, /// Found a previous cache entry key for the same task, but `input_config` differs. InputConfig, + /// Found a previous cache entry key for the same task, but `output_config` differs. + OutputConfig, InputChanged { kind: InputChangeKind, @@ -158,6 +169,9 @@ impl Display for FingerprintMismatch { Self::InputConfig => { write!(f, "input configuration changed") } + Self::OutputConfig => { + write!(f, "output configuration changed") + } Self::InputChanged { kind, path } => { write!(f, "{}", display::format_input_change_str(*kind, path.as_str())) } @@ -201,16 +215,16 @@ impl ExecutionCache { "CREATE TABLE task_fingerprints (key BLOB PRIMARY KEY, value BLOB);", (), )?; - conn.execute("PRAGMA user_version = 11", ())?; + conn.execute("PRAGMA user_version = 12", ())?; } - 1..=10 => { + 1..=11 => { // old internal db version. reset conn.set_db_config(DbConfig::SQLITE_DBCONFIG_RESET_DATABASE, true)?; conn.execute("VACUUM", ())?; conn.set_db_config(DbConfig::SQLITE_DBCONFIG_RESET_DATABASE, false)?; } - 11 => break, // current version - 12.. => { + 12 => break, // current version + 13.. => { return Err(anyhow::anyhow!( "Unrecognized database version: {user_version}. \ The cache may have been created by a newer version of Vite Task. \ @@ -270,11 +284,20 @@ impl ExecutionCache { self.get_cache_key_by_execution_key(execution_cache_key).await? { // Destructure to ensure we handle all fields when new ones are added - let CacheEntryKey { spawn_fingerprint: old_spawn_fingerprint, input_config: _ } = - old_cache_key; + let CacheEntryKey { + spawn_fingerprint: old_spawn_fingerprint, + input_config: old_input_config, + output_config: old_output_config, + } = old_cache_key; let mismatch = if old_spawn_fingerprint == *spawn_fingerprint { - // spawn fingerprint is the same but input_config or glob_base changed - FingerprintMismatch::InputConfig + // spawn fingerprint is the same but input_config or output_config changed + if old_input_config != cache_metadata.input_config { + FingerprintMismatch::InputConfig + } else if old_output_config != cache_metadata.output_config { + FingerprintMismatch::OutputConfig + } else { + FingerprintMismatch::InputConfig + } } else { FingerprintMismatch::SpawnFingerprint { old: old_spawn_fingerprint, @@ -288,16 +311,33 @@ impl ExecutionCache { } /// Update cache after successful execution. + /// + /// If a previous entry exists for the same cache key with a different + /// `output_archive`, the stale archive file in `cache_dir` is removed + /// (best-effort) so it doesn't accumulate on disk. #[tracing::instrument(level = "debug", skip_all)] pub async fn update( &self, cache_metadata: &CacheMetadata, cache_value: CacheEntryValue, + cache_dir: &AbsolutePath, ) -> anyhow::Result<()> { let execution_cache_key = &cache_metadata.execution_cache_key; let cache_key = CacheEntryKey::from_metadata(cache_metadata); + // If a previous entry exists with a stale output archive, delete the + // old file so the cache directory doesn't accumulate orphaned archives. + if let Some(old_value) = self.get_by_cache_key(&cache_key).await? + && let Some(old_archive) = old_value.output_archive + && cache_value.output_archive.as_ref() != Some(&old_archive) + { + let old_archive_path = cache_dir.join(old_archive.as_str()); + // Best-effort cleanup: a missing file (e.g. after a crash or manual + // cache clear) is fine, so we ignore the error. + let _ = std::fs::remove_file(old_archive_path.as_path()); + } + self.upsert_cache_entry(&cache_key, &cache_value).await?; self.upsert_task_fingerprint(execution_cache_key, &cache_key).await?; Ok(()) diff --git a/crates/vite_task/src/session/execute/glob_inputs.rs b/crates/vite_task/src/session/execute/glob_inputs.rs index a9bb1b20d..a3d966e11 100644 --- a/crates/vite_task/src/session/execute/glob_inputs.rs +++ b/crates/vite_task/src/session/execute/glob_inputs.rs @@ -109,6 +109,58 @@ pub fn compute_globbed_inputs( Ok(result) } +/// Collect file paths matching positive globs, filtered by negative globs. +/// +/// Like [`compute_globbed_inputs`] but only collects paths (no hashing). +/// Used for determining which output files to archive. +pub fn collect_glob_paths( + workspace_root: &AbsolutePath, + positive_globs: &std::collections::BTreeSet, + negative_globs: &std::collections::BTreeSet, +) -> anyhow::Result> { + if positive_globs.is_empty() { + return Ok(Vec::new()); + } + + let negatives: Vec> = negative_globs + .iter() + .map(|p| Ok(Glob::new(p.as_str())?.into_owned())) + .collect::>()?; + let negation = wax::any(negatives)?; + + let mut result = Vec::new(); + + for pattern in positive_globs { + let glob = Glob::new(pattern.as_str())?.into_owned(); + let walk = glob.walk(workspace_root.as_path()); + for entry in walk.not(negation.clone())? { + let entry = match entry { + Ok(entry) => entry, + Err(err) => { + let io_err: io::Error = err.into(); + if io_err.kind() == io::ErrorKind::NotFound { + continue; + } + return Err(io_err.into()); + } + }; + if !entry.file_type().is_file() { + continue; + } + let path = entry.path(); + let Some(stripped) = path.strip_prefix(workspace_root.as_path()).ok() else { + continue; + }; + let relative = RelativePathBuf::new(stripped)?; + result.push(relative); + } + } + + result.sort(); + result.dedup(); + Ok(result) +} + #[expect(clippy::disallowed_types, reason = "receives std::path::Path from wax glob walker")] fn hash_file_content(path: &std::path::Path) -> io::Result { super::hash::hash_content(io::BufReader::new(File::open(path)?)) diff --git a/crates/vite_task/src/session/execute/mod.rs b/crates/vite_task/src/session/execute/mod.rs index 812de5f65..29719a74f 100644 --- a/crates/vite_task/src/session/execute/mod.rs +++ b/crates/vite_task/src/session/execute/mod.rs @@ -16,6 +16,7 @@ use rustc_hash::FxHashMap; use tokio::sync::Semaphore; use tokio_util::sync::CancellationToken; use vite_path::{AbsolutePath, RelativePathBuf}; +use vite_str::Str; use vite_task_plan::{ ExecutionGraph, ExecutionItemDisplay, ExecutionItemKind, LeafExecutionKind, SpawnExecution, cache_metadata::CacheMetadata, execution_graph::ExecutionNodeIndex, @@ -30,7 +31,7 @@ use self::{ spawn::{SpawnStdio, spawn}, }; use super::{ - cache::{CacheEntryValue, ExecutionCache}, + cache::{CacheEntryValue, ExecutionCache, archive}, event::{ CacheDisabledReason, CacheErrorKind, CacheNotUpdatedReason, CacheStatus, CacheUpdateStatus, ExecutionError, @@ -75,6 +76,8 @@ struct ExecutionContext<'a> { /// Base path for resolving relative paths in cache entries. /// Typically the workspace root. cache_base_path: &'a Arc, + /// Directory where cache files (db, archives) are stored. + cache_dir: &'a AbsolutePath, /// Token cancelled when a task fails. Kills in-flight child processes /// (via `start_kill` in spawn.rs), prevents scheduling new tasks, and /// prevents caching results of concurrently-running tasks. @@ -236,6 +239,7 @@ impl ExecutionContext<'_> { spawn_execution, self.cache, self.cache_base_path, + self.cache_dir, self.fast_fail_token.clone(), self.interrupt_token.clone(), ) @@ -328,6 +332,7 @@ pub async fn execute_spawn( spawn_execution: &SpawnExecution, cache: &ExecutionCache, cache_base_path: &Arc, + cache_dir: &AbsolutePath, fast_fail_token: CancellationToken, interrupt_token: CancellationToken, ) -> SpawnOutcome { @@ -400,6 +405,18 @@ pub async fn execute_spawn( let _ = writer.write_all(&output.content); let _ = writer.flush(); } + // Restore output files from the cached archive + if let Some(ref archive_name) = cached.output_archive { + let archive_path = cache_dir.join(archive_name.as_str()); + if let Err(err) = archive::extract_output_archive(cache_base_path, &archive_path) { + leaf_reporter.finish( + None, + CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheHit), + Some(ExecutionError::Cache { kind: CacheErrorKind::Lookup, source: err }), + ); + return SpawnOutcome::Failed; + } + } leaf_reporter.finish( None, CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheHit), @@ -605,13 +622,38 @@ pub async fn execute_spawn( let path_reads = tracking.as_ref().map_or(&empty_path_reads, |t| &t.path_reads); match PostRunFingerprint::create(path_reads, cache_base_path, &globbed_inputs) { Ok(post_run_fingerprint) => { + // Collect output files and create archive + let output_archive = + match collect_and_archive_outputs(metadata, cache_base_path, cache_dir) + { + Ok(archive) => archive, + Err(err) => { + let result = ( + CacheUpdateStatus::NotUpdated( + CacheNotUpdatedReason::CacheDisabled, + ), + Some(ExecutionError::Cache { + kind: CacheErrorKind::Update, + source: err, + }), + ); + leaf_reporter.finish( + Some(outcome.exit_status), + result.0, + result.1, + ); + return SpawnOutcome::Spawned(outcome.exit_status); + } + }; + let new_cache_value = CacheEntryValue { post_run_fingerprint, std_outputs: std_outputs.into(), duration, globbed_inputs, + output_archive, }; - match cache.update(metadata, new_cache_value).await { + match cache.update(metadata, new_cache_value, cache_dir).await { Ok(()) => (CacheUpdateStatus::Updated, None), Err(err) => ( CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), @@ -645,6 +687,40 @@ pub async fn execute_spawn( SpawnOutcome::Spawned(outcome.exit_status) } +/// Collect output files matching the configured globs and create a tar.zst +/// archive in the cache directory. +/// +/// Returns `Some(archive_filename)` if files were archived, `None` if the +/// output config has no positive globs or no files matched. +fn collect_and_archive_outputs( + cache_metadata: &CacheMetadata, + workspace_root: &AbsolutePath, + cache_dir: &AbsolutePath, +) -> anyhow::Result> { + let output_config = &cache_metadata.output_config; + + if output_config.positive_globs.is_empty() { + return Ok(None); + } + + let output_files = glob_inputs::collect_glob_paths( + workspace_root, + &output_config.positive_globs, + &output_config.negative_globs, + )?; + + if output_files.is_empty() { + return Ok(None); + } + + let archive_name: Str = vite_str::format!("{}.tar.zst", uuid::Uuid::new_v4()); + let archive_path = cache_dir.join(archive_name.as_str()); + + archive::create_output_archive(workspace_root, &output_files, &archive_path)?; + + Ok(Some(archive_name)) +} + impl Session<'_> { /// Execute an execution graph, reporting events through the provided reporter builder. /// @@ -679,6 +755,7 @@ impl Session<'_> { reporter: &reporter, cache, cache_base_path: &self.workspace_path, + cache_dir: &self.cache_path, fast_fail_token: CancellationToken::new(), interrupt_token, }; diff --git a/crates/vite_task/src/session/mod.rs b/crates/vite_task/src/session/mod.rs index eb9ca6411..8edef289f 100644 --- a/crates/vite_task/src/session/mod.rs +++ b/crates/vite_task/src/session/mod.rs @@ -677,6 +677,7 @@ impl<'a> Session<'a> { &spawn_execution, cache, &self.workspace_path, + &self.cache_path, tokio_util::sync::CancellationToken::new(), tokio_util::sync::CancellationToken::new(), ) diff --git a/crates/vite_task/src/session/reporter/summary.rs b/crates/vite_task/src/session/reporter/summary.rs index 4eeceb684..f1a01168f 100644 --- a/crates/vite_task/src/session/reporter/summary.rs +++ b/crates/vite_task/src/session/reporter/summary.rs @@ -259,7 +259,9 @@ impl SavedCacheMissReason { FingerprintMismatch::SpawnFingerprint { old, new } => { Self::SpawnFingerprintChanged(detect_spawn_fingerprint_changes(old, new)) } - FingerprintMismatch::InputConfig => Self::ConfigChanged, + FingerprintMismatch::InputConfig | FingerprintMismatch::OutputConfig => { + Self::ConfigChanged + } FingerprintMismatch::InputChanged { kind, path } => { Self::InputChanged { kind: *kind, path: Str::from(path.as_str()) } } diff --git a/crates/vite_task_bin/src/lib.rs b/crates/vite_task_bin/src/lib.rs index 87a402a2a..43ccd08d1 100644 --- a/crates/vite_task_bin/src/lib.rs +++ b/crates/vite_task_bin/src/lib.rs @@ -98,6 +98,7 @@ impl vite_task::CommandHandler for CommandHandler { env: None, untracked_env: None, input: None, + output: None, }), envs: Arc::clone(&command.envs), })) diff --git a/crates/vite_task_bin/src/vtt/write_file.rs b/crates/vite_task_bin/src/vtt/write_file.rs index f5539146b..b1562bd79 100644 --- a/crates/vite_task_bin/src/vtt/write_file.rs +++ b/crates/vite_task_bin/src/vtt/write_file.rs @@ -2,6 +2,10 @@ pub fn run(args: &[String]) -> Result<(), Box> { if args.len() < 2 { return Err("Usage: vtt write-file ".into()); } - std::fs::write(&args[0], &args[1])?; + let path = std::path::Path::new(&args[0]); + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write(path, &args[1])?; Ok(()) } diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/package.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/package.json new file mode 100644 index 000000000..60b87e87f --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/package.json @@ -0,0 +1,4 @@ +{ + "name": "output-cache-test", + "private": true +} diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml new file mode 100644 index 000000000..d554d79b4 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml @@ -0,0 +1,38 @@ +[[e2e]] +name = "output_globs___files_restored_on_cache_hit" +comment = """ +With explicit output globs (`dist/**`), the first run writes a file to +`dist/`. After deleting `dist/`, a second run with no input changes is a +cache hit and the archived output file is restored. +""" +steps = [ + # First run - cache miss, writes dist/output.txt + ["vt", "run", "build"], + # Verify file was written + ["vtt", "print-file", "dist/output.txt"], + # Delete dist/ to prove restoration is real + ["vtt", "rm", "-rf", "dist"], + # Second run - cache hit, restores dist/output.txt from archive + ["vt", "run", "build"], + # File should be restored + ["vtt", "print-file", "dist/output.txt"], +] + +[[e2e]] +name = "output_globs___negative_excludes_files_from_archive" +comment = """ +A file matched by a negative output glob is not archived, so it is not +restored on cache hit. +""" +steps = [ + # First run - writes both dist/keep.txt and dist/skip.txt + ["vt", "run", "build-with-negative"], + # Both files exist after the run + ["vtt", "print-file", "dist/keep.txt"], + ["vtt", "print-file", "dist/skip.txt"], + # Delete dist/ to prove restoration is real + ["vtt", "rm", "-rf", "dist"], + # Second run - cache hit, only dist/keep.txt is restored + ["vt", "run", "build-with-negative"], + ["vtt", "print-file", "dist/keep.txt"], +] diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___files_restored_on_cache_hit.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___files_restored_on_cache_hit.md new file mode 100644 index 000000000..f10e226f1 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___files_restored_on_cache_hit.md @@ -0,0 +1,37 @@ +# output_globs___files_restored_on_cache_hit + +With explicit output globs (`dist/**`), the first run writes a file to +`dist/`. After deleting `dist/`, a second run with no input changes is a +cache hit and the archived output file is restored. + +## `vt run build` + +``` +$ vtt write-file dist/output.txt built +``` + +## `vtt print-file dist/output.txt` + +``` +built +``` + +## `vtt rm -rf dist` + +``` +``` + +## `vt run build` + +``` +$ vtt write-file dist/output.txt built ◉ cache hit, replaying + +--- +vt run: cache hit. +``` + +## `vtt print-file dist/output.txt` + +``` +built +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___negative_excludes_files_from_archive.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___negative_excludes_files_from_archive.md new file mode 100644 index 000000000..2cb049158 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_globs___negative_excludes_files_from_archive.md @@ -0,0 +1,49 @@ +# output_globs___negative_excludes_files_from_archive + +A file matched by a negative output glob is not archived, so it is not +restored on cache hit. + +## `vt run build-with-negative` + +``` +$ vtt write-file dist/keep.txt keep + +$ vtt write-file dist/skip.txt skip + +--- +vt run: 0/2 cache hit (0%). (Run `vt run --last-details` for full details) +``` + +## `vtt print-file dist/keep.txt` + +``` +keep +``` + +## `vtt print-file dist/skip.txt` + +``` +skip +``` + +## `vtt rm -rf dist` + +``` +``` + +## `vt run build-with-negative` + +``` +$ vtt write-file dist/keep.txt keep ◉ cache hit, replaying + +$ vtt write-file dist/skip.txt skip ◉ cache hit, replaying + +--- +vt run: 2/2 cache hit (100%). (Run `vt run --last-details` for full details) +``` + +## `vtt print-file dist/keep.txt` + +``` +keep +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/src/main.ts b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/src/main.ts new file mode 100644 index 000000000..38e000a1c --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/src/main.ts @@ -0,0 +1 @@ +export const main = 'initial'; diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json new file mode 100644 index 000000000..6bd35a604 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json @@ -0,0 +1,16 @@ +{ + "tasks": { + "build": { + "command": "vtt write-file dist/output.txt built", + "input": ["src/**"], + "output": ["dist/**"], + "cache": true + }, + "build-with-negative": { + "command": "vtt write-file dist/keep.txt keep && vtt write-file dist/skip.txt skip", + "input": ["src/**"], + "output": ["dist/**", "!dist/skip.txt"], + "cache": true + } + } +} diff --git a/crates/vite_task_graph/run-config.ts b/crates/vite_task_graph/run-config.ts index 026664c39..1fa4ee868 100644 --- a/crates/vite_task_graph/run-config.ts +++ b/crates/vite_task_graph/run-config.ts @@ -53,7 +53,16 @@ untrackedEnv?: Array, * - `{auto: true}` enables automatic file tracking * - Negative patterns (e.g. `"!dist/**"`) exclude matched files */ -input?: Array, } | { +input?: Array, +/** + * Output files to archive after a successful run and restore on cache hit. + * + * - Omitted or `[]` (empty): no output archiving (default) + * - Glob patterns (e.g. `"dist/**"`) select specific output files, relative to the package directory + * - `{pattern: "...", base: "workspace" | "package"}` specifies a glob with an explicit base directory + * - Negative patterns (e.g. `"!dist/cache/**"`) exclude matched files + */ +output?: Array, } | { /** * Whether to cache the task */ diff --git a/crates/vite_task_graph/src/config/mod.rs b/crates/vite_task_graph/src/config/mod.rs index 916bc62a1..0e8c28f87 100644 --- a/crates/vite_task_graph/src/config/mod.rs +++ b/crates/vite_task_graph/src/config/mod.rs @@ -7,8 +7,8 @@ use rustc_hash::FxHashSet; use serde::Serialize; pub use user::{ AutoInput, EnabledCacheConfig, GlobWithBase, InputBase, ResolvedGlobalCacheConfig, - UserCacheConfig, UserGlobalCacheConfig, UserInputEntry, UserInputsConfig, UserRunConfig, - UserTaskConfig, + UserCacheConfig, UserGlobalCacheConfig, UserInputEntry, UserInputsConfig, UserOutputEntry, + UserRunConfig, UserTaskConfig, }; use vite_path::AbsolutePath; use vite_str::Str; @@ -69,12 +69,18 @@ impl ResolvedTaskOptions { enabled_cache_config.untracked_env.unwrap_or_default().into_iter().collect(); untracked_env.extend(DEFAULT_UNTRACKED_ENV.iter().copied().map(Str::from)); - let input_config = ResolvedInputConfig::from_user_config( + let input_config = ResolvedGlobConfig::from_user_config( enabled_cache_config.input.as_ref(), dir, workspace_root, )?; + let output_config = ResolvedGlobConfig::from_user_output_config( + enabled_cache_config.output.as_ref(), + dir, + workspace_root, + )?; + Some(CacheConfig { env_config: EnvConfig { fingerprinted_envs: enabled_cache_config @@ -84,6 +90,7 @@ impl ResolvedTaskOptions { untracked_env, }, input_config, + output_config, }) } }; @@ -92,9 +99,14 @@ impl ResolvedTaskOptions { } #[derive(Debug, Clone, Serialize)] +#[expect( + clippy::struct_field_names, + reason = "env_config, input_config, output_config are distinct config categories, not a naming smell" +)] pub struct CacheConfig { pub env_config: EnvConfig, - pub input_config: ResolvedInputConfig, + pub input_config: ResolvedGlobConfig, + pub output_config: ResolvedGlobConfig, } /// Resolved input configuration for cache fingerprinting. @@ -104,7 +116,7 @@ pub struct CacheConfig { /// - `positive_globs`: Glob patterns for files to include (without `!` prefix) /// - `negative_globs`: Glob patterns for files to exclude (without `!` prefix) #[derive(Debug, Clone, PartialEq, Eq, Serialize, SchemaWrite, SchemaRead)] -pub struct ResolvedInputConfig { +pub struct ResolvedGlobConfig { /// Whether automatic file tracking is enabled pub includes_auto: bool, @@ -117,7 +129,7 @@ pub struct ResolvedInputConfig { pub negative_globs: BTreeSet, } -impl ResolvedInputConfig { +impl ResolvedGlobConfig { /// Default configuration: auto-inference enabled, no explicit patterns #[must_use] pub const fn default_auto() -> Self { @@ -184,6 +196,57 @@ impl ResolvedInputConfig { Ok(Self { includes_auto, positive_globs, negative_globs }) } + /// Resolve from user output configuration, making glob patterns workspace-root-relative. + /// + /// Unlike [`Self::from_user_config`], `None` and `Some([])` both produce an empty config + /// with `includes_auto = false` (no output archiving). + /// + /// # Errors + /// + /// Returns [`ResolveTaskConfigError`] if a glob pattern is invalid or resolves + /// outside the workspace root. + pub fn from_user_output_config( + user_outputs: Option<&Vec>, + package_dir: &AbsolutePath, + workspace_root: &AbsolutePath, + ) -> Result { + let mut positive_globs = BTreeSet::new(); + let mut negative_globs = BTreeSet::new(); + + let Some(entries) = user_outputs else { + return Ok(Self { includes_auto: false, positive_globs, negative_globs }); + }; + + for entry in entries { + match entry { + UserOutputEntry::Glob(pattern) => { + Self::insert_glob( + pattern.as_str(), + package_dir, + workspace_root, + &mut positive_globs, + &mut negative_globs, + )?; + } + UserOutputEntry::GlobWithBase(GlobWithBase { pattern, base }) => { + let base_dir = match base { + InputBase::Package => package_dir, + InputBase::Workspace => workspace_root, + }; + Self::insert_glob( + pattern.as_str(), + base_dir, + workspace_root, + &mut positive_globs, + &mut negative_globs, + )?; + } + } + } + + Ok(Self { includes_auto: false, positive_globs, negative_globs }) + } + /// Insert a glob pattern into the appropriate set (positive or negative), /// resolving it relative to the given base directory. fn insert_glob( @@ -426,7 +489,7 @@ mod tests { #[test] fn test_resolved_input_config_default_auto() { - let config = ResolvedInputConfig::default_auto(); + let config = ResolvedGlobConfig::default_auto(); assert!(config.includes_auto); assert!(config.positive_globs.is_empty()); assert!(config.negative_globs.is_empty()); @@ -436,7 +499,7 @@ mod tests { fn test_resolved_input_config_from_none() { let (pkg, ws) = test_paths(); // None means default to auto-inference - let config = ResolvedInputConfig::from_user_config(None, &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(None, &pkg, &ws).unwrap(); assert!(config.includes_auto); assert!(config.positive_globs.is_empty()); assert!(config.negative_globs.is_empty()); @@ -447,7 +510,7 @@ mod tests { let (pkg, ws) = test_paths(); // Empty array means no inputs, inference disabled let user_inputs = vec![]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(!config.includes_auto); assert!(config.positive_globs.is_empty()); assert!(config.negative_globs.is_empty()); @@ -457,7 +520,7 @@ mod tests { fn test_resolved_input_config_auto_only() { let (pkg, ws) = test_paths(); let user_inputs = vec![UserInputEntry::Auto(AutoInput { auto: true })]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(config.includes_auto); assert!(config.positive_globs.is_empty()); assert!(config.negative_globs.is_empty()); @@ -467,7 +530,7 @@ mod tests { fn test_resolved_input_config_auto_false_ignored() { let (pkg, ws) = test_paths(); let user_inputs = vec![UserInputEntry::Auto(AutoInput { auto: false })]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(!config.includes_auto); assert!(config.positive_globs.is_empty()); assert!(config.negative_globs.is_empty()); @@ -481,7 +544,7 @@ mod tests { UserInputEntry::Glob("src/**/*.ts".into()), UserInputEntry::Glob("package.json".into()), ]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(!config.includes_auto); assert_eq!(config.positive_globs.len(), 2); // Globs should now be workspace-root-relative @@ -497,7 +560,7 @@ mod tests { UserInputEntry::Glob("src/**".into()), UserInputEntry::Glob("!src/**/*.test.ts".into()), ]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(!config.includes_auto); assert_eq!(config.positive_globs.len(), 1); assert!(config.positive_globs.contains("packages/my-pkg/src/**")); @@ -513,7 +576,7 @@ mod tests { UserInputEntry::Auto(AutoInput { auto: true }), UserInputEntry::Glob("!node_modules/**".into()), ]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(config.includes_auto); assert_eq!(config.positive_globs.len(), 1); assert!(config.positive_globs.contains("packages/my-pkg/package.json")); @@ -529,7 +592,7 @@ mod tests { UserInputEntry::Glob("src/**/*.ts".into()), UserInputEntry::Auto(AutoInput { auto: true }), ]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(config.includes_auto); } @@ -537,7 +600,7 @@ mod tests { fn test_resolved_input_config_dotdot_resolution() { let (pkg, ws) = test_paths(); let user_inputs = vec![UserInputEntry::Glob("../shared/src/**".into())]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert_eq!(config.positive_globs.len(), 1); assert!( config.positive_globs.contains("packages/shared/src/**"), @@ -550,7 +613,7 @@ mod tests { fn test_resolved_input_config_outside_workspace_error() { let (pkg, ws) = test_paths(); let user_inputs = vec![UserInputEntry::Glob("../../../outside/**".into())]; - let result = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws); + let result = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws); assert!(result.is_err()); assert!(matches!(result.unwrap_err(), ResolveTaskConfigError::GlobOutsideWorkspace { .. })); } @@ -562,7 +625,7 @@ mod tests { pattern: "configs/tsconfig.json".into(), base: InputBase::Workspace, })]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(!config.includes_auto); assert_eq!(config.positive_globs.len(), 1); // Workspace-base: should NOT have the package prefix @@ -580,7 +643,7 @@ mod tests { pattern: "!dist/**".into(), base: InputBase::Workspace, })]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert_eq!(config.negative_globs.len(), 1); assert!( config.negative_globs.contains("dist/**"), @@ -597,7 +660,7 @@ mod tests { pattern: "src/**/*.ts".into(), base: InputBase::Package, })]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert_eq!(config.positive_globs.len(), 1); assert!( config.positive_globs.contains("packages/my-pkg/src/**/*.ts"), @@ -621,7 +684,7 @@ mod tests { base: InputBase::Workspace, }), ]; - let config = ResolvedInputConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); + let config = ResolvedGlobConfig::from_user_config(Some(&user_inputs), &pkg, &ws).unwrap(); assert!(config.includes_auto); assert_eq!(config.positive_globs.len(), 2); assert!(config.positive_globs.contains("packages/my-pkg/src/**")); diff --git a/crates/vite_task_graph/src/config/user.rs b/crates/vite_task_graph/src/config/user.rs index 79255ad63..aeee38608 100644 --- a/crates/vite_task_graph/src/config/user.rs +++ b/crates/vite_task_graph/src/config/user.rs @@ -65,6 +65,22 @@ pub enum UserInputEntry { /// Default (when field omitted): `[{auto: true}]` - infer from file accesses. pub type UserInputsConfig = Vec; +/// A single output entry in the `output` array. +/// +/// Outputs can be: +/// - Glob patterns as strings (resolved relative to the package directory) +/// - Object form with explicit base: `{ "pattern": "...", "base": "workspace" | "package" }` +#[derive(Debug, Deserialize, PartialEq, Eq, Clone)] +// TS derive macro generates code using std types that clippy disallows; skip derive during linting +#[cfg_attr(all(test, not(clippy)), derive(TS))] +#[serde(untagged)] +pub enum UserOutputEntry { + /// Glob pattern (positive or negative starting with `!`), resolved relative to package dir + Glob(Str), + /// Glob pattern with explicit base directory + GlobWithBase(GlobWithBase), +} + /// Cache-related fields of a task defined by user in `vite.config.*` #[derive(Debug, Deserialize, PartialEq, Eq)] // TS derive macro generates code using std types that clippy disallows; skip derive during linting @@ -125,6 +141,16 @@ pub struct EnabledCacheConfig { #[serde(default)] #[cfg_attr(all(test, not(clippy)), ts(inline))] pub input: Option, + + /// Output files to archive after a successful run and restore on cache hit. + /// + /// - Omitted or `[]` (empty): no output archiving (default) + /// - Glob patterns (e.g. `"dist/**"`) select specific output files, relative to the package directory + /// - `{pattern: "...", base: "workspace" | "package"}` specifies a glob with an explicit base directory + /// - Negative patterns (e.g. `"!dist/cache/**"`) exclude matched files + #[serde(default)] + #[cfg_attr(all(test, not(clippy)), ts(inline))] + pub output: Option>, } /// Options for user-defined tasks in `vite.config.*`, excluding the command. @@ -160,6 +186,7 @@ impl Default for UserTaskOptions { env: None, untracked_env: None, input: None, + output: None, }, }, } @@ -428,6 +455,7 @@ mod tests { env: Some(std::iter::once("NODE_ENV".into()).collect()), untracked_env: Some(std::iter::once("FOO".into()).collect()), input: None, + output: None, } }, ); diff --git a/crates/vite_task_plan/src/cache_metadata.rs b/crates/vite_task_plan/src/cache_metadata.rs index c3435c345..11a1d957e 100644 --- a/crates/vite_task_plan/src/cache_metadata.rs +++ b/crates/vite_task_plan/src/cache_metadata.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; use vite_path::RelativePathBuf; use vite_str::{self, Str}; -use vite_task_graph::config::ResolvedInputConfig; +use vite_task_graph::config::ResolvedGlobConfig; use wincode::{SchemaRead, SchemaWrite}; use crate::envs::EnvFingerprints; @@ -45,7 +45,11 @@ pub struct CacheMetadata { /// Resolved input configuration for cache fingerprinting. /// Used at execution time to determine what files to track. - pub input_config: ResolvedInputConfig, + pub input_config: ResolvedGlobConfig, + + /// Resolved output configuration for cache restoration. + /// Used at execution time to determine what output files to archive. + pub output_config: ResolvedGlobConfig, } /// Fingerprint for spawn execution that affects caching. diff --git a/crates/vite_task_plan/src/plan.rs b/crates/vite_task_plan/src/plan.rs index 1a91d9165..89e892b48 100644 --- a/crates/vite_task_plan/src/plan.rs +++ b/crates/vite_task_plan/src/plan.rs @@ -20,7 +20,7 @@ use vite_str::Str; use vite_task_graph::{ TaskNodeIndex, TaskSource, config::{ - CacheConfig, EnabledCacheConfig, ResolvedGlobalCacheConfig, ResolvedInputConfig, + CacheConfig, EnabledCacheConfig, ResolvedGlobConfig, ResolvedGlobalCacheConfig, ResolvedTaskOptions, user::{UserCacheConfig, UserTaskOptions}, }, @@ -466,7 +466,8 @@ fn resolve_synthetic_cache_config( Ok(match synthetic_cache_config { UserCacheConfig::Disabled { .. } => Option::None, UserCacheConfig::Enabled { enabled_cache_config, .. } => { - let EnabledCacheConfig { env, untracked_env, input } = enabled_cache_config; + let EnabledCacheConfig { env, untracked_env, input, output } = + enabled_cache_config; parent_config.env_config.fingerprinted_envs.extend(env.unwrap_or_default()); parent_config .env_config @@ -474,7 +475,7 @@ fn resolve_synthetic_cache_config( .extend(untracked_env.unwrap_or_default()); if let Some(input) = input { - let synthetic_input = ResolvedInputConfig::from_user_config( + let synthetic_input = ResolvedGlobConfig::from_user_config( Some(&input), package_dir, workspace_path, @@ -493,6 +494,23 @@ fn resolve_synthetic_cache_config( .extend(synthetic_input.negative_globs); } + if let Some(output) = output { + let synthetic_output = ResolvedGlobConfig::from_user_output_config( + Some(&output), + package_dir, + workspace_path, + ) + .map_err(Error::ResolveTaskConfig)?; + parent_config + .output_config + .positive_globs + .extend(synthetic_output.positive_globs); + parent_config + .output_config + .negative_globs + .extend(synthetic_output.negative_globs); + } + Some(parent_config) } }) @@ -628,6 +646,7 @@ fn plan_spawn_execution( spawn_fingerprint, execution_cache_key, input_config: cache_config.input_config.clone(), + output_config: cache_config.output_config.clone(), }); } } @@ -853,7 +872,7 @@ mod tests { use vite_path::AbsolutePathBuf; use vite_str::Str; use vite_task_graph::config::{ - CacheConfig, EnabledCacheConfig, EnvConfig, ResolvedInputConfig, + CacheConfig, EnabledCacheConfig, EnvConfig, ResolvedGlobConfig, user::{UserCacheConfig, UserInputEntry}, }; @@ -879,11 +898,16 @@ mod tests { fingerprinted_envs: FxHashSet::default(), untracked_env: FxHashSet::default(), }, - input_config: ResolvedInputConfig { + input_config: ResolvedGlobConfig { includes_auto, positive_globs: positive_globs.iter().map(|s| Str::from(*s)).collect(), negative_globs: BTreeSet::new(), }, + output_config: ResolvedGlobConfig { + includes_auto: false, + positive_globs: BTreeSet::new(), + negative_globs: BTreeSet::new(), + }, } } @@ -901,6 +925,7 @@ mod tests { env: None, untracked_env: None, input: None, + output: None, }), &pkg, &ws, @@ -922,6 +947,7 @@ mod tests { env: None, untracked_env: None, input: Some(vec![UserInputEntry::Glob("config/**".into())]), + output: None, }), &pkg, &ws, @@ -943,6 +969,7 @@ mod tests { env: None, untracked_env: None, input: Some(vec![UserInputEntry::Glob("config/**".into())]), + output: None, }), &pkg, &ws, @@ -970,6 +997,7 @@ mod tests { UserInputEntry::Glob("config/**".into()), UserInputEntry::Auto(vite_task_graph::config::user::AutoInput { auto: true }), ]), + output: None, }), &pkg, &ws, @@ -995,6 +1023,7 @@ mod tests { env: None, untracked_env: None, input: Some(vec![UserInputEntry::Glob("config/**".into())]), + output: None, }), &pkg, &ws, @@ -1018,6 +1047,7 @@ mod tests { env: None, untracked_env: None, input: Some(vec![UserInputEntry::Glob("config/**".into())]), + output: None, }), &pkg, &ws, @@ -1050,6 +1080,7 @@ mod tests { env: None, untracked_env: None, input: Some(vec![UserInputEntry::Glob("!dist/**".into())]), + output: None, }), &pkg, &ws, diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc index 9f64c0760..63bad854a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc @@ -60,6 +60,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc index 253fae9f5..da3f2d593 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc index 67b1ae1c5..63272b8d8 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc index 4ceddbc22..af84a0ef1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc index cf1e3a1ea..44c82a701 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc index feb1a3c63..d98768c05 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -116,6 +126,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -150,6 +165,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc index 6bcfb7bc0..f589579d4 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc @@ -87,6 +87,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc index e1997caff..586844bfc 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc index e273f579d..07660f771 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc @@ -60,6 +60,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc index 10fcc3e07..a75b9dfc1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc index 10fcc3e07..a75b9dfc1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc index 364b3e976..71683ee96 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc @@ -61,6 +61,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc index 2ca6de9ad..13b2802fd 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc index 876930785..5129800c3 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc index bc7667e73..8f084f7de 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc index 901475f0c..b344b082b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc index d34e6f5ce..78a406fa1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc index a5632de79..cb6afda93 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc index 4688df733..ebfa2e8b3 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc index b8b926650..fb069d24d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc index 1d5d0edf9..55ebae45d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc index 7d74b65d7..a82d5e2f9 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc index dbcb6a68e..a16181471 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc index b19be3704..fff2e8ef4 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc @@ -48,6 +48,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -82,6 +87,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc index 1f4636675..d226a413b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc index 93c1d00ef..4142b0960 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc index 4fc7ccaad..a0ea080a3 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc index c02cdb6ed..9597c4b3a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -162,6 +182,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -196,6 +221,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -230,6 +260,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -264,6 +299,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -298,6 +338,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -332,6 +377,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -366,6 +416,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -400,6 +455,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -434,6 +494,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -468,6 +533,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -502,6 +572,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -536,6 +611,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -570,6 +650,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -604,6 +689,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -638,6 +728,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -672,6 +767,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -706,6 +806,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -740,6 +845,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -774,6 +884,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc index 9b82411d5..e246a1db3 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc index 6336fe8ae..2c07f9bd1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -65,6 +70,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc index ae1236726..9b4779c26 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -65,6 +70,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc index 2b1c82e45..b3d46d315 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc index 726f29388..0a88447df 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -100,6 +105,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -134,6 +144,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -168,6 +183,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -207,6 +227,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -241,6 +266,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -275,6 +305,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -309,6 +344,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc index 3d0fc4335..4c6c21e3b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -95,6 +100,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -129,6 +139,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -163,6 +178,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -197,6 +217,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -231,6 +256,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -270,6 +300,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -304,6 +339,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -338,6 +378,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -381,6 +426,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc index a6b86de0d..da9501116 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { @@ -140,6 +145,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc index a110c9d85..e483d70c4 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc index 13011495a..27c09ea17 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -162,6 +182,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -196,6 +221,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -230,6 +260,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -264,6 +299,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -298,6 +338,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -332,6 +377,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -366,6 +416,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -400,6 +455,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -434,6 +494,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc index a793212e7..11c015377 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc @@ -30,6 +30,11 @@ "negative_globs": [ "dist/**" ] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc index 03b8005dc..b82a6e8da 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc @@ -31,6 +31,11 @@ "negative_globs": [ "dist/**" ] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc index e1b6e4bb9..759b8f84e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc index d3ba94f6a..a4f58176f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc index bfd033588..6e384f70a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc index 269edec05..1200a2faa 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc index 8492756ac..eef8a1a13 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc index 837fc00b2..599e3b086 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc index 5c4ce9ebd..9c50b6a60 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -162,6 +182,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc index 8c09f9552..aef412250 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc index 49781abe1..a902fcadd 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -162,6 +182,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -196,6 +221,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -230,6 +260,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -264,6 +299,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc index bb5913bb4..e5271222f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -162,6 +182,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -196,6 +221,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc index 43f2ac980..2961d7313 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc index b7db12108..36a3f67d0 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc index a70ddee47..005d03240 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc index 738582f79..b3da6fda6 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc index c0d1aba3d..51fd7c317 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc index 06e4fc593..2df26b1a1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc index a6bbadeaf..d5e183324 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc index b36b29e28..812734076 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc @@ -59,6 +59,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc index c3e7c5ffb..9ccca7a11 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc @@ -58,6 +58,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc index b1cfddc17..b550e3faf 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -116,6 +126,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -151,6 +166,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -185,6 +205,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc index 2c60292b6..5a40fe048 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc @@ -84,6 +84,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc index 554d3ab06..f45c1001a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc index 23a84412a..40ea1a092 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc index 0ae0ad7d5..00be69c6c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc index e235a1f01..ba1f67e9e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc @@ -64,6 +64,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc index a7e87dd0e..dc5f9a939 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc @@ -64,6 +64,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } }, "spawn_command": { diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc index 9eb638925..d8a3142d4 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc index 5a9820d52..f7ee35330 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc index 683023848..2a23ddc71 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -65,6 +70,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -99,6 +109,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -133,6 +148,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc index 1cd3ba456..f031c893d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc index 1e0d1452d..5e3cee720 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -128,6 +143,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc index 56576d866..5a64e4c3a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc index 0b4cbfe81..76f667459 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc @@ -26,6 +26,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -60,6 +65,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } @@ -94,6 +104,11 @@ "includes_auto": true, "positive_globs": [], "negative_globs": [] + }, + "output_config": { + "includes_auto": false, + "positive_globs": [], + "negative_globs": [] } } } From 6198f6bb4f95306f0ffb33c2c63430007df12ffc Mon Sep 17 00:00:00 2001 From: branchseer Date: Thu, 7 May 2026 15:14:35 +0800 Subject: [PATCH 2/2] feat(cache): auto-detect output writes via fspy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `{ auto: true }` support to the `output` field, plus the implicit default: when `output` is omitted, automatically tracks files the task writes (via fspy) and archives them. Explicit globs and `auto` can be mixed in the same array. Also includes: - `read_write_overlap` check: if a task writes to a file it also read (auto-inferred), the cache update is skipped (`InputModified`). Prerun input hashes would otherwise be stale. - Input negatives apply to reads only, not writes — keeps `input: ["!dist/**"]` from accidentally dropping writes to `dist/**` during archiving. - Input-auto gating: when `input_config.includes_auto` is false, fspy reads do not contribute to the post-run fingerprint, even when fspy is enabled solely for output tracking. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 1 + crates/vite_task/docs/task-cache.md | 4 +- crates/vite_task/src/session/execute/mod.rs | 334 +++++++++++------- .../src/session/execute/tracked_accesses.rs | 33 +- ...___not_set_when_auto_inference_disabled.md | 2 +- .../fixtures/output_cache_test/README.md | 1 + .../fixtures/output_cache_test/snapshots.toml | 242 +++++++++++-- ...to_output___files_restored_on_cache_hit.md | 46 +++ .../auto_output_with_non_auto_input.md | 39 ++ .../explicit_input_ignores_fspy_reads.md | 34 ++ ...ob_output___only_matched_files_restored.md | 60 ++++ ...ut_negative_does_not_drop_output_writes.md | 40 +++ ...ve_output___excluded_files_not_restored.md | 60 ++++ .../output_config_change_invalidates_cache.md | 27 ++ .../fixtures/output_cache_test/vite-task.json | 34 +- crates/vite_task_graph/run-config.ts | 8 +- crates/vite_task_graph/src/config/mod.rs | 57 +-- crates/vite_task_graph/src/config/user.rs | 24 +- crates/vite_task_plan/src/plan.rs | 8 +- ...ery_tool_synthetic_task_in_user_task.jsonc | 2 +- .../additional_env/snapshots/task_graph.jsonc | 4 +- ...query___cache_enables_script_caching.jsonc | 2 +- ...ching_even_when_cache_tasks_is_false.jsonc | 2 +- ..._per_task_cache_true_enables_caching.jsonc | 2 +- .../snapshots/task_graph.jsonc | 8 +- .../query_echo_and_lint_with_extra_args.jsonc | 2 +- .../query_lint_and_echo_with_extra_args.jsonc | 2 +- .../query_normal_task_with_extra_args.jsonc | 2 +- .../query_synthetic_task_in_user_task.jsonc | 2 +- ...synthetic_task_in_user_task_with_cwd.jsonc | 2 +- ...ic_task_with_extra_args_in_user_task.jsonc | 2 +- .../cache_keys/snapshots/task_graph.jsonc | 8 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 4 +- ...query_another_task_cached_by_default.jsonc | 2 +- .../query_task_cached_by_default.jsonc | 2 +- .../snapshots/task_graph.jsonc | 6 +- .../cache_sharing/snapshots/task_graph.jsonc | 6 +- .../snapshots/task_graph.jsonc | 2 +- .../snapshots/task_graph.jsonc | 6 +- ...script_cached_when_global_cache_true.jsonc | 2 +- ...y_task_cached_when_global_cache_true.jsonc | 2 +- .../snapshots/task_graph.jsonc | 4 +- ..._should_put_synthetic_task_under_cwd.jsonc | 2 +- ..._should_not_affect_expanded_task_cwd.jsonc | 2 +- .../cd_in_scripts/snapshots/task_graph.jsonc | 6 +- .../snapshots/task_graph.jsonc | 46 +-- .../conflict_test/snapshots/task_graph.jsonc | 6 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 16 +- .../snapshots/task_graph.jsonc | 20 +- ...extra_args_only_reach_requested_task.jsonc | 4 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 26 +- .../snapshots/task_graph.jsonc | 2 +- .../snapshots/task_graph.jsonc | 2 +- ...d___cache_enables_inner_task_caching.jsonc | 2 +- ...opagates_to_nested_run_without_flags.jsonc | 2 +- ...es_not_propagate_into_nested___cache.jsonc | 2 +- .../snapshots/task_graph.jsonc | 8 +- .../nested_tasks/snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 2 +- .../snapshots/task_graph.jsonc | 10 +- .../snapshots/task_graph.jsonc | 2 +- .../snapshots/task_graph.jsonc | 16 +- .../script_hooks/snapshots/task_graph.jsonc | 12 +- .../snapshots/task_graph.jsonc | 6 +- .../snapshots/task_graph.jsonc | 8 +- .../snapshots/task_graph.jsonc | 4 +- ...uery_shell_fallback_for_pipe_command.jsonc | 2 +- .../shell_fallback/snapshots/task_graph.jsonc | 2 +- ...does_not_affect_expanded_query_tasks.jsonc | 2 +- ..._not_affect_expanded_synthetic_cache.jsonc | 2 +- ..._untrackedEnv_inherited_by_synthetic.jsonc | 2 +- ...h_cache_true_enables_synthetic_cache.jsonc | 2 +- .../snapshots/task_graph.jsonc | 10 +- .../query_synthetic_in_subpackage.jsonc | 2 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 6 +- .../vpr_shorthand/snapshots/task_graph.jsonc | 4 +- .../query_dev_filter_from_root.jsonc | 2 +- .../snapshots/query_dev_in_subpackage.jsonc | 2 +- .../snapshots/task_graph.jsonc | 2 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 8 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 8 +- .../snapshots/task_graph.jsonc | 4 +- .../snapshots/task_graph.jsonc | 6 +- docs/output-restoration-research.md | 117 ++++++ docs/output-restoration.md | 120 +++++++ 93 files changed, 1211 insertions(+), 464 deletions(-) create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/README.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output___files_restored_on_cache_hit.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output_with_non_auto_input.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/explicit_input_ignores_fspy_reads.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/glob_output___only_matched_files_restored.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/input_negative_does_not_drop_output_writes.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/negative_output___excluded_files_not_restored.md create mode 100644 crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_config_change_invalidates_cache.md create mode 100644 docs/output-restoration-research.md create mode 100644 docs/output-restoration.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b9d75801..2056680ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - **Added** `output` field for cached tasks: archives output files matching the configured globs after a successful run and restores them on cache hit. Patterns are relative to the package directory; supports negative patterns (e.g. `"!dist/cache/**"`) and `{pattern, base}` form for explicit base. ([#321](https://github.com/voidzero-dev/vite-task/pull/321)) - **Fixed** Windows cached tasks can now run package shims rewritten through PowerShell; default env passthrough now preserves `PATHEXT` ([#366](https://github.com/voidzero-dev/vite-task/pull/366)) - **Added** Platform support for targets without `input` auto-inference (e.g. Android). Tasks still run; those relying on auto-inference run uncached, with the summary noting that `input` must be configured manually to enable caching ([#352](https://github.com/voidzero-dev/vite-task/pull/352)) +- **Added** `output` field for cached tasks: 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/**"`) ([#321](https://github.com/voidzero-dev/vite-task/pull/321)) - **Fixed** `vp run` no longer aborts with `failed to prepare the command for injection: Invalid argument` when the user environment already has `LD_PRELOAD` (Linux) or `DYLD_INSERT_LIBRARIES` (macOS) set. The tracer shim is now appended to any existing value and placed last, so user preloads keep their symbol-interposition precedence ([#340](https://github.com/voidzero-dev/vite-task/issues/340)) - **Changed** Arguments passed after a task name (e.g. `vp run test some-filter`) are now forwarded only to that task. Tasks pulled in via `dependsOn` no longer receive them ([#324](https://github.com/voidzero-dev/vite-task/issues/324)) - **Fixed** Windows file access tracking no longer panics when a task touches malformed paths that cannot be represented as workspace-relative inputs ([#330](https://github.com/voidzero-dev/vite-task/pull/330)) diff --git a/crates/vite_task/docs/task-cache.md b/crates/vite_task/docs/task-cache.md index 440901ccd..d6c75a910 100644 --- a/crates/vite_task/docs/task-cache.md +++ b/crates/vite_task/docs/task-cache.md @@ -92,7 +92,7 @@ The cache entry key uniquely identifies a command execution context: ```rust pub struct CacheEntryKey { pub spawn_fingerprint: SpawnFingerprint, - pub input_config: ResolvedInputConfig, + pub input_config: ResolvedGlobConfig, } ``` @@ -303,7 +303,7 @@ Cache entries are serialized using `bincode` for efficient storage. │ ────────────────────── │ │ CacheEntryKey { │ │ spawn_fingerprint: SpawnFingerprint { ... }, │ -│ input_config: ResolvedInputConfig { ... }, │ +│ input_config: ResolvedGlobConfig { ... }, │ │ } │ │ ExecutionCacheKey::UserTask { │ │ task_name: "build", │ diff --git a/crates/vite_task/src/session/execute/mod.rs b/crates/vite_task/src/session/execute/mod.rs index 29719a74f..903f8d09e 100644 --- a/crates/vite_task/src/session/execute/mod.rs +++ b/crates/vite_task/src/session/execute/mod.rs @@ -12,7 +12,7 @@ use std::{cell::RefCell, collections::BTreeMap, io::Write as _, sync::Arc, time: use futures_util::{FutureExt, StreamExt, future::LocalBoxFuture, stream::FuturesUnordered}; use petgraph::Direction; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use tokio::sync::Semaphore; use tokio_util::sync::CancellationToken; use vite_path::{AbsolutePath, RelativePathBuf}; @@ -21,6 +21,7 @@ use vite_task_plan::{ ExecutionGraph, ExecutionItemDisplay, ExecutionItemKind, LeafExecutionKind, SpawnExecution, cache_metadata::CacheMetadata, execution_graph::ExecutionNodeIndex, }; +use wax::Program as _; #[cfg(fspy)] use self::tracked_accesses::TrackedPathAccesses; @@ -291,10 +292,11 @@ struct CacheState<'a> { /// Captured stdout/stderr for cache replay. Written in place during drain; /// always present (possibly empty) once we reach the cache-update phase. std_outputs: Vec, - /// `Some` iff fspy is enabled (`includes_auto`). Holds the resolved - /// negative globs used by [`TrackedPathAccesses::from_raw`] to filter - /// tracked accesses. `None` means fspy tracking is off for this task. - fspy_negatives: Option>>, + /// Fspy tracking status and pre-resolved input negative globs. + /// `None` means fspy tracking is off for this task. `Some(globs)` means + /// fspy is on; the globs are used to filter inferred input reads (not + /// writes — output negatives are applied separately during archiving). + fspy_input_negatives: Option>>, } /// Post-execution summary of what fspy observed for a single task. Used in the @@ -303,6 +305,9 @@ struct CacheState<'a> { /// happened (see the `let tracking = ...` fork in `execute_spawn`). struct TrackingOutcome { path_reads: HashMap, + /// All paths the task wrote to. Consumed by `collect_and_archive_outputs` + /// when `output_config.includes_auto` is set. + path_writes: FxHashSet, /// First path that was both read and written during execution, if any. /// A non-empty value means caching this task is unsound. read_write_overlap: Option, @@ -441,36 +446,38 @@ pub async fn execute_spawn( // ───────────────────────────────────────────────────────────────────── let mut mode: ExecutionMode<'_> = match cache_metadata { Some(metadata) => { - let fspy = if metadata.input_config.includes_auto { - // Resolve negative globs for fspy path filtering - // (already workspace-root-relative). - match metadata - .input_config - .negative_globs - .iter() - .map(|p| Ok(wax::Glob::new(p.as_str())?.into_owned())) - .collect::>>() - { - Ok(negs) => Some(negs), - Err(err) => { - leaf_reporter.finish( - None, - CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), - Some(ExecutionError::PostRunFingerprint(err)), - ); - return SpawnOutcome::Failed; + 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::>>() + { + 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 + }; ExecutionMode::Cached { pipe_writers: stdio_config.writers, state: CacheState { metadata, globbed_inputs, std_outputs: Vec::new(), - fspy_negatives: fspy, + fspy_input_negatives: fspy, }, } } @@ -482,7 +489,9 @@ pub async fn execute_spawn( // 5. Derive the arguments for `spawn()` from the mode without consuming it. let (spawn_stdio, fspy_enabled) = match &mode { - ExecutionMode::Cached { state, .. } => (SpawnStdio::Piped, state.fspy_negatives.is_some()), + ExecutionMode::Cached { state, .. } => { + (SpawnStdio::Piped, state.fspy_input_negatives.is_some()) + } ExecutionMode::Uncached { pipe_writers: Some(_) } => (SpawnStdio::Piped, false), ExecutionMode::Uncached { pipe_writers: None } => (SpawnStdio::Inherited, false), }; @@ -566,69 +575,103 @@ pub async fn execute_spawn( // 9. Cache update (only when we were in `Cached` mode). Errors during cache // update are reported but do not affect the exit status we return. - let (cache_update_status, cache_error) = if let ExecutionMode::Cached { state, .. } = mode { - let CacheState { metadata, globbed_inputs, std_outputs, fspy_negatives } = state; - - // Post-execution summary of what fspy observed. `Some` iff tracking was - // both requested (`fspy_negatives.is_some()`) and compiled in (`cfg(fspy)`). - // On a `cfg(not(fspy))` build this is always `None`, and the match below - // short-circuits to `FspyUnsupported` when tracking was needed. - let tracking: Option = { - #[cfg(fspy)] - { - outcome.path_accesses.as_ref().zip(fspy_negatives.as_deref()).map(|(raw, negs)| { - let tracked = TrackedPathAccesses::from_raw(raw, cache_base_path, negs); - let read_write_overlap = tracked - .path_reads - .keys() - .find(|p| tracked.path_writes.contains(*p)) - .cloned(); - TrackingOutcome { path_reads: tracked.path_reads, read_write_overlap } - }) - } - #[cfg(not(fspy))] - { - None - } - }; - - let cancelled = fast_fail_token.is_cancelled() || interrupt_token.is_cancelled(); - if cancelled { - // Cancelled (Ctrl-C or sibling failure) — result is untrustworthy - (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::Cancelled), None) - } else if outcome.exit_status.success() { - // fspy-inferred read-write overlap: the task wrote to a file it also - // read, so the prerun input hashes are stale and caching is unsound. - // (We only check fspy-inferred reads, not globbed_inputs. A task that - // writes to a glob-matched file without reading it produces perpetual - // cache misses but not a correctness bug.) - if let Some(TrackingOutcome { read_write_overlap: Some(path), .. }) = &tracking { - ( - CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::InputModified { - path: path.clone(), - }), - None, - ) - } else if tracking.is_none() && fspy_negatives.is_some() { - // Task requested fspy auto-inference but this binary was built - // without `cfg(fspy)`. Task ran, but we can't compute a valid - // cache entry without tracked path accesses. - (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::FspyUnsupported), None) - } else { - // Paths already in globbed_inputs are skipped: the overlap check - // above guarantees no input modification, so the prerun hash is - // the correct post-exec hash. - let empty_path_reads = HashMap::default(); - let path_reads = tracking.as_ref().map_or(&empty_path_reads, |t| &t.path_reads); - match PostRunFingerprint::create(path_reads, cache_base_path, &globbed_inputs) { - Ok(post_run_fingerprint) => { - // Collect output files and create archive - let output_archive = - match collect_and_archive_outputs(metadata, cache_base_path, cache_dir) + let (cache_update_status, cache_error) = 'cache_update: { + if let ExecutionMode::Cached { state, .. } = mode { + let CacheState { metadata, globbed_inputs, std_outputs, fspy_input_negatives } = state; + + // Post-execution summary of what fspy observed. `Some` iff tracking + // was both requested (`fspy_input_negatives.is_some()`) and compiled + // in (`cfg(fspy)`). On a `cfg(not(fspy))` build this is always + // `None`, and the match below short-circuits to `FspyUnsupported` + // when tracking was needed. + // + // `path_reads` is gated on `input_config.includes_auto` and filtered + // by input negatives. When input auto is disabled (even if fspy is + // enabled for output tracking) no reads contribute to the + // fingerprint or the read-write overlap check. Writes are NOT + // filtered here — output negatives are applied later inside + // `collect_and_archive_outputs`. The split avoids + // `input: ["!dist/**"]` accidentally dropping writes to `dist/**`, + // which would break archive restoration. + let tracking: Option = { + #[cfg(fspy)] + { + outcome.path_accesses.as_ref().map(|raw| { + let tracked = TrackedPathAccesses::from_raw(raw, cache_base_path); + let path_reads: HashMap = + if metadata.input_config.includes_auto + && let Some(negatives) = fspy_input_negatives.as_deref() { + tracked + .path_reads + .iter() + .filter(|(path, _)| { + !negatives.iter().any(|neg| neg.is_match(path.as_str())) + }) + .map(|(path, read)| (path.clone(), *read)) + .collect() + } else { + HashMap::default() + }; + let read_write_overlap = + path_reads.keys().find(|p| tracked.path_writes.contains(*p)).cloned(); + TrackingOutcome { + path_reads, + path_writes: tracked.path_writes, + read_write_overlap, + } + }) + } + #[cfg(not(fspy))] + { + None + } + }; + + let cancelled = fast_fail_token.is_cancelled() || interrupt_token.is_cancelled(); + if cancelled { + // Cancelled (Ctrl-C or sibling failure) — result is untrustworthy + (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::Cancelled), None) + } else if outcome.exit_status.success() { + // fspy-inferred read-write overlap: the task wrote to a file it + // also read (as an inferred input), so the prerun input hashes + // are stale and caching is unsound. Reads excluded by input + // negatives don't count — `tracking.path_reads` is already + // filtered, so the overlap check is too. (We only check + // fspy-inferred reads, not globbed_inputs. A task that writes + // to a glob-matched file without reading it produces perpetual + // cache misses but not a correctness bug.) + if let Some(TrackingOutcome { read_write_overlap: Some(path), .. }) = &tracking { + ( + CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::InputModified { + path: path.clone(), + }), + None, + ) + } else if tracking.is_none() && fspy_input_negatives.is_some() { + // Task requested fspy auto-inference but this binary was built + // without `cfg(fspy)`. Task ran, but we can't compute a valid + // cache entry without tracked path accesses. + (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::FspyUnsupported), None) + } else { + // Paths already in globbed_inputs are skipped: the overlap check + // above guarantees no input modification, so the prerun hash is + // the correct post-exec hash. `tracking.path_reads` is already + // filtered by input negatives. + let empty_path_reads = HashMap::default(); + let path_reads = tracking.as_ref().map_or(&empty_path_reads, |t| &t.path_reads); + match PostRunFingerprint::create(path_reads, cache_base_path, &globbed_inputs) { + Ok(post_run_fingerprint) => { + // Collect output files and create archive + let output_archive = match collect_and_archive_outputs( + metadata, + tracking.as_ref(), + cache_base_path, + cache_dir, + ) { Ok(archive) => archive, Err(err) => { - let result = ( + break 'cache_update ( CacheUpdateStatus::NotUpdated( CacheNotUpdatedReason::CacheDisabled, ), @@ -637,46 +680,43 @@ pub async fn execute_spawn( source: err, }), ); - leaf_reporter.finish( - Some(outcome.exit_status), - result.0, - result.1, - ); - return SpawnOutcome::Spawned(outcome.exit_status); } }; - let new_cache_value = CacheEntryValue { - post_run_fingerprint, - std_outputs: std_outputs.into(), - duration, - globbed_inputs, - output_archive, - }; - match cache.update(metadata, new_cache_value, cache_dir).await { - Ok(()) => (CacheUpdateStatus::Updated, None), - Err(err) => ( - CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), - Some(ExecutionError::Cache { - kind: CacheErrorKind::Update, - source: err, - }), - ), + let new_cache_value = CacheEntryValue { + post_run_fingerprint, + std_outputs: std_outputs.into(), + duration, + globbed_inputs, + output_archive, + }; + match cache.update(metadata, new_cache_value, cache_dir).await { + Ok(()) => (CacheUpdateStatus::Updated, None), + Err(err) => ( + CacheUpdateStatus::NotUpdated( + CacheNotUpdatedReason::CacheDisabled, + ), + Some(ExecutionError::Cache { + kind: CacheErrorKind::Update, + source: err, + }), + ), + } } + Err(err) => ( + CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), + Some(ExecutionError::PostRunFingerprint(err)), + ), } - Err(err) => ( - CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), - Some(ExecutionError::PostRunFingerprint(err)), - ), } + } else { + // Execution failed with non-zero exit status — don't update cache + (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::NonZeroExitStatus), None) } } else { - // Execution failed with non-zero exit status — don't update cache - (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::NonZeroExitStatus), None) + // Caching was disabled for this task + (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), None) } - } else { - // Caching was disabled for this task - (CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::CacheDisabled), None) }; // 7. Finish the leaf execution with the result and optional cache error. @@ -687,36 +727,64 @@ pub async fn execute_spawn( SpawnOutcome::Spawned(outcome.exit_status) } -/// Collect output files matching the configured globs and create a tar.zst -/// archive in the cache directory. +/// Collect output files and create a tar.zst archive in the cache directory. +/// +/// Output files are determined by: +/// - fspy-tracked writes (when `output_config.includes_auto` is true) +/// - Positive output globs (always, if configured) +/// - Filtered by negative output globs /// -/// Returns `Some(archive_filename)` if files were archived, `None` if the -/// output config has no positive globs or no files matched. +/// Returns `Some(archive_filename)` if files were archived, `None` if no output files. fn collect_and_archive_outputs( - cache_metadata: &CacheMetadata, + cache_metadata: &vite_task_plan::cache_metadata::CacheMetadata, + tracking: Option<&TrackingOutcome>, workspace_root: &AbsolutePath, cache_dir: &AbsolutePath, ) -> anyhow::Result> { let output_config = &cache_metadata.output_config; - if output_config.positive_globs.is_empty() { - return Ok(None); + // Collect output files from auto-detection (fspy writes) + let mut output_files: FxHashSet = FxHashSet::default(); + + if output_config.includes_auto + && let Some(t) = tracking + { + output_files.extend(t.path_writes.iter().cloned()); } - let output_files = glob_inputs::collect_glob_paths( - workspace_root, - &output_config.positive_globs, - &output_config.negative_globs, - )?; + // Collect output files from positive globs + if !output_config.positive_globs.is_empty() { + let glob_paths = glob_inputs::collect_glob_paths( + workspace_root, + &output_config.positive_globs, + &output_config.negative_globs, + )?; + output_files.extend(glob_paths); + } + + // Apply negative globs to auto-detected files + if output_config.includes_auto && !output_config.negative_globs.is_empty() { + let negatives: Vec> = output_config + .negative_globs + .iter() + .map(|p| Ok(wax::Glob::new(p.as_str())?.into_owned())) + .collect::>()?; + output_files.retain(|path| !negatives.iter().any(|neg| neg.is_match(path.as_str()))); + } if output_files.is_empty() { return Ok(None); } + // Sort for deterministic archive content + let mut sorted_files: Vec = output_files.into_iter().collect(); + sorted_files.sort(); + + // Create archive with UUID filename let archive_name: Str = vite_str::format!("{}.tar.zst", uuid::Uuid::new_v4()); let archive_path = cache_dir.join(archive_name.as_str()); - archive::create_output_archive(workspace_root, &output_files, &archive_path)?; + archive::create_output_archive(workspace_root, &sorted_files, &archive_path)?; Ok(Some(archive_name)) } diff --git a/crates/vite_task/src/session/execute/tracked_accesses.rs b/crates/vite_task/src/session/execute/tracked_accesses.rs index 83596cc7d..6e3596512 100644 --- a/crates/vite_task/src/session/execute/tracked_accesses.rs +++ b/crates/vite_task/src/session/execute/tracked_accesses.rs @@ -1,4 +1,8 @@ //! Normalize raw fspy path accesses into workspace-relative, filtered form. +//! +//! User-configured negative globs are NOT applied here. They are applied later, +//! separately for reads (input config) and writes (output config), since those +//! two configs are independent. #![cfg(fspy)] use std::collections::hash_map::Entry; @@ -21,22 +25,19 @@ pub struct TrackedPathAccesses { } impl TrackedPathAccesses { - /// Build from fspy's raw iterable by stripping the workspace prefix, - /// normalizing `..` components, and filtering against the negative globs. - pub fn from_raw( - raw: &PathAccessIterable, - workspace_root: &AbsolutePath, - resolved_negatives: &[wax::Glob<'static>], - ) -> Self { + /// Build from fspy's raw iterable by stripping the workspace prefix and + /// normalizing `..` components. `.git/*` paths are skipped. User-configured + /// negatives are applied by the caller (see module docs). + pub fn from_raw(raw: &PathAccessIterable, workspace_root: &AbsolutePath) -> Self { let mut accesses = Self::default(); for access in raw.iter() { - // Strip workspace root, clean `..` components, and filter in one pass. + // Strip workspace root and clean `..` components in one pass. // fspy may report paths like `packages/sub-pkg/../shared/dist/output.js`. let relative_path = access.path.strip_path_prefix(workspace_root, |strip_result| { let Ok(stripped_path) = strip_result else { return None; }; - normalize_tracked_workspace_path(stripped_path, resolved_negatives) + normalize_tracked_workspace_path(stripped_path) }); let Some(relative_path) = relative_path else { @@ -71,10 +72,7 @@ impl TrackedPathAccesses { clippy::disallowed_types, reason = "fspy strip_path_prefix exposes std::path::Path; convert to RelativePathBuf immediately" )] -fn normalize_tracked_workspace_path( - stripped_path: &std::path::Path, - resolved_negatives: &[wax::Glob<'static>], -) -> Option { +fn normalize_tracked_workspace_path(stripped_path: &std::path::Path) -> Option { // On Windows, paths are possible to be still absolute after stripping the workspace root. // For example: c:\workspace\subdir\c:\workspace\subdir // Just ignore those accesses. @@ -90,12 +88,6 @@ fn normalize_tracked_workspace_path( return None; } - if !resolved_negatives.is_empty() - && resolved_negatives.iter().any(|neg| wax::Program::is_match(neg, relative.as_str())) - { - return None; - } - Some(relative) } @@ -111,8 +103,7 @@ mod tests { clippy::disallowed_types, reason = "normalize_tracked_workspace_path requires std::path::Path for fspy strip_path_prefix output" )] - let relative_path = - normalize_tracked_workspace_path(std::path::Path::new(r"foo\C:\bar"), &[]); + let relative_path = normalize_tracked_workspace_path(std::path::Path::new(r"foo\C:\bar")); assert!(relative_path.is_none()); } } diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/fspy_env___not_set_when_auto_inference_disabled.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/fspy_env___not_set_when_auto_inference_disabled.md index 256db2ea9..e68888bf0 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/fspy_env___not_set_when_auto_inference_disabled.md +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/input_cache_test/snapshots/fspy_env___not_set_when_auto_inference_disabled.md @@ -7,5 +7,5 @@ should not see `FSPY` set. ``` $ vtt print-env FSPY -(undefined) +1 ``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/README.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/README.md new file mode 100644 index 000000000..626799f0f --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/README.md @@ -0,0 +1 @@ +v1 diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml index d554d79b4..a170c1ef2 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots.toml @@ -1,38 +1,226 @@ [[e2e]] -name = "output_globs___files_restored_on_cache_hit" +name = "auto_output___files_restored_on_cache_hit" comment = """ -With explicit output globs (`dist/**`), the first run writes a file to -`dist/`. After deleting `dist/`, a second run with no input changes is a -cache hit and the archived output file is restored. +Auto output detection (default): output files written by the task are +restored on a cache hit. """ steps = [ - # First run - cache miss, writes dist/output.txt - ["vt", "run", "build"], - # Verify file was written - ["vtt", "print-file", "dist/output.txt"], - # Delete dist/ to prove restoration is real - ["vtt", "rm", "-rf", "dist"], - # Second run - cache hit, restores dist/output.txt from archive - ["vt", "run", "build"], - # File should be restored - ["vtt", "print-file", "dist/output.txt"], + { argv = [ + "vt", + "run", + "auto-output", + ], comment = "first run writes dist/out.txt" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "output exists after the build" }, + { argv = [ + "vtt", + "rm", + "dist/out.txt", + ], comment = "delete only the file (keep dir to avoid an fspy inferred-input miss on Windows)" }, + { argv = [ + "vt", + "run", + "auto-output", + ], comment = "cache hit, should restore dist/out.txt" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "output was restored from the archive" }, ] [[e2e]] -name = "output_globs___negative_excludes_files_from_archive" +name = "glob_output___only_matched_files_restored" comment = """ -A file matched by a negative output glob is not archived, so it is not -restored on cache hit. +Glob output: only files matching the configured output globs are restored +on a cache hit; files produced outside those globs are left alone. """ steps = [ - # First run - writes both dist/keep.txt and dist/skip.txt - ["vt", "run", "build-with-negative"], - # Both files exist after the run - ["vtt", "print-file", "dist/keep.txt"], - ["vtt", "print-file", "dist/skip.txt"], - # Delete dist/ to prove restoration is real - ["vtt", "rm", "-rf", "dist"], - # Second run - cache hit, only dist/keep.txt is restored - ["vt", "run", "build-with-negative"], - ["vtt", "print-file", "dist/keep.txt"], + { argv = [ + "vt", + "run", + "glob-output", + ], comment = "first run writes dist/out.txt and tmp/temp.txt" }, + { argv = [ + "vtt", + "rm", + "dist/out.txt", + ], comment = "delete the glob-matched output" }, + { argv = [ + "vtt", + "rm", + "tmp/temp.txt", + ], comment = "delete the non-matched output" }, + { argv = [ + "vt", + "run", + "glob-output", + ], comment = "cache hit: should restore dist/out.txt but not tmp/temp.txt" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "dist/out.txt was restored" }, + { argv = [ + "vtt", + "print-file", + "tmp/temp.txt", + ], comment = "should fail - tmp not in output globs" }, +] + +[[e2e]] +name = "auto_output_with_non_auto_input" +comment = """ +Auto output works even when input tracking is explicit +(`input: [\"src/**\"]`). Output auto-detection and input auto-detection +are independent. +""" +steps = [ + { argv = [ + "vt", + "run", + "auto-output-no-auto-input", + ], comment = "first run: input src/** (no auto), output default (auto)" }, + { argv = [ + "vtt", + "rm", + "dist/out.txt", + ], comment = "delete the output" }, + { argv = [ + "vt", + "run", + "auto-output-no-auto-input", + ], comment = "cache hit - output files should still be restored" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "output was restored" }, +] + +[[e2e]] +name = "negative_output___excluded_files_not_restored" +comment = """ +Negative output globs exclude matching files from the cache archive, so +they are not restored on a cache hit even though the task produced them. +""" +steps = [ + { argv = [ + "vt", + "run", + "negative-output", + ], comment = "first run writes dist/out.txt and dist/cache/tmp.txt" }, + { argv = [ + "vtt", + "rm", + "dist/out.txt", + ], comment = "delete the archived output" }, + { argv = [ + "vtt", + "rm", + "dist/cache/tmp.txt", + ], comment = "delete the excluded output" }, + { argv = [ + "vt", + "run", + "negative-output", + ], comment = "cache hit: should restore dist/out.txt but NOT dist/cache/tmp.txt" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "dist/out.txt was restored" }, + { argv = [ + "vtt", + "print-file", + "dist/cache/tmp.txt", + ], comment = "should fail - excluded by !dist/cache/**" }, +] + +[[e2e]] +name = "output_config_change_invalidates_cache" +comment = """ +Changing a task's output configuration invalidates the cache entry — +the next run is a miss, not a hit of the stale archive. +""" +steps = [ + { argv = [ + "vt", + "run", + "output-config-change", + ], comment = "first run populates the cache" }, + { argv = [ + "vtt", + "replace-file-content", + "vite-task.json", + "REPLACE_ME", + "dist/**", + ], comment = "change the output globs in the task config" }, + { argv = [ + "vt", + "run", + "output-config-change", + ], comment = "cache miss: output config changed" }, +] + +[[e2e]] +name = "input_negative_does_not_drop_output_writes" +comment = """ +Input negative globs must not drop matching writes from the output +archive. Here the user excludes `dist/**` from inferred inputs (so +rewriting dist/ won't mark inputs as modified), but default auto output +should still capture dist writes and restore them on a cache hit. +""" +steps = [ + { argv = [ + "vt", + "run", + "input-neg-dist-auto-output", + ], comment = "first run writes dist/out.txt" }, + { argv = [ + "vtt", + "rm", + "dist/out.txt", + ], comment = "delete the output" }, + { argv = [ + "vt", + "run", + "input-neg-dist-auto-output", + ], comment = "cache hit should restore dist/out.txt" }, + { argv = [ + "vtt", + "print-file", + "dist/out.txt", + ], comment = "output was restored despite dist/** being a negative input glob" }, +] + +[[e2e]] +name = "explicit_input_ignores_fspy_reads" +comment = """ +When input auto is disabled (explicit globs only), unrelated reads +tracked by fspy must NOT become inferred inputs. Default auto output +still needs fspy for write tracking, but reads outside `input: [\"src/**\"]` +should be ignored. +""" +steps = [ + { argv = [ + "vt", + "run", + "explicit-input-auto-output", + ], comment = "first run reads README.md (not in input globs) and captures the output" }, + { argv = [ + "vtt", + "replace-file-content", + "README.md", + "v1", + "v2", + ], comment = "modify README.md — not an input, so it must not invalidate the cache" }, + { argv = [ + "vt", + "run", + "explicit-input-auto-output", + ], comment = "cache hit: README.md not in input globs" }, ] diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output___files_restored_on_cache_hit.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output___files_restored_on_cache_hit.md new file mode 100644 index 000000000..08ec43680 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output___files_restored_on_cache_hit.md @@ -0,0 +1,46 @@ +# auto_output___files_restored_on_cache_hit + +Auto output detection (default): output files written by the task are +restored on a cache hit. + +## `vt run auto-output` + +first run writes dist/out.txt + +``` +$ vtt write-file dist/out.txt built +``` + +## `vtt print-file dist/out.txt` + +output exists after the build + +``` +built +``` + +## `vtt rm dist/out.txt` + +delete only the file (keep dir to avoid an fspy inferred-input miss on Windows) + +``` +``` + +## `vt run auto-output` + +cache hit, should restore dist/out.txt + +``` +$ vtt write-file dist/out.txt built ◉ cache hit, replaying + +--- +vt run: cache hit. +``` + +## `vtt print-file dist/out.txt` + +output was restored from the archive + +``` +built +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output_with_non_auto_input.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output_with_non_auto_input.md new file mode 100644 index 000000000..ba8c3e460 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/auto_output_with_non_auto_input.md @@ -0,0 +1,39 @@ +# auto_output_with_non_auto_input + +Auto output works even when input tracking is explicit +(`input: ["src/**"]`). Output auto-detection and input auto-detection +are independent. + +## `vt run auto-output-no-auto-input` + +first run: input src/** (no auto), output default (auto) + +``` +$ vtt write-file dist/out.txt built +``` + +## `vtt rm dist/out.txt` + +delete the output + +``` +``` + +## `vt run auto-output-no-auto-input` + +cache hit - output files should still be restored + +``` +$ vtt write-file dist/out.txt built ◉ cache hit, replaying + +--- +vt run: cache hit. +``` + +## `vtt print-file dist/out.txt` + +output was restored + +``` +built +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/explicit_input_ignores_fspy_reads.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/explicit_input_ignores_fspy_reads.md new file mode 100644 index 000000000..c0e5e0f9f --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/explicit_input_ignores_fspy_reads.md @@ -0,0 +1,34 @@ +# explicit_input_ignores_fspy_reads + +When input auto is disabled (explicit globs only), unrelated reads +tracked by fspy must NOT become inferred inputs. Default auto output +still needs fspy for write tracking, but reads outside `input: ["src/**"]` +should be ignored. + +## `vt run explicit-input-auto-output` + +first run reads README.md (not in input globs) and captures the output + +``` +$ vtt print-file README.md +v1 +``` + +## `vtt replace-file-content README.md v1 v2` + +modify README.md — not an input, so it must not invalidate the cache + +``` +``` + +## `vt run explicit-input-auto-output` + +cache hit: README.md not in input globs + +``` +$ vtt print-file README.md ◉ cache hit, replaying +v1 + +--- +vt run: cache hit. +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/glob_output___only_matched_files_restored.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/glob_output___only_matched_files_restored.md new file mode 100644 index 000000000..99df20c84 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/glob_output___only_matched_files_restored.md @@ -0,0 +1,60 @@ +# glob_output___only_matched_files_restored + +Glob output: only files matching the configured output globs are restored +on a cache hit; files produced outside those globs are left alone. + +## `vt run glob-output` + +first run writes dist/out.txt and tmp/temp.txt + +``` +$ vtt write-file dist/out.txt built + +$ vtt write-file tmp/temp.txt temp + +--- +vt run: 0/2 cache hit (0%). (Run `vt run --last-details` for full details) +``` + +## `vtt rm dist/out.txt` + +delete the glob-matched output + +``` +``` + +## `vtt rm tmp/temp.txt` + +delete the non-matched output + +``` +``` + +## `vt run glob-output` + +cache hit: should restore dist/out.txt but not tmp/temp.txt + +``` +$ vtt write-file dist/out.txt built ◉ cache hit, replaying + +$ vtt write-file tmp/temp.txt temp ◉ cache hit, replaying + +--- +vt run: 2/2 cache hit (100%). (Run `vt run --last-details` for full details) +``` + +## `vtt print-file dist/out.txt` + +dist/out.txt was restored + +``` +built +``` + +## `vtt print-file tmp/temp.txt` + +should fail - tmp not in output globs + +``` +tmp/temp.txt: not found +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/input_negative_does_not_drop_output_writes.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/input_negative_does_not_drop_output_writes.md new file mode 100644 index 000000000..81153bb8a --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/input_negative_does_not_drop_output_writes.md @@ -0,0 +1,40 @@ +# input_negative_does_not_drop_output_writes + +Input negative globs must not drop matching writes from the output +archive. Here the user excludes `dist/**` from inferred inputs (so +rewriting dist/ won't mark inputs as modified), but default auto output +should still capture dist writes and restore them on a cache hit. + +## `vt run input-neg-dist-auto-output` + +first run writes dist/out.txt + +``` +$ vtt write-file dist/out.txt built +``` + +## `vtt rm dist/out.txt` + +delete the output + +``` +``` + +## `vt run input-neg-dist-auto-output` + +cache hit should restore dist/out.txt + +``` +$ vtt write-file dist/out.txt built ◉ cache hit, replaying + +--- +vt run: cache hit. +``` + +## `vtt print-file dist/out.txt` + +output was restored despite dist/** being a negative input glob + +``` +built +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/negative_output___excluded_files_not_restored.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/negative_output___excluded_files_not_restored.md new file mode 100644 index 000000000..e355a36d5 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/negative_output___excluded_files_not_restored.md @@ -0,0 +1,60 @@ +# negative_output___excluded_files_not_restored + +Negative output globs exclude matching files from the cache archive, so +they are not restored on a cache hit even though the task produced them. + +## `vt run negative-output` + +first run writes dist/out.txt and dist/cache/tmp.txt + +``` +$ vtt write-file dist/out.txt built + +$ vtt write-file dist/cache/tmp.txt temp + +--- +vt run: 0/2 cache hit (0%). (Run `vt run --last-details` for full details) +``` + +## `vtt rm dist/out.txt` + +delete the archived output + +``` +``` + +## `vtt rm dist/cache/tmp.txt` + +delete the excluded output + +``` +``` + +## `vt run negative-output` + +cache hit: should restore dist/out.txt but NOT dist/cache/tmp.txt + +``` +$ vtt write-file dist/out.txt built ◉ cache hit, replaying + +$ vtt write-file dist/cache/tmp.txt temp ◉ cache hit, replaying + +--- +vt run: 2/2 cache hit (100%). (Run `vt run --last-details` for full details) +``` + +## `vtt print-file dist/out.txt` + +dist/out.txt was restored + +``` +built +``` + +## `vtt print-file dist/cache/tmp.txt` + +should fail - excluded by !dist/cache/** + +``` +dist/cache/tmp.txt: not found +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_config_change_invalidates_cache.md b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_config_change_invalidates_cache.md new file mode 100644 index 000000000..ad0870994 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/snapshots/output_config_change_invalidates_cache.md @@ -0,0 +1,27 @@ +# output_config_change_invalidates_cache + +Changing a task's output configuration invalidates the cache entry — +the next run is a miss, not a hit of the stale archive. + +## `vt run output-config-change` + +first run populates the cache + +``` +$ vtt write-file dist/out.txt built +``` + +## `vtt replace-file-content vite-task.json REPLACE_ME dist/**` + +change the output globs in the task config + +``` +``` + +## `vt run output-config-change` + +cache miss: output config changed + +``` +$ vtt write-file dist/out.txt built ○ cache miss: output configuration changed, executing +``` diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json index 6bd35a604..f7b271462 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/output_cache_test/vite-task.json @@ -1,15 +1,37 @@ { "tasks": { - "build": { - "command": "vtt write-file dist/output.txt built", - "input": ["src/**"], + "auto-output": { + "command": "vtt write-file dist/out.txt built", + "cache": true + }, + "glob-output": { + "command": "vtt write-file dist/out.txt built && vtt write-file tmp/temp.txt temp", "output": ["dist/**"], "cache": true }, - "build-with-negative": { - "command": "vtt write-file dist/keep.txt keep && vtt write-file dist/skip.txt skip", + "auto-output-no-auto-input": { + "command": "vtt write-file dist/out.txt built", + "input": ["src/**"], + "cache": true + }, + "negative-output": { + "command": "vtt write-file dist/out.txt built && vtt write-file dist/cache/tmp.txt temp", + "output": [{ "auto": true }, "!dist/cache/**"], + "cache": true + }, + "output-config-change": { + "command": "vtt write-file dist/out.txt built", + "output": ["REPLACE_ME"], + "cache": true + }, + "input-neg-dist-auto-output": { + "command": "vtt write-file dist/out.txt built", + "input": [{ "auto": true }, "!dist/**"], + "cache": true + }, + "explicit-input-auto-output": { + "command": "vtt print-file README.md", "input": ["src/**"], - "output": ["dist/**", "!dist/skip.txt"], "cache": true } } diff --git a/crates/vite_task_graph/run-config.ts b/crates/vite_task_graph/run-config.ts index 1fa4ee868..ebf41c36b 100644 --- a/crates/vite_task_graph/run-config.ts +++ b/crates/vite_task_graph/run-config.ts @@ -55,14 +55,16 @@ untrackedEnv?: Array, */ input?: Array, /** - * Output files to archive after a successful run and restore on cache hit. + * Output files to archive and restore on cache hit. * - * - Omitted or `[]` (empty): no output archiving (default) + * - Omitted: automatically tracks which files the task writes + * - `[]` (empty): disables output restoration entirely * - Glob patterns (e.g. `"dist/**"`) select specific output files, relative to the package directory * - `{pattern: "...", base: "workspace" | "package"}` specifies a glob with an explicit base directory + * - `{auto: true}` enables automatic file tracking * - Negative patterns (e.g. `"!dist/cache/**"`) exclude matched files */ -output?: Array, } | { +output?: Array, } | { /** * Whether to cache the task */ diff --git a/crates/vite_task_graph/src/config/mod.rs b/crates/vite_task_graph/src/config/mod.rs index 0e8c28f87..925f6a637 100644 --- a/crates/vite_task_graph/src/config/mod.rs +++ b/crates/vite_task_graph/src/config/mod.rs @@ -7,8 +7,8 @@ use rustc_hash::FxHashSet; use serde::Serialize; pub use user::{ AutoInput, EnabledCacheConfig, GlobWithBase, InputBase, ResolvedGlobalCacheConfig, - UserCacheConfig, UserGlobalCacheConfig, UserInputEntry, UserInputsConfig, UserOutputEntry, - UserRunConfig, UserTaskConfig, + UserCacheConfig, UserGlobalCacheConfig, UserInputEntry, UserInputsConfig, UserRunConfig, + UserTaskConfig, }; use vite_path::AbsolutePath; use vite_str::Str; @@ -75,7 +75,7 @@ impl ResolvedTaskOptions { workspace_root, )?; - let output_config = ResolvedGlobConfig::from_user_output_config( + let output_config = ResolvedGlobConfig::from_user_config( enabled_cache_config.output.as_ref(), dir, workspace_root, @@ -196,57 +196,6 @@ impl ResolvedGlobConfig { Ok(Self { includes_auto, positive_globs, negative_globs }) } - /// Resolve from user output configuration, making glob patterns workspace-root-relative. - /// - /// Unlike [`Self::from_user_config`], `None` and `Some([])` both produce an empty config - /// with `includes_auto = false` (no output archiving). - /// - /// # Errors - /// - /// Returns [`ResolveTaskConfigError`] if a glob pattern is invalid or resolves - /// outside the workspace root. - pub fn from_user_output_config( - user_outputs: Option<&Vec>, - package_dir: &AbsolutePath, - workspace_root: &AbsolutePath, - ) -> Result { - let mut positive_globs = BTreeSet::new(); - let mut negative_globs = BTreeSet::new(); - - let Some(entries) = user_outputs else { - return Ok(Self { includes_auto: false, positive_globs, negative_globs }); - }; - - for entry in entries { - match entry { - UserOutputEntry::Glob(pattern) => { - Self::insert_glob( - pattern.as_str(), - package_dir, - workspace_root, - &mut positive_globs, - &mut negative_globs, - )?; - } - UserOutputEntry::GlobWithBase(GlobWithBase { pattern, base }) => { - let base_dir = match base { - InputBase::Package => package_dir, - InputBase::Workspace => workspace_root, - }; - Self::insert_glob( - pattern.as_str(), - base_dir, - workspace_root, - &mut positive_globs, - &mut negative_globs, - )?; - } - } - } - - Ok(Self { includes_auto: false, positive_globs, negative_globs }) - } - /// Insert a glob pattern into the appropriate set (positive or negative), /// resolving it relative to the given base directory. fn insert_glob( diff --git a/crates/vite_task_graph/src/config/user.rs b/crates/vite_task_graph/src/config/user.rs index aeee38608..cc5571e69 100644 --- a/crates/vite_task_graph/src/config/user.rs +++ b/crates/vite_task_graph/src/config/user.rs @@ -65,22 +65,6 @@ pub enum UserInputEntry { /// Default (when field omitted): `[{auto: true}]` - infer from file accesses. pub type UserInputsConfig = Vec; -/// A single output entry in the `output` array. -/// -/// Outputs can be: -/// - Glob patterns as strings (resolved relative to the package directory) -/// - Object form with explicit base: `{ "pattern": "...", "base": "workspace" | "package" }` -#[derive(Debug, Deserialize, PartialEq, Eq, Clone)] -// TS derive macro generates code using std types that clippy disallows; skip derive during linting -#[cfg_attr(all(test, not(clippy)), derive(TS))] -#[serde(untagged)] -pub enum UserOutputEntry { - /// Glob pattern (positive or negative starting with `!`), resolved relative to package dir - Glob(Str), - /// Glob pattern with explicit base directory - GlobWithBase(GlobWithBase), -} - /// Cache-related fields of a task defined by user in `vite.config.*` #[derive(Debug, Deserialize, PartialEq, Eq)] // TS derive macro generates code using std types that clippy disallows; skip derive during linting @@ -142,15 +126,17 @@ pub struct EnabledCacheConfig { #[cfg_attr(all(test, not(clippy)), ts(inline))] pub input: Option, - /// Output files to archive after a successful run and restore on cache hit. + /// Output files to archive and restore on cache hit. /// - /// - Omitted or `[]` (empty): no output archiving (default) + /// - Omitted: automatically tracks which files the task writes + /// - `[]` (empty): disables output restoration entirely /// - Glob patterns (e.g. `"dist/**"`) select specific output files, relative to the package directory /// - `{pattern: "...", base: "workspace" | "package"}` specifies a glob with an explicit base directory + /// - `{auto: true}` enables automatic file tracking /// - Negative patterns (e.g. `"!dist/cache/**"`) exclude matched files #[serde(default)] #[cfg_attr(all(test, not(clippy)), ts(inline))] - pub output: Option>, + pub output: Option, } /// Options for user-defined tasks in `vite.config.*`, excluding the command. diff --git a/crates/vite_task_plan/src/plan.rs b/crates/vite_task_plan/src/plan.rs index 89e892b48..7d73671d5 100644 --- a/crates/vite_task_plan/src/plan.rs +++ b/crates/vite_task_plan/src/plan.rs @@ -495,7 +495,7 @@ fn resolve_synthetic_cache_config( } if let Some(output) = output { - let synthetic_output = ResolvedGlobConfig::from_user_output_config( + let synthetic_output = ResolvedGlobConfig::from_user_config( Some(&output), package_dir, workspace_path, @@ -903,11 +903,7 @@ mod tests { positive_globs: positive_globs.iter().map(|s| Str::from(*s)).collect(), negative_globs: BTreeSet::new(), }, - output_config: ResolvedGlobConfig { - includes_auto: false, - positive_globs: BTreeSet::new(), - negative_globs: BTreeSet::new(), - }, + output_config: ResolvedGlobConfig::default_auto(), } } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc index 63bad854a..70a30a680 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/query_tool_synthetic_task_in_user_task.jsonc @@ -62,7 +62,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc index da3f2d593..3690168f9 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/additional_env/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc index 63272b8d8..17487e76c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_script_caching.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc index af84a0ef1..be52cb30b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_enables_task_caching_even_when_cache_tasks_is_false.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc index 44c82a701..4c12deaae 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/query___cache_on_task_with_per_task_cache_true_enables_caching.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc index d98768c05..9f5fe4c2f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_cli_override/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -128,7 +128,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -167,7 +167,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc index f589579d4..48e0bcd9b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_echo_and_lint_with_extra_args.jsonc @@ -89,7 +89,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc index 586844bfc..4e1becc6d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_lint_and_echo_with_extra_args.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc index 07660f771..85eda7c07 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_normal_task_with_extra_args.jsonc @@ -62,7 +62,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc index a75b9dfc1..9b0261769 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc index a75b9dfc1..9b0261769 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_in_user_task_with_cwd.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc index 71683ee96..b49b7cdab 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/query_synthetic_task_with_extra_args_in_user_task.jsonc @@ -63,7 +63,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc index 13b2802fd..69c2936d8 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_keys/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc index 5129800c3..8b8f3c465 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_default/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc index 8f084f7de..85e08a273 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_enabled/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc index b344b082b..96355742c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_another_task_cached_by_default.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc index 78a406fa1..e4922043b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/query_task_cached_by_default.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc index cb6afda93..a6a4e8722 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_scripts_task_override/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc index ebfa2e8b3..406b3f570 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_sharing/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc index fb069d24d..3ae013b8e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_subcommand/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc index 55ebae45d..0e3aa085f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_tasks_disabled/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc index a82d5e2f9..bdc8c7add 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_script_cached_when_global_cache_true.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc index a16181471..e27d6cc80 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/query_task_cached_when_global_cache_true.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc index fff2e8ef4..ae2a02d9e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cache_true_no_force_enable/snapshots/task_graph.jsonc @@ -50,7 +50,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -89,7 +89,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc index d226a413b..7e658be2c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_lint_should_put_synthetic_task_under_cwd.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc index 4142b0960..3504841c9 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/query_cd_before_vt_run_should_not_affect_expanded_task_cwd.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc index a0ea080a3..09b02be13 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cd_in_scripts/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc index 9597c4b3a..2d5f8307c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/comprehensive_task_graph/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -184,7 +184,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -223,7 +223,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -262,7 +262,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -301,7 +301,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -340,7 +340,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -379,7 +379,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -418,7 +418,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -457,7 +457,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -496,7 +496,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -535,7 +535,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -574,7 +574,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -613,7 +613,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -652,7 +652,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -691,7 +691,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -730,7 +730,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -769,7 +769,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -808,7 +808,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -847,7 +847,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -886,7 +886,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc index e246a1db3..f88266a47 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/conflict_test/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc index 2c07f9bd1..02744a92a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/cycle_dependency/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -72,7 +72,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc index 9b4779c26..6cd676ac1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/dependency_both_topo_and_explicit/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -72,7 +72,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc index b3d46d315..dc309692e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/duplicate_package_names/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc index 0a88447df..15f5fee21 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/empty_package_test/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -107,7 +107,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -146,7 +146,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -185,7 +185,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -229,7 +229,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -268,7 +268,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -307,7 +307,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -346,7 +346,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc index 4c6c21e3b..258dbe37a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/explicit_deps_workspace/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -102,7 +102,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -141,7 +141,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -180,7 +180,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -219,7 +219,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -258,7 +258,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -302,7 +302,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -341,7 +341,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -380,7 +380,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -428,7 +428,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc index da9501116..87c2c445a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/query_extra_args_only_reach_requested_task.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -147,7 +147,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc index e483d70c4..0f8a5a02d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/extra_args_not_forwarded_to_depends_on/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc index 27c09ea17..749052ab4 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/filter_workspace/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -184,7 +184,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -223,7 +223,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -262,7 +262,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -301,7 +301,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -340,7 +340,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -379,7 +379,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -418,7 +418,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -457,7 +457,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -496,7 +496,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc index 11c015377..cc3c5380e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_trailing_slash/snapshots/task_graph.jsonc @@ -32,7 +32,7 @@ ] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc index b82a6e8da..f8a2b06f1 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/input_workspace_base/snapshots/task_graph.jsonc @@ -33,7 +33,7 @@ ] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc index 759b8f84e..bb31ec14a 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_nested___cache_enables_inner_task_caching.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc index a4f58176f..2429e6f57 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___cache_propagates_to_nested_run_without_flags.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc index 6e384f70a..2239dc902 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/query_outer___no_cache_does_not_propagate_into_nested___cache.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc index 1200a2faa..d1f6cf7ab 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_cache_override/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc index eef8a1a13..84427555e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/nested_tasks/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc index 599e3b086..0fa96e98b 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/package_self_dependency/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc index 9c50b6a60..3310ddddc 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/parallel_and_concurrency/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -184,7 +184,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc index aef412250..7c721c0cd 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm_workspace_packages_optional/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc index a902fcadd..721994b03 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/recursive_topological_workspace/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -184,7 +184,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -223,7 +223,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -262,7 +262,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -301,7 +301,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc index e5271222f..74c4fb4d8 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -184,7 +184,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -223,7 +223,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc index 2961d7313..2d6390832 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_disabled/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc index 36a3f67d0..89b34531f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_nested_run/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc index 005d03240..a7a338907 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/script_hooks_task_no_hook/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc index b3da6fda6..c1fadfcf5 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/query_shell_fallback_for_pipe_command.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc index 51fd7c317..c8d4d2825 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/shell_fallback/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc index 2df26b1a1..a706bf224 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_parent_cache_false_does_not_affect_expanded_query_tasks.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc index d5e183324..07de08fd6 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_script_cache_false_does_not_affect_expanded_synthetic_cache.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc index 812734076..e8ecc3a8f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_untrackedEnv_inherited_by_synthetic.jsonc @@ -61,7 +61,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc index 9ccca7a11..6c8b888d5 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/query_task_with_cache_true_enables_synthetic_cache.jsonc @@ -60,7 +60,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc index b550e3faf..28255bc3e 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_cache_disabled/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -128,7 +128,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -168,7 +168,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -207,7 +207,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc index 5a40fe048..073de3756 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/query_synthetic_in_subpackage.jsonc @@ -86,7 +86,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc index f45c1001a..29978073f 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/synthetic_in_subpackage/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc index 40ea1a092..281260a09 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/transitive_skip_intermediate/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc index 00be69c6c..a4fbd68c9 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr_shorthand/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc index ba1f67e9e..663a73858 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_filter_from_root.jsonc @@ -66,7 +66,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc index dc5f9a939..ad348fadb 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/query_dev_in_subpackage.jsonc @@ -66,7 +66,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc index d8a3142d4..8dd415471 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/windows_cmd_shim_rewrite/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc index f7ee35330..f105a6563 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_cd_no_skip/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc index 2a23ddc71..b6b8e743d 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_depends_on_passthrough/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -72,7 +72,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -111,7 +111,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -150,7 +150,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc index f031c893d..30236c51c 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_multi_command/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc index 5e3cee720..4cb032386 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_mutual_recursion/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -145,7 +145,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc index 5a64e4c3a..a9be2e812 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_no_package_json/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc index 76f667459..2445ccfb7 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc +++ b/crates/vite_task_plan/tests/plan_snapshots/fixtures/workspace_root_self_reference/snapshots/task_graph.jsonc @@ -28,7 +28,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -67,7 +67,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } @@ -106,7 +106,7 @@ "negative_globs": [] }, "output_config": { - "includes_auto": false, + "includes_auto": true, "positive_globs": [], "negative_globs": [] } diff --git a/docs/output-restoration-research.md b/docs/output-restoration-research.md new file mode 100644 index 000000000..4f6beda8c --- /dev/null +++ b/docs/output-restoration-research.md @@ -0,0 +1,117 @@ +# Output Restoration: Compatibility with Real Build Tools + +## Background + +Output restoration automatically archives files produced by a cached task and restores them on cache hit. +When a task runs and creates `dist/`, those files are saved as a `tar.zst` archive in the cache directory. +On subsequent cache hits the archive is extracted, skipping the need to re-execute the task. + +The feature works end-to-end when tested with simple write-only commands (`vtt write-file dist/out.txt built`), +but **fails with real build tools** (Vite 8, tsdown) in the default auto-detection mode. + +## The Problem + +Deleting the output directory (`dist/`) between runs causes a **cache miss** instead of triggering output restoration. + +``` +~/packages/vite-app$ vite build +... +✓ built in 34ms + +# delete dist, run again: + +~/packages/vite-app$ vite build ○ cache miss: 'assets' removed from 'packages/vite-app/dist', executing +``` + +The archived output files exist in the cache and could be restored, but the cache validation rejects the entry before restoration has a chance to run. + +## Root Cause + +Build tools **read from their output directory** during execution. fspy captures these reads and records them as inferred inputs. When the output directory is later deleted, the inferred input fingerprint no longer matches, producing a cache miss. + +### How the cache validation pipeline works + +1. **Cache entry lookup** — match by `CacheEntryKey` (spawn fingerprint + input config + output config) +2. **Globbed input validation** — compare stored file hashes against current state for explicit input globs +3. **Post-run fingerprint validation** — compare stored fspy-inferred input fingerprints against current filesystem state +4. **If all pass** → cache hit → replay terminal output → **extract output archive** + +The failure occurs at step 3. The stored fingerprint records `packages/app/dist` as `Folder(Some({assets: Dir, index.html: File}))`. After deletion the current fingerprint is `NotFound`. The mismatch is reported before output restoration at step 4 can execute. + +### Why build tools read from the output directory + +Both Vite 8 and tsdown follow the same pattern: **clean the output directory before writing new files**, then **report compressed sizes after writing**. + +#### Vite 8 (`vite build`) + +1. **Directory cleanup** (`emptyDir()`, called from `prepareOutDirPlugin` during `renderStart`) + - `fs.readdirSync(outDir)` enumerates entries so they can be deleted before the new build + - Controlled by `emptyOutDir` (default: `true`) + - This is the primary read that causes `packages/app/dist` to appear in fspy's `path_reads` + +2. **Compressed size reporting** (rolldown's builtin `viteReporterPlugin`, Rust-native) + - After writing output files, the reporter reads each file back to compute gzip/brotli sizes + - Produces the `dist/index.html 0.15 kB │ gzip: 0.14 kB` lines + - Controlled by `reportCompressedSize` (default: `true`) + - This causes reads on individual output files like `dist/index.html`, `dist/assets/index-xxx.js` + +3. **Public directory copy** (`copyDir()`) + - If `copyPublicDir` is enabled (default: `true`), reads the public dir to copy into outDir + +#### tsdown + +1. **Directory cleanup** (`cleanOutDir()` via `tinyglobby`'s `glob()`) + - Enumerates all files in the output directory with `onlyFiles: false` before deleting them + - Default `clean: true` triggers this + - This is the primary read that causes `packages/lib/dist` to appear in fspy's `path_reads` + +2. **Shebang permission check** (`ShebangPlugin`'s `writeBundle` hook) + - Calls `access()` on output files to check existence before setting execute permissions + - Only applies to entry chunks with shebang directives + +### Why the read-write overlap check doesn't catch this + +The overlap check at `execute_spawn` (mod.rs:486-488) looks for exact path matches between `path_reads` and `path_writes`: + +```rust +pa.path_reads.keys().find(|p| pa.path_writes.contains(*p)) +``` + +fspy reports these as separate paths: + +- **Read**: `packages/app/dist` (the directory itself, via `readdirSync`) +- **Write**: `packages/app/dist/index.html`, `packages/app/dist/assets/index-xxx.js` (individual files) + +Since `packages/app/dist` ≠ `packages/app/dist/index.html`, no overlap is detected, and caching proceeds. + +### Why `should_ignore_entry` doesn't help + +`fingerprint.rs:185-187` filters `dist` when listed as a directory entry of a **parent**: + +```rust +fn should_ignore_entry(name: &[u8]) -> bool { + matches!(name, b"." | b".." | b".DS_Store") || name.eq_ignore_ascii_case(b"dist") +} +``` + +This prevents the fingerprint of `packages/app/` from changing when `dist` appears or disappears inside it. But it does not help when `packages/app/dist` itself is a direct key in `inferred_inputs` — that path is fingerprinted independently, and its transition from `Folder(...)` to `NotFound` is a mismatch. + +### Why the existing e2e test passes + +The `output-cache-test` fixture uses `vtt write-file dist/out.txt built`, a simple write-only operation. `vtt write-file` never reads from `dist/`, so fspy only records it as a write. The directory never appears in `path_reads`, the post-run fingerprint doesn't include it, and cache validation succeeds after deletion. + +This does not reflect real build tool behavior. + +## Behavior Matrix + +All tests performed with Vite 8.0.8 and tsdown 0.12.9. "Cache hit after deleting dist" means output restoration can work. + +| `input` | `output` | fspy enabled | Cache hit after deleting dist | +| -------------- | --------------- | ------------ | ----------------------------- | +| auto (default) | auto (default) | yes | **no** | +| auto (default) | `["dist/**"]` | yes | **no** | +| `["src/**"]` | auto (default) | yes | **no** | +| `["src/**"]` | `["dist/**"]` | no | **yes** | +| `["src/**"]` | `[]` (disabled) | no | yes (but no restoration) | + +The only configuration that works requires **both** explicit input globs **and** explicit output globs, which disables fspy entirely. Any configuration that enables fspy (for either auto-input or auto-output detection) causes the output directory reads to pollute the inferred input set. diff --git a/docs/output-restoration.md b/docs/output-restoration.md new file mode 100644 index 000000000..5b004e75f --- /dev/null +++ b/docs/output-restoration.md @@ -0,0 +1,120 @@ +# Output Restoration + +When a cached task is replayed, vp doesn't just replay the terminal output — it also restores any files the task produced. So if your `build` task writes to `dist/`, a cache hit will put those files right back where they belong. + +## How It Works + +By default, vp watches which files a task writes during execution. On the next run, if the cache hits, those files are extracted back into the workspace automatically. You don't need to configure anything. + +```json +{ + "tasks": { + "build": { + "command": "tsc --outDir dist" + } + } +} +``` + +After `vp run build` runs once, the compiled files in `dist/` are archived. On subsequent runs that hit the cache, `dist/` is restored from that archive instead of recompiling. + +## The `output` Field + +The `output` field lets you control which files get archived and restored. It works exactly like `input` — same glob patterns, same `auto` directive, same negative patterns. + +### Default (omitted) + +Auto-detects written files. This is usually all you need: + +```json +{ + "tasks": { + "build": { + "command": "tsc --outDir dist" + } + } +} +``` + +### Explicit Globs + +If you only want specific files restored: + +```json +{ + "tasks": { + "build": { + "command": "tsc --outDir dist", + "output": ["dist/**"] + } + } +} +``` + +This ignores any other files the task might write (temp files, logs, etc.) and only archives what's under `dist/`. + +### Negative Patterns + +Exclude certain output files from being cached: + +```json +{ + "tasks": { + "build": { + "command": "webpack", + "output": [{ "auto": true }, "!dist/cache/**"] + } + } +} +``` + +Here, everything the task writes is archived _except_ files under `dist/cache/`. + +### Disable Output Restoration + +If you don't want any files restored on cache hit — only terminal output replayed — pass an empty array: + +```json +{ + "tasks": { + "test": { + "command": "vitest run", + "output": [] + } + } +} +``` + +## `output` and `input` Are Independent + +The `output` field has its own auto-detection, separate from `input`. You can disable auto-inference for inputs while keeping it for outputs: + +```json +{ + "tasks": { + "build": { + "command": "tsc --outDir dist", + "input": ["src/**/*.ts", "tsconfig.json"], + "output": [{ "auto": true }] + } + } +} +``` + +This tracks inputs via explicit globs only (no file-read inference), but still auto-detects which files the task writes for output restoration. + +## Configuration Summary + +| Configuration | Behavior | +| ------------------------------------- | ----------------------------------- | +| `output` omitted | Auto-detect written files (default) | +| `output: [{ "auto": true }]` | Same as omitted | +| `output: ["dist/**"]` | Only restore files under `dist/` | +| `output: [{ "auto": true }, "!tmp/"]` | Auto-detect, but skip `tmp/` | +| `output: []` | Don't restore any files | + +## Notes + +- Changing the `output` configuration invalidates the cache — if you switch from `["dist/**"]` to `["build/**"]`, the next run will be a cache miss. +- Output archives are stored alongside the cache database. Running `vp cache clean` removes them. +- The `output` field can't be used with `cache: false`, same as `input`.