@visulima/task-runner 1.0.0-alpha.17 → 1.0.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +2 -0
  3. package/dist/index.d.ts +308 -5
  4. package/dist/index.js +1 -1
  5. package/dist/packem_shared/Cache-BVrj9bd4.js +2 -0
  6. package/dist/packem_shared/CompositeLifeCycle-C6aee9GK.js +1 -0
  7. package/dist/packem_shared/FileAccessTracker-DBz_w4wl.js +50 -0
  8. package/dist/packem_shared/HttpRemoteCache-CpPl6lzE.js +1 -0
  9. package/dist/packem_shared/IncrementalFileHasher-B-V3i2x-.js +1 -0
  10. package/dist/packem_shared/LogReporter-3R3oWj-Q.js +13 -0
  11. package/dist/packem_shared/ReapiRemoteCache-BXJip5wH.js +251 -0
  12. package/dist/packem_shared/TaskOrchestrator-CYj5MLwz.js +6 -0
  13. package/dist/packem_shared/TrackedTaskExecutor-CtYLL3vS.js +1 -0
  14. package/dist/packem_shared/buildForwardDependencyMap-DudUDFze.js +3 -0
  15. package/dist/packem_shared/collectNodeModulesBinDirs-CD-eDrtO.js +1 -0
  16. package/dist/packem_shared/computeTaskHash-CaPdG1BA.js +1 -0
  17. package/dist/packem_shared/containsBlob-DAU8R7GH.js +1 -0
  18. package/dist/packem_shared/createTaskGraph-BBG8Rosl.js +1 -0
  19. package/dist/packem_shared/defaultTaskRunner-RJnuLoJz.js +2 -0
  20. package/dist/packem_shared/generateRunSummary-L9Z2NfWn.js +1 -0
  21. package/dist/packem_shared/{getMainWorktreeRoot-DRN_i8jA.js → getMainWorktreeRoot-DB9P2wDL.js} +1 -1
  22. package/dist/packem_shared/{isNativeAvailable-BOavFPX1.js → isNativeAvailable-CkTjxb7P.js} +1 -1
  23. package/dist/packem_shared/parsePartition-Bt1jBjZH.js +1 -0
  24. package/dist/packem_shared/{resolveCacheMode-DEDFC-kM.js → resolveCacheMode--4y60ODd.js} +1 -1
  25. package/dist/packem_shared/runConcurrentFallback-BhJCT2LA.js +3 -0
  26. package/dist/packem_shared/runConcurrently-D1Ytsjaj.js +1 -0
  27. package/dist/packem_shared/{runTeardown-CiJJeWVf.js → runTeardown-DAn1xFWJ.js} +1 -1
  28. package/dist/packem_shared/tracked-executor-B90U4Um3.js +3 -0
  29. package/index.js +54 -53
  30. package/package.json +11 -11
  31. package/dist/packem_shared/Cache-C540ZPYk.js +0 -2
  32. package/dist/packem_shared/CompositeLifeCycle-D0zWvAXJ.js +0 -1
  33. package/dist/packem_shared/FileAccessTracker-IG-Z0Ijw.js +0 -47
  34. package/dist/packem_shared/HttpRemoteCache-D3Z6b_FO.js +0 -1
  35. package/dist/packem_shared/IncrementalFileHasher-CdLXVB5F.js +0 -1
  36. package/dist/packem_shared/LogReporter-BUPWiXAq.js +0 -13
  37. package/dist/packem_shared/ReapiRemoteCache-B3uQuVqP.js +0 -251
  38. package/dist/packem_shared/TaskOrchestrator-F_NrcUYn.js +0 -2
  39. package/dist/packem_shared/TrackedTaskExecutor-BiK0Coso.js +0 -2
  40. package/dist/packem_shared/buildForwardDependencyMap-w1FVPFdv.js +0 -3
  41. package/dist/packem_shared/collectNodeModulesBinDirs-JaeFLP9l.js +0 -1
  42. package/dist/packem_shared/computeTaskHash-Xxd8v-X3.js +0 -1
  43. package/dist/packem_shared/containsBlob-DBWgvkM_.js +0 -1
  44. package/dist/packem_shared/createTaskGraph-D6nPDd4s.js +0 -1
  45. package/dist/packem_shared/defaultTaskRunner-CjaCnt_W.js +0 -2
  46. package/dist/packem_shared/generateRunSummary-beN13GH4.js +0 -1
  47. package/dist/packem_shared/parsePartition-uzPNgtPp.js +0 -1
  48. package/dist/packem_shared/runConcurrentFallback-SvS4ElEX.js +0 -3
  49. package/dist/packem_shared/runConcurrently-ebFf3uYs.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ ## @visulima/task-runner [1.0.0-alpha.19](https://github.com/visulima/visulima/compare/@visulima/task-runner@1.0.0-alpha.18...@visulima/task-runner@1.0.0-alpha.19) (2026-06-04)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **task-runner:** 3 bug fixes ([ccf08a1](https://github.com/visulima/visulima/commit/ccf08a1faed664d4545b7594bba9afade782b2e5))
6
+
7
+
8
+ ### Dependencies
9
+
10
+ * **@visulima/humanizer:** upgraded to 3.0.0-alpha.13
11
+ * **@visulima/path:** upgraded to 3.0.0-alpha.12
12
+
13
+ ## @visulima/task-runner [1.0.0-alpha.18](https://github.com/visulima/visulima/compare/@visulima/task-runner@1.0.0-alpha.17...@visulima/task-runner@1.0.0-alpha.18) (2026-06-02)
14
+
15
+ ### Features
16
+
17
+ * **task-runner,vis:** per-task pty + concurrency weight, abort cache gate, fspy scaffolds ([#656](https://github.com/visulima/visulima/issues/656)) ([ca64010](https://github.com/visulima/visulima/commit/ca64010b236903e08273680ea65dec7046fcd18b))
18
+
19
+ ### Bug Fixes
20
+
21
+ * **task-runner:** atomic restoreOutputs and graceful REAPI shutdown ([a3f7088](https://github.com/visulima/visulima/commit/a3f7088c58560f9c98d9d68914ebaf0a458e319d)), closes [#inflightRpcs](https://github.com/visulima/visulima/issues/inflightRpcs) [#closeQuiescenceTimeoutMs](https://github.com/visulima/visulima/issues/closeQuiescenceTimeoutMs)
22
+ * **task-runner:** bound fspy drains so a lingering child can't hang the run ([#666](https://github.com/visulima/visulima/issues/666)) ([3f56348](https://github.com/visulima/visulima/commit/3f56348e1998b50e3b8496ce5f97a9a34932946d)), closes [vite-task#396](https://github.com/visulima/vite-task/issues/396) [vite-task#396](https://github.com/visulima/vite-task/issues/396) [vite-task#396](https://github.com/visulima/vite-task/issues/396) [vite-task#396](https://github.com/visulima/vite-task/issues/396) [vite-task#396](https://github.com/visulima/vite-task/issues/396)
23
+ * **task-runner:** close remaining audit findings ([28c5870](https://github.com/visulima/visulima/commit/28c587008a7f4be73c0e4695f443eccf1a9ed264)), closes [vite-task#358](https://github.com/visulima/vite-task/issues/358)
24
+ * **task-runner:** harden native runner and respect caller FORCE_COLOR ([d1e7231](https://github.com/visulima/visulima/commit/d1e72317428501c1221ffb3c1a4a0e0c5bcfafc0))
25
+ * **task-runner:** harden scheduler, cache, and remote backends ([ce94b16](https://github.com/visulima/visulima/commit/ce94b16c7600967e2d47b1e18975a904f8aef779))
26
+ * **task-runner:** tolerate dev-only dependency cycles ([#664](https://github.com/visulima/visulima/issues/664)) ([9ad384e](https://github.com/visulima/visulima/commit/9ad384e34927b40823ae104d6b05a581dcd05705)), closes [#411](https://github.com/visulima/visulima/issues/411)
27
+
28
+ ### Miscellaneous Chores
29
+
30
+ * cs fixes ([#659](https://github.com/visulima/visulima/issues/659)) ([61f8912](https://github.com/visulima/visulima/commit/61f891274c1de22a36af256fc981b585b9ec6a6a))
31
+ * **task-runner:** track fspy_macos Cargo.lock ([7a69ff9](https://github.com/visulima/visulima/commit/7a69ff9bcbc25b2c6d8f249c66b135d1ff9a1577))
32
+
33
+ ### Tests
34
+
35
+ * **task-runner:** regression guard for vite-task[#411](https://github.com/visulima/visulima/issues/411) (peer-dep cycle) ([#665](https://github.com/visulima/visulima/issues/665)) ([41ed071](https://github.com/visulima/visulima/commit/41ed0710d103647137f0448d999f355451f80df4))
36
+
1
37
  ## @visulima/task-runner [1.0.0-alpha.17](https://github.com/visulima/visulima/compare/@visulima/task-runner@1.0.0-alpha.16...@visulima/task-runner@1.0.0-alpha.17) (2026-05-29)
2
38
 
3
39
  ### Bug Fixes
package/README.md CHANGED
@@ -34,6 +34,7 @@
34
34
  - **npm script-shell support**: Honors `npm config set script-shell` for custom shells (Git Bash, etc.)
35
35
  - **Long-running process support**: Configurable stdin mode (null/pipe/inherit), bounded output buffers
36
36
  - **Two caching modes**: Nx-style explicit inputs or Vite Task-style auto-fingerprinting
37
+ - **3-tier auto-fingerprint dispatch on Linux**: kernel-level `seccomp_unotify` (catches Alpine/musl/static-binary children), `strace` fallback, then no-op. The seccomp path uses a tiny `fspy-seccomp-helper` binary bundled with the platform binding package — sidesteps the fork-from-multithreaded hazard of installing seccomp in `pre_exec` from Node's NAPI host. See `rfc/design-fspy-seccomp-unotify.md`.
37
38
  - **Smart lockfile hashing**: Only hashes resolved versions relevant to each package (like Turborepo)
38
39
  - **Framework env inference**: Auto-detects Next.js, Vite, CRA, Gatsby, Nuxt, and more
39
40
  - **Remote caching**: Turborepo-compatible HTTP cache protocol, plus a Bazel REAPI gRPC backend (bazel-remote, BuildBuddy, BuildBarn, EngFlow)
@@ -49,6 +50,7 @@
49
50
  - **Output archiving**: Caches and restores build outputs (dist/ directories)
50
51
  - **LRU cache eviction**: Configurable max size and age limits
51
52
  - **Lifecycle hooks**: 7 hook points for custom behavior
53
+ - **Cooperative cache hints**: tools can refine the inferred fingerprint from the inside via the zero-dependency [`@visulima/task-runner-client`](../task-runner-client) — `ignoreInput`/`ignoreOutput` to drop noise, `disableCache` for non-deterministic runs, and `getEnv`/`getEnvs` to register env-var dependencies at the point of use (closing the silent under-tracking gap that pattern-only env config leaves open). Complements observation: works on every platform, no client = no change.
52
54
 
53
55
  ## Install
54
56
 
package/dist/index.d.ts CHANGED
@@ -39,15 +39,70 @@ declare class FileAccessTracker {
39
39
  */
40
40
  isSupported(): boolean;
41
41
  /**
42
+ * True when the macOS DYLD-interpose tracker is usable. Unlike
43
+ * {@link isSupported} (which gates the syscall-level Linux paths),
44
+ * interpose only covers *directly-exec'd* commands — the caller
45
+ * must additionally check {@link parseDirectExec} and fall back to
46
+ * the preload path for shell-syntax commands.
47
+ */
48
+ isInterposeSupported(): boolean;
49
+ /**
50
+ * Tracks a directly-exec'd `argv` via the macOS interpose dylib.
51
+ * `argv` MUST come from {@link parseDirectExec} (a single binary,
52
+ * no shell syntax) — it is exec'd directly, never through a shell,
53
+ * so `DYLD_INSERT_LIBRARIES` survives SIP. Degrades to the
54
+ * no-tracking path if the addon/dylib went missing since the
55
+ * availability check.
56
+ */
57
+ trackInterpose(argv: string[], options?: {
58
+ abortSignal?: AbortSignal;
59
+ cwd?: string;
60
+ env?: Record<string, string | undefined>;
61
+ }): Promise<TrackingResult>;
62
+ /**
63
+ * True when the Windows IAT-hook tracker is usable. Like
64
+ * {@link isInterposeSupported}, only covers *directly-exec'd*
65
+ * commands (the DLL is injected into the spawned binary, with no
66
+ * child-process propagation) — the caller must gate on
67
+ * {@link parseDirectExec} and fall back to the preload path for
68
+ * shell-syntax commands.
69
+ */
70
+ isIatHookSupported(): boolean;
71
+ /**
72
+ * Tracks a directly-exec'd `argv` via the Windows `fspy_windows`
73
+ * DLL (IAT hooks). `argv` MUST come from {@link parseDirectExec}.
74
+ * Degrades to the no-tracking path if the addon/DLL went missing
75
+ * since the availability check.
76
+ */
77
+ trackIatHook(argv: string[], options?: {
78
+ abortSignal?: AbortSignal;
79
+ cwd?: string;
80
+ env?: Record<string, string | undefined>;
81
+ }): Promise<TrackingResult>;
82
+ /**
42
83
  * Runs a command and tracks all file system accesses.
43
- * On unsupported platforms, runs the command without tracking.
84
+ *
85
+ * Dispatch order (highest fidelity first):
86
+ * 1. **seccomp_unotify** — kernel-level interception via the
87
+ * bundled helper binary. Catches static binaries and musl
88
+ * children that the strace + preload paths miss. Linux only.
89
+ * 2. **strace** — userspace fallback when seccomp isn't
90
+ * available (no native addon, no helper bin, kernel < 5.0).
91
+ * 3. **no-op** — on every other platform, run the command and
92
+ * return zero accesses so the orchestrator's empty-fingerprint
93
+ * diagnostic fires.
44
94
  */
45
95
  track(command: string, options?: {
96
+ /** When fired, SIGTERMs the active spawn for this call. */
97
+ abortSignal?: AbortSignal;
46
98
  cwd?: string;
47
99
  env?: Record<string, string | undefined>;
48
100
  }): Promise<TrackingResult>;
49
101
  /**
50
- * Kills all active child processes. Called on abort/signal to prevent orphans.
102
+ * Kills all active child processes. Called on abort/signal to
103
+ * prevent orphans. Works for both `ChildProcess` (strace path)
104
+ * and the seccomp helper PID stub via the shared `Killable`
105
+ * shape.
51
106
  */
52
107
  killAll(): void;
53
108
  }
@@ -631,6 +686,14 @@ interface Task {
631
686
  * {@link TaskRunnerOptions.concurrencyGroups}.
632
687
  */
633
688
  concurrencyGroup?: string;
689
+ /**
690
+ * Per-task slot weight against the global `parallel` cap. Defaults
691
+ * to `1` (one slot). Carried over from
692
+ * {@link TargetConfiguration.concurrencyWeight}; values `&lt;= 0`,
693
+ * non-finite, or non-integer are ignored (treated as `1` — matches
694
+ * `resolveWeight` in `task-scheduler.ts`).
695
+ */
696
+ concurrencyWeight?: number;
634
697
  /** Hash of the task inputs for caching */
635
698
  hash?: string;
636
699
  /** Detailed hash information */
@@ -670,6 +733,15 @@ interface Task {
670
733
  priority?: TaskPriority;
671
734
  /** The project root directory */
672
735
  projectRoot?: string;
736
+ /**
737
+ * Per-task PTY override. When `true`, this task spawns inside a
738
+ * pseudo-terminal even if the workspace-level toggle is off (or
739
+ * vice versa when `false`). Carried over from
740
+ * {@link TargetConfiguration.pty}. Consumed by the runner that
741
+ * actually spawns the command — the task-runner library exposes
742
+ * the flag and leaves the spawn decision to the executor.
743
+ */
744
+ pty?: boolean;
673
745
  /** The target this task executes */
674
746
  target: TaskTarget;
675
747
  /**
@@ -722,6 +794,33 @@ type TaskStatus = "success" | "failure" | "skipped" | "local-cache" | "local-cac
722
794
  * Result of executing a task.
723
795
  */
724
796
  interface TaskResult {
797
+ /**
798
+ * Set when the task asked the runner not to cache this run by calling
799
+ * `disableCache()` from `@visulima/task-runner-client`. Unlike
800
+ * {@link TaskResult.emptyFingerprint}, the fingerprint may be perfectly
801
+ * valid — the task itself declared the run non-deterministic (network
802
+ * flake, debug mode, aborted watch). Surfaced to reporters and the run
803
+ * summary so the skip is explained rather than silent.
804
+ */
805
+ cacheDisabledByTask?: boolean;
806
+ /**
807
+ * Provenance of the cooperative cache hints a task emitted via
808
+ * `@visulima/task-runner-client` during this run. Present only when
809
+ * the task registered at least one hint, so the common (no-client)
810
+ * path leaves it `undefined`. Surfaced in `--summarize` output so a
811
+ * cache key can be explained: which reads/writes were ignored and
812
+ * which env vars/patterns were registered as dependencies.
813
+ */
814
+ cacheHints?: {
815
+ /** Absolute paths whose reads were dropped from inferred inputs. */
816
+ ignoredInputs: string[];
817
+ /** Absolute paths whose writes were dropped from inferred outputs. */
818
+ ignoredOutputs: string[];
819
+ /** Env var names registered as cache dependencies via `getEnv`. */
820
+ trackedEnv: string[];
821
+ /** Env glob patterns registered as cache dependencies via `getEnvs`. */
822
+ trackedEnvPatterns: string[];
823
+ };
725
824
  /** The exit code, if applicable */
726
825
  code?: number;
727
826
  /**
@@ -866,6 +965,20 @@ interface TargetConfiguration {
866
965
  * finalisation phase outside the scheduler.
867
966
  */
868
967
  concurrencyGroup?: string;
968
+ /**
969
+ * Per-task slot weight against the global `parallel` cap. Defaults
970
+ * to `1`. A task with `concurrencyWeight: 2` consumes two slots; with
971
+ * `parallel: 4` only two such tasks can run concurrently (or one
972
+ * weight-2 plus two weight-1). Use for CPU-pinning tasks — bundlers,
973
+ * `tsc`, native compiles — where the runner shouldn't keep
974
+ * over-subscribing the box just because slots are nominally free.
975
+ *
976
+ * The scheduler always lets a single task run even if its weight
977
+ * exceeds the remaining budget; otherwise a heavy task on a
978
+ * `parallel: 1` pool would deadlock. Values `&lt;= 0`, non-finite, or
979
+ * non-integer are ignored (treated as `1`).
980
+ */
981
+ concurrencyWeight?: number;
869
982
  /** Named configurations (e.g., "production", "development") */
870
983
  configurations?: Record<string, Record<string, unknown>>;
871
984
  /** Other targets this target depends on */
@@ -935,6 +1048,19 @@ interface TargetConfiguration {
935
1048
  /** Whether this target supports parallel execution */
936
1049
  parallelism?: boolean;
937
1050
  /**
1051
+ * Per-target PTY override. When `true`, every task spawned from
1052
+ * this target runs inside a pseudo-terminal (so `isatty()` returns
1053
+ * true and the child preserves color / progress UI). When `false`,
1054
+ * the workspace-level PTY toggle is suppressed for this target.
1055
+ * Useful when most targets are happy with piped stdio but one
1056
+ * tool (vitest, prettier, a colorising linter) needs a real TTY,
1057
+ * or vice versa.
1058
+ *
1059
+ * Absent means "follow the workspace default" — the executor
1060
+ * decides based on its own toggles.
1061
+ */
1062
+ pty?: boolean;
1063
+ /**
938
1064
  * Regex source string(s) that mark a successful task as having
939
1065
  * emitted warnings. The orchestrator scans the task's combined
940
1066
  * terminal output after a 0-exit and, on first match, sets
@@ -1188,6 +1314,18 @@ interface TaskRunnerOptions {
1188
1314
  */
1189
1315
  autoFingerprint?: boolean;
1190
1316
  /**
1317
+ * Failure-propagation policy.
1318
+ *
1319
+ * - `false` (default) — when a task fails, its transitive
1320
+ * dependents are marked `skipped`. Tasks not downstream of the
1321
+ * failure still run. Prevents cascade failures from running a
1322
+ * dependent on a missing `dist/` produced by the failed dep.
1323
+ * - `true` — fail-fast. On the first failure every not-yet-started
1324
+ * task is marked `skipped`; in-flight tasks finish naturally.
1325
+ * @default false
1326
+ */
1327
+ bail?: boolean;
1328
+ /**
1191
1329
  * Whether to show cache miss diagnostics (why a cache miss occurred).
1192
1330
  * @default false
1193
1331
  */
@@ -1588,6 +1726,13 @@ interface LifeCycleInterface {
1588
1726
  * semantics — same contract, different stream.
1589
1727
  */
1590
1728
  onTaskStdout?: (task: Task, chunk: string) => void;
1729
+ /**
1730
+ * Called when caching is skipped because the task itself requested it
1731
+ * via `disableCache()` (`@visulima/task-runner-client`). Distinct from
1732
+ * {@link LifeCycleInterface.printEmptyFingerprintWarning}: the
1733
+ * fingerprint may be valid; the task declared the run non-cacheable.
1734
+ */
1735
+ printCacheDisabledByTask?: (task: Task) => void;
1591
1736
  /** Called when a cache miss occurs with diagnostic information */
1592
1737
  printCacheMiss?: (task: Task, reasons: string) => void;
1593
1738
  /**
@@ -2045,6 +2190,14 @@ declare class Cache {
2045
2190
  /**
2046
2191
  * Removes old cache entries that exceed the maximum age,
2047
2192
  * and enforces the maximum cache size by evicting oldest entries.
2193
+ *
2194
+ * NOTE: `maxCacheSize` only bounds the *legacy* `<hash>/` entry
2195
+ * layout. The v2 CAS subtree (rooted at {@link V2_ROOT}) is skipped
2196
+ * here — it manages its own lifetime via blob-level touch + reference
2197
+ * accounting (see `cas/store.ts`) and is deliberately excluded from
2198
+ * both age and size accounting below. Consequently a cache dominated
2199
+ * by v2 blobs reports a small measured size and may exceed
2200
+ * `maxCacheSize`; size-based eviction is not driven from the CAS GC.
2048
2201
  */
2049
2202
  removeOldEntries(): Promise<void>;
2050
2203
  /**
@@ -2143,6 +2296,20 @@ declare const touchBlob: (root: string, digest: CasDigest) => Promise<void>;
2143
2296
  interface TaskSummary {
2144
2297
  /** Whether the task was cacheable */
2145
2298
  cacheable: boolean;
2299
+ /**
2300
+ * Provenance of cooperative cache hints the task emitted via
2301
+ * `@visulima/task-runner-client` ({@link TaskResult.cacheHints}).
2302
+ * Omitted when the task used no client hints.
2303
+ */
2304
+ cacheHints?: TaskResult["cacheHints"];
2305
+ /**
2306
+ * Why a cacheable task that ran (exit 0) seeded no cache entry.
2307
+ * Omitted for cache hits, failures, and ordinary cache writes.
2308
+ * `disabled-by-task` — the task called `disableCache()`;
2309
+ * `self-modified` — it rewrote one of its own tracked inputs;
2310
+ * `empty-fingerprint` — tracking observed no workspace accesses.
2311
+ */
2312
+ cacheSkipReason?: "disabled-by-task" | "empty-fingerprint" | "self-modified";
2146
2313
  /** Cache status */
2147
2314
  cacheStatus: "HIT" | "MISS" | "REMOTE_HIT" | "SKIPPED";
2148
2315
  /** Dependencies on other tasks */
@@ -2760,6 +2927,9 @@ declare class CompositeLifeCycle implements LifeCycleInterface {
2760
2927
  endTasks(taskResults: TaskResult[]): void;
2761
2928
  printTaskTerminalOutput(task: Task, status: TaskStatus, terminalOutput: string): void;
2762
2929
  printCacheMiss(task: Task, reasons: string): void;
2930
+ printCacheDisabledByTask(task: Task): void;
2931
+ printEmptyFingerprintWarning(task: Task, reason: string): void;
2932
+ printSelfModifyingSkip(task: Task, modifiedFiles: string[]): void;
2763
2933
  onTaskStdout(task: Task, chunk: string): void;
2764
2934
  onTaskStderr(task: Task, chunk: string): void;
2765
2935
  }
@@ -2866,6 +3036,23 @@ declare class LockfileHasher {
2866
3036
  */
2867
3037
  type LogMode = "grouped" | "interleaved" | "labeled";
2868
3038
  /**
3039
+ * How the reporter handles ANSI escape sequences in the buffered output
3040
+ * it receives.
3041
+ *
3042
+ * - `auto` **(default)**: detect color capability of the write target;
3043
+ * strip escapes when stdout isn't a TTY, `NO_COLOR` is set, or
3044
+ * `TERM=dumb`. Matches what colorize libraries do for live output.
3045
+ * - `always`: keep escapes — useful when piping into another tool that
3046
+ * understands ANSI.
3047
+ * - `never`: always strip — useful for log files / JSON-collecting CI.
3048
+ *
3049
+ * Live spawn output is captured with `FORCE_COLOR=1` so cache entries
3050
+ * always contain colored bytes; without this control, replaying a cache
3051
+ * hit into a non-color destination prints raw escape sequences. See
3052
+ * voidzero-dev/vite-task#358 / #378.
3053
+ */
3054
+ type ColorMode = "always" | "auto" | "never";
3055
+ /**
2869
3056
  * A lifecycle handler that renders task terminal output per {@link LogMode}.
2870
3057
  *
2871
3058
  * Operates on the buffered `printTaskTerminalOutput` signal the orchestrator
@@ -2875,7 +3062,7 @@ type LogMode = "grouped" | "interleaved" | "labeled";
2875
3062
  */
2876
3063
  declare class LogReporter implements LifeCycleInterface {
2877
3064
  #private;
2878
- constructor(mode: LogMode, write?: (chunk: string) => void);
3065
+ constructor(mode: LogMode, write?: (chunk: string) => void, color?: ColorMode);
2879
3066
  printTaskTerminalOutput(task: Task, _status: TaskStatus, terminalOutput: string): void;
2880
3067
  endTasks(_taskResults: TaskResult[]): void;
2881
3068
  }
@@ -2884,7 +3071,7 @@ declare class LogReporter implements LifeCycleInterface {
2884
3071
  * Consumers that already compose their own lifecycle handlers can instantiate
2885
3072
  * {@link LogReporter} directly.
2886
3073
  */
2887
- declare const createLogReporter: (mode: LogMode, write?: (chunk: string) => void) => LogReporter;
3074
+ declare const createLogReporter: (mode: LogMode, write?: (chunk: string) => void, color?: ColorMode) => LogReporter;
2888
3075
  interface NativeFileHash {
2889
3076
  hash: string;
2890
3077
  path: string;
@@ -2963,6 +3150,51 @@ interface NativeBindings {
2963
3150
  runConcurrent: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions, onEvent: (event: NativeProcessEvent) => void) => Promise<NativeConcurrentRunResult>;
2964
3151
  runConcurrentBatch: (commands: NativeConcurrentCommandConfig[], options: NativeConcurrentRunnerOptions, onLifecycle?: ((event: NativeProcessEvent) => void) | null) => Promise<NativeConcurrentRunResult>;
2965
3152
  topologicalSort: (graph: NativeTaskGraph) => string[];
3153
+ /**
3154
+ * Windows-only: spawn the directly-exec'd `argv` suspended, inject
3155
+ * the `fspy_windows` DLL (at `dllPath`) via
3156
+ * `CreateRemoteThread(LoadLibraryW)`, and collect the IAT-hooked
3157
+ * accesses streamed over a named pipe. Same result shape as
3158
+ * `trackWithSeccomp`. Present only when the addon was built for a
3159
+ * Windows target.
3160
+ */
3161
+ trackWithIatHook?: (argv: string[], dllPath: string, options?: NativeSeccompSpawnOptions, onStarted?: (pid: number) => void) => Promise<NativeSeccompTrackingResult>;
3162
+ /**
3163
+ * macOS-only: spawn the directly-exec'd `argv` with the
3164
+ * `fspy_macos` interpose dylib (at `dylibPath`) injected via
3165
+ * `DYLD_INSERT_LIBRARIES` and collect reported accesses. Same
3166
+ * result shape as `trackWithSeccomp`. Present only when the
3167
+ * addon was built for a macOS target.
3168
+ */
3169
+ trackWithInterpose?: (argv: string[], dylibPath: string, options?: NativeSeccompSpawnOptions, onStarted?: (pid: number) => void) => Promise<NativeSeccompTrackingResult>;
3170
+ /**
3171
+ * Linux-only: spawn `argv` under seccomp_unotify tracking via
3172
+ * the helper binary at `helperPath`. Resolves once the child
3173
+ * exits with the gathered file accesses.
3174
+ *
3175
+ * `onStarted` (when supplied) fires once with the helper PID
3176
+ * as soon as the spawn succeeds. The PID survives the
3177
+ * helper→target execve, so callers can SIGTERM it via
3178
+ * `process.kill(pid)` to abort the traced command.
3179
+ *
3180
+ * Undefined when the addon was built on a non-Linux target.
3181
+ */
3182
+ trackWithSeccomp?: (argv: string[], helperPath: string, options?: NativeSeccompSpawnOptions, onStarted?: (pid: number) => void) => Promise<NativeSeccompTrackingResult>;
3183
+ }
3184
+ interface NativeSeccompSpawnOptions {
3185
+ cwd?: string;
3186
+ /** Extra env vars merged on top of the parent's. */
3187
+ env?: Record<string, string>;
3188
+ }
3189
+ interface NativeSeccompFileAccess {
3190
+ kind: "missing" | "read" | "readdir" | "stat" | "write";
3191
+ path: string;
3192
+ }
3193
+ interface NativeSeccompTrackingResult {
3194
+ accesses: NativeSeccompFileAccess[];
3195
+ exitCode: number;
3196
+ stderr: Buffer;
3197
+ stdout: Buffer;
2966
3198
  }
2967
3199
  /**
2968
3200
  * Attempts to load the native addon. Returns undefined if unavailable.
@@ -3044,7 +3276,7 @@ declare const parseInputUri: (input: string) => InputDefinition | undefined;
3044
3276
  declare const looksLikeInputUri: (input: string) => boolean;
3045
3277
  /**
3046
3278
  * Walks from `cwd` (resolved against `process.cwd()` when relative)
3047
- * up to the filesystem root, returning every `<dir>/node_modules/.bin`
3279
+ * up to the filesystem root, returning every `&lt;dir>/node_modules/.bin`
3048
3280
  * path encountered. Ordered nearest-first so the cwd-local `.bin`
3049
3281
  * shadows ancestor `.bin` directories, matching npm/pnpm semantics.
3050
3282
  *
@@ -3080,6 +3312,15 @@ declare const withEnhancedPath: <T extends NodeJS.ProcessEnv | Record<string, st
3080
3312
  */
3081
3313
  declare const enforceProjectConstraints: (projectGraph: ProjectGraph, constraints: ConstraintsConfig) => ConstraintViolation[];
3082
3314
  interface CreateTaskGraphOptions {
3315
+ /**
3316
+ * Invoked once per dependency cycle that {@link createTaskGraph}
3317
+ * breaks because it runs *solely* through soft (devDependency)
3318
+ * edges. The argument is the cycle as a closed path of task ids
3319
+ * (`[a, b, …, a]`). Consumers can surface this as a warning; cycles
3320
+ * that contain a hard (static) edge are left intact and never
3321
+ * reported here.
3322
+ */
3323
+ onCycleBroken?: (cycle: string[]) => void;
3083
3324
  /** The project graph */
3084
3325
  projectGraph: ProjectGraph;
3085
3326
  /** Target default configurations */
@@ -3275,6 +3516,12 @@ declare class TaskScheduler {
3275
3516
  constructor(taskGraph: TaskGraph, projectGraph: ProjectGraph, maxParallel?: number, concurrencyGroups?: ConcurrencyGroups);
3276
3517
  /**
3277
3518
  * Returns the next batch of tasks that are ready to execute.
3519
+ *
3520
+ * Slot accounting is weighted: a task's `concurrencyWeight` (default
3521
+ * `1`) counts against the global `parallel` cap. A heavier task may
3522
+ * still run alone — when nothing is in flight, the scheduler always
3523
+ * admits at least one ready task even if its weight exceeds the cap,
3524
+ * so a `parallel: 1` pool can't deadlock on a weight-3 task.
3278
3525
  */
3279
3526
  getNextBatch(): Task[];
3280
3527
  startTask(taskId: string): void;
@@ -3282,6 +3529,26 @@ declare class TaskScheduler {
3282
3529
  isComplete(): boolean;
3283
3530
  get remainingCount(): number;
3284
3531
  get runningCount(): number;
3532
+ /**
3533
+ * Returns dep-id refs the task graph carries that don't resolve to
3534
+ * any task in `tasks`, keyed by the task that declared them. The
3535
+ * scheduler treats these as already-completed so the run can
3536
+ * proceed, but the orchestrator surfaces this map as a warning at
3537
+ * run start so the underlying input bug (vis / config emitting
3538
+ * dangling refs) doesn't go silently masked.
3539
+ */
3540
+ getOrphanDependencies(): Map<string, string[]>;
3541
+ /**
3542
+ * Returns task ids that are not in `completedTasks` and not in
3543
+ * `runningTasks`, along with their unmet deps after orphan refs
3544
+ * have been filtered out. The orchestrator's deadlock error reads
3545
+ * this so the message can name the actual stranded tasks instead
3546
+ * of a generic "may indicate a circular dependency" hint.
3547
+ */
3548
+ describeStrandedTasks(): {
3549
+ id: string;
3550
+ unmetDeps: string[];
3551
+ }[];
3285
3552
  }
3286
3553
  /**
3287
3554
  * Options for the TaskOrchestrator.
@@ -3296,6 +3563,19 @@ interface TaskOrchestratorOptions {
3296
3563
  */
3297
3564
  alwaysTasks?: Task[];
3298
3565
  autoFingerprint?: boolean;
3566
+ /**
3567
+ * Failure-propagation policy.
3568
+ *
3569
+ * - `false` (default) — when a task fails, its transitive
3570
+ * dependents are marked `skipped` with a "dependency failed"
3571
+ * note. Tasks not downstream of the failure still run. Prevents
3572
+ * the cascade failures that result from running a dependent on
3573
+ * a missing `dist/` produced by the failed dep.
3574
+ * - `true` — fail-fast. On the first failure every task that
3575
+ * hasn't started is marked `skipped`; in-flight tasks are
3576
+ * allowed to finish.
3577
+ */
3578
+ bail?: boolean;
3299
3579
  cache: Cache;
3300
3580
  cacheDiagnostics?: boolean;
3301
3581
  captureOutput?: boolean;
@@ -3372,6 +3652,23 @@ declare class TerminalBuffer {
3372
3652
  toString(): string;
3373
3653
  }
3374
3654
  /**
3655
+ * Hints aggregated from a task's NDJSON file, with paths resolved to
3656
+ * absolute form against the child's cwd. Consumed by the orchestrator
3657
+ * to refine the auto-fingerprint before it's sealed.
3658
+ */
3659
+ interface CollectedHints {
3660
+ /** The task asked not to cache this run (via `disableCache()`). */
3661
+ cacheDisabled: boolean;
3662
+ /** Absolute paths whose reads should be dropped from inferred inputs. */
3663
+ ignoredInputs: string[];
3664
+ /** Absolute paths whose writes should be dropped from inferred outputs. */
3665
+ ignoredOutputs: string[];
3666
+ /** Env var names registered as cache dependencies via `getEnv`. */
3667
+ trackedEnv: string[];
3668
+ /** Env glob patterns registered as cache dependencies via `getEnvs`. */
3669
+ trackedEnvPatterns: string[];
3670
+ }
3671
+ /**
3375
3672
  * Result of a tracked task execution.
3376
3673
  */
3377
3674
  interface TrackedExecutionResult {
@@ -3379,6 +3676,12 @@ interface TrackedExecutionResult {
3379
3676
  accesses: FileAccess[];
3380
3677
  /** The command exit code */
3381
3678
  code: number;
3679
+ /**
3680
+ * Cooperative cache hints the task emitted via
3681
+ * `@visulima/task-runner-client` ({@link CollectedHints}). Empty when
3682
+ * the task didn't use the client.
3683
+ */
3684
+ hints: CollectedHints;
3382
3685
  /** The command stdout + stderr output */
3383
3686
  terminalOutput: string;
3384
3687
  }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{buildForwardDependencyMap as o,buildReverseDependencyMap as t,expandAffected as a,filterAffectedTasks as s,getAffectedProjects as p,getChangedFiles as n}from"./packem_shared/buildForwardDependencyMap-w1FVPFdv.js";import{createRemoteCacheBackend as i,resolveCacheMode as c,resolveTurboEnvCompat as f}from"./packem_shared/resolveCacheMode-DEDFC-kM.js";import{actionDigestForTaskHash as x,containsByTaskHash as h,retrieveByTaskHash as d,storeByTaskHash as u}from"./packem_shared/actionDigestForTaskHash-BOL4fZ9v.js";import{HttpRemoteCache as T}from"./packem_shared/HttpRemoteCache-D3Z6b_FO.js";import{ReapiRemoteCache as g}from"./packem_shared/ReapiRemoteCache-B3uQuVqP.js";import{Cache as R,DEFAULT_CACHE_DIRECTORY_NAME as v,formatCacheSize as F,parseCacheSize as B}from"./packem_shared/Cache-C540ZPYk.js";import{digestBuffer as E,digestFile as P}from"./packem_shared/digestBuffer-g11aCaDx.js";import{V2_AC as I,V2_CAS as L,V2_INDEX as H,V2_ROOT as A,V2_TMP as w,acEntryPath as D,casBlobPath as _,taskHashIndexPath as M}from"./packem_shared/V2_ROOT-injxWBrl.js";import{containsBlob as N,fetchBlobToFile as O,putBlobFromBytes as U,putBlobFromFile as V,touchBlob as W,verifyBlob as j}from"./packem_shared/containsBlob-DBWgvkM_.js";import{toChromeTrace as Y,writeChromeTrace as q}from"./packem_shared/toChromeTrace-DxN5NQIU.js";import{parseCommands as K}from"./packem_shared/parseCommands-BHsXoUCd.js";import{runConcurrently as X}from"./packem_shared/runConcurrently-ebFf3uYs.js";import{runConcurrentFallback as $}from"./packem_shared/runConcurrentFallback-SvS4ElEX.js";import{defaultTaskRunner as re}from"./packem_shared/defaultTaskRunner-CjaCnt_W.js";import{detectScriptShell as te}from"./packem_shared/detectScriptShell-CaTDk5cW.js";import{FileAccessTracker as se,generatePreloadScript as pe}from"./packem_shared/FileAccessTracker-IG-Z0Ijw.js";import{FingerprintManager as me}from"./packem_shared/FingerprintManager-CYW2EwLc.js";import{detectFrameworks as ce,getFrameworkEnvVariables as fe,inferFrameworkEnvPatterns as le}from"./packem_shared/detectFrameworks-WVZJOPgN.js";import{projectGraphToDot as he,toGraphAscii as de,toGraphHtml as ue,toGraphJson as ke,toGraphvizDot as Te}from"./packem_shared/projectGraphToDot-FN6oHDGH.js";import{IncrementalFileHasher as ge}from"./packem_shared/IncrementalFileHasher-CdLXVB5F.js";import{CompositeLifeCycle as Re,ConsoleLifeCycle as ve,EmptyLifeCycle as Fe}from"./packem_shared/CompositeLifeCycle-D0zWvAXJ.js";import{LockfileHasher as be,extractPackageName as Ee,parseNpmLockfile as Pe,parsePnpmLockfile as Se,parseYarnLockfile as Ie}from"./packem_shared/extractPackageName-BeL6Gc3a.js";import{LogReporter as He,createLogReporter as Ae}from"./packem_shared/LogReporter-BUPWiXAq.js";import{isNativeAvailable as De,loadNativeBindings as _e}from"./packem_shared/isNativeAvailable-BOavFPX1.js";import{resolveOutputs as Ge}from"./packem_shared/resolveOutputs-BBjdaraf.js";import{INPUT_URI_SCHEMES as Oe,InvalidInputUriError as Ue,looksLikeInputUri as Ve,parseInputUri as We}from"./packem_shared/INPUT_URI_SCHEMES-Csrd0tlg.js";import{buildEnhancedPath as ze,collectNodeModulesBinDirs as Ye,withEnhancedPath as qe}from"./packem_shared/collectNodeModulesBinDirs-JaeFLP9l.js";import{enforceProjectConstraints as Ke}from"./packem_shared/enforceProjectConstraints-dNc1SwRi.js";import{generateRunSummary as Xe,getLastRunSummaryPath as Ze,readLastRunSummary as $e,writeLastRunSummary as er,writeRunSummary as rr}from"./packem_shared/generateRunSummary-beN13GH4.js";import{createTaskGraph as tr,getTaskId as ar,parseTaskId as sr}from"./packem_shared/createTaskGraph-D6nPDd4s.js";import{findCycle as nr,findCycles as mr,getDependentTasks as ir,getLeafTasks as cr,getTransitiveDependencies as fr,makeAcyclic as lr,reverseTaskGraph as xr,walkTaskGraph as hr}from"./packem_shared/findCycle-BY8-jmzB.js";import{InProcessTaskHasher as ur,computeTaskHash as kr}from"./packem_shared/computeTaskHash-Xxd8v-X3.js";import{TaskOrchestrator as Cr}from"./packem_shared/TaskOrchestrator-F_NrcUYn.js";import{TaskScheduler as yr,parsePartition as Rr}from"./packem_shared/parsePartition-uzPNgtPp.js";import{TerminalBuffer as Fr}from"./packem_shared/TerminalBuffer-BtZy7TpT.js";import{TrackedTaskExecutor as br}from"./packem_shared/TrackedTaskExecutor-BiK0Coso.js";import{d as Pr,j as Sr,T as Ir,b as Lr,E as Hr,v as Ar,h as wr,O as Dr}from"./packem_shared/utils-BH2W5Wml.js";import{evaluateWhen as Mr,explainWhen as Gr,getCurrentBranch as Nr,resetBranchCache as Or}from"./packem_shared/getCurrentBranch-D-qoZByx.js";import{getMainWorktreeRoot as Vr,isLinkedWorktree as Wr,resetWorktreeCache as jr}from"./packem_shared/getMainWorktreeRoot-DRN_i8jA.js";import{createInputHandler as Yr}from"./packem_shared/createInputHandler-CkDCpPYy.js";import{expandArguments as Jr}from"./packem_shared/expandArguments-D7qvc6Rp.js";import{expandShortcut as Qr}from"./packem_shared/expandShortcut-BErNHNXZ.js";import{expandTokens as Zr,expandTokensInString as $r}from"./packem_shared/expandTokensInString-DVSFEdWu.js";import{expandWildcard as ro}from"./packem_shared/expandWildcard-DE0dOOZF.js";import{formatTimingTable as to,logTimings as ao}from"./packem_shared/formatTimingTable-CP3rsDwf.js";import{runTeardown as po}from"./packem_shared/runTeardown-CiJJeWVf.js";import{stripQuotes as mo}from"./packem_shared/stripQuotes-jkZb0CL9.js";import{withRestart as co}from"./packem_shared/withRestart-DKtEGsQA.js";export{R as Cache,Re as CompositeLifeCycle,ve as ConsoleLifeCycle,v as DEFAULT_CACHE_DIRECTORY_NAME,Fe as EmptyLifeCycle,se as FileAccessTracker,me as FingerprintManager,T as HttpRemoteCache,Oe as INPUT_URI_SCHEMES,ur as InProcessTaskHasher,ge as IncrementalFileHasher,Ue as InvalidInputUriError,be as LockfileHasher,He as LogReporter,g as ReapiRemoteCache,Cr as TaskOrchestrator,yr as TaskScheduler,Fr as TerminalBuffer,br as TrackedTaskExecutor,I as V2_AC,L as V2_CAS,H as V2_INDEX,A as V2_ROOT,w as V2_TMP,D as acEntryPath,x as actionDigestForTaskHash,ze as buildEnhancedPath,o as buildForwardDependencyMap,t as buildReverseDependencyMap,_ as casBlobPath,Pr as collectFiles,Ye as collectNodeModulesBinDirs,kr as computeTaskHash,N as containsBlob,h as containsByTaskHash,Sr as createFailureResult,Yr as createInputHandler,Ae as createLogReporter,i as createRemoteCacheBackend,tr as createTaskGraph,re as defaultTaskRunner,ce as detectFrameworks,te as detectScriptShell,E as digestBuffer,P as digestFile,Ke as enforceProjectConstraints,Mr as evaluateWhen,a as expandAffected,Jr as expandArguments,Qr as expandShortcut,Zr as expandTokens,$r as expandTokensInString,ro as expandWildcard,Gr as explainWhen,Ee as extractPackageName,O as fetchBlobToFile,s as filterAffectedTasks,nr as findCycle,mr as findCycles,F as formatCacheSize,to as formatTimingTable,pe as generatePreloadScript,Xe as generateRunSummary,p as getAffectedProjects,n as getChangedFiles,Nr as getCurrentBranch,ir as getDependentTasks,fe as getFrameworkEnvVariables,Ze as getLastRunSummaryPath,cr as getLeafTasks,Vr as getMainWorktreeRoot,ar as getTaskId,fr as getTransitiveDependencies,Ir as hashFile,Lr as hashStrings,le as inferFrameworkEnvPatterns,Wr as isLinkedWorktree,De as isNativeAvailable,_e as loadNativeBindings,ao as logTimings,Ve as looksLikeInputUri,lr as makeAcyclic,B as parseCacheSize,K as parseCommands,We as parseInputUri,Pe as parseNpmLockfile,Rr as parsePartition,Se as parsePnpmLockfile,sr as parseTaskId,Ie as parseYarnLockfile,he as projectGraphToDot,U as putBlobFromBytes,V as putBlobFromFile,$e as readLastRunSummary,Hr as readPackageDeps,Or as resetBranchCache,jr as resetWorktreeCache,c as resolveCacheMode,Ge as resolveOutputs,Ar as resolveTaskCwd,f as resolveTurboEnvCompat,d as retrieveByTaskHash,xr as reverseTaskGraph,$ as runConcurrentFallback,X as runConcurrently,po as runTeardown,wr as sortObjectKeys,u as storeByTaskHash,mo as stripQuotes,M as taskHashIndexPath,Y as toChromeTrace,de as toGraphAscii,ue as toGraphHtml,ke as toGraphJson,Te as toGraphvizDot,W as touchBlob,Dr as uniqueId,j as verifyBlob,hr as walkTaskGraph,qe as withEnhancedPath,co as withRestart,q as writeChromeTrace,er as writeLastRunSummary,rr as writeRunSummary};
1
+ import{buildForwardDependencyMap as o,buildReverseDependencyMap as t,expandAffected as a,filterAffectedTasks as s,getAffectedProjects as p,getChangedFiles as n}from"./packem_shared/buildForwardDependencyMap-DudUDFze.js";import{createRemoteCacheBackend as i,resolveCacheMode as c,resolveTurboEnvCompat as f}from"./packem_shared/resolveCacheMode--4y60ODd.js";import{actionDigestForTaskHash as x,containsByTaskHash as h,retrieveByTaskHash as d,storeByTaskHash as u}from"./packem_shared/actionDigestForTaskHash-BOL4fZ9v.js";import{HttpRemoteCache as T}from"./packem_shared/HttpRemoteCache-CpPl6lzE.js";import{ReapiRemoteCache as g}from"./packem_shared/ReapiRemoteCache-BXJip5wH.js";import{Cache as R,DEFAULT_CACHE_DIRECTORY_NAME as v,formatCacheSize as F,parseCacheSize as B}from"./packem_shared/Cache-BVrj9bd4.js";import{digestBuffer as E,digestFile as P}from"./packem_shared/digestBuffer-g11aCaDx.js";import{V2_AC as I,V2_CAS as L,V2_INDEX as H,V2_ROOT as A,V2_TMP as w,acEntryPath as D,casBlobPath as _,taskHashIndexPath as M}from"./packem_shared/V2_ROOT-injxWBrl.js";import{containsBlob as N,fetchBlobToFile as O,putBlobFromBytes as U,putBlobFromFile as V,touchBlob as W,verifyBlob as j}from"./packem_shared/containsBlob-DAU8R7GH.js";import{toChromeTrace as Y,writeChromeTrace as q}from"./packem_shared/toChromeTrace-DxN5NQIU.js";import{parseCommands as K}from"./packem_shared/parseCommands-BHsXoUCd.js";import{runConcurrently as X}from"./packem_shared/runConcurrently-D1Ytsjaj.js";import{runConcurrentFallback as $}from"./packem_shared/runConcurrentFallback-BhJCT2LA.js";import{defaultTaskRunner as re}from"./packem_shared/defaultTaskRunner-RJnuLoJz.js";import{detectScriptShell as te}from"./packem_shared/detectScriptShell-CaTDk5cW.js";import{FileAccessTracker as se,generatePreloadScript as pe}from"./packem_shared/FileAccessTracker-DBz_w4wl.js";import{FingerprintManager as me}from"./packem_shared/FingerprintManager-CYW2EwLc.js";import{detectFrameworks as ce,getFrameworkEnvVariables as fe,inferFrameworkEnvPatterns as le}from"./packem_shared/detectFrameworks-WVZJOPgN.js";import{projectGraphToDot as he,toGraphAscii as de,toGraphHtml as ue,toGraphJson as ke,toGraphvizDot as Te}from"./packem_shared/projectGraphToDot-FN6oHDGH.js";import{IncrementalFileHasher as ge}from"./packem_shared/IncrementalFileHasher-B-V3i2x-.js";import{CompositeLifeCycle as Re,ConsoleLifeCycle as ve,EmptyLifeCycle as Fe}from"./packem_shared/CompositeLifeCycle-C6aee9GK.js";import{LockfileHasher as be,extractPackageName as Ee,parseNpmLockfile as Pe,parsePnpmLockfile as Se,parseYarnLockfile as Ie}from"./packem_shared/extractPackageName-BeL6Gc3a.js";import{LogReporter as He,createLogReporter as Ae}from"./packem_shared/LogReporter-3R3oWj-Q.js";import{isNativeAvailable as De,loadNativeBindings as _e}from"./packem_shared/isNativeAvailable-CkTjxb7P.js";import{resolveOutputs as Ge}from"./packem_shared/resolveOutputs-BBjdaraf.js";import{INPUT_URI_SCHEMES as Oe,InvalidInputUriError as Ue,looksLikeInputUri as Ve,parseInputUri as We}from"./packem_shared/INPUT_URI_SCHEMES-Csrd0tlg.js";import{buildEnhancedPath as ze,collectNodeModulesBinDirs as Ye,withEnhancedPath as qe}from"./packem_shared/collectNodeModulesBinDirs-CD-eDrtO.js";import{enforceProjectConstraints as Ke}from"./packem_shared/enforceProjectConstraints-dNc1SwRi.js";import{generateRunSummary as Xe,getLastRunSummaryPath as Ze,readLastRunSummary as $e,writeLastRunSummary as er,writeRunSummary as rr}from"./packem_shared/generateRunSummary-L9Z2NfWn.js";import{createTaskGraph as tr,getTaskId as ar,parseTaskId as sr}from"./packem_shared/createTaskGraph-BBG8Rosl.js";import{findCycle as nr,findCycles as mr,getDependentTasks as ir,getLeafTasks as cr,getTransitiveDependencies as fr,makeAcyclic as lr,reverseTaskGraph as xr,walkTaskGraph as hr}from"./packem_shared/findCycle-BY8-jmzB.js";import{InProcessTaskHasher as ur,computeTaskHash as kr}from"./packem_shared/computeTaskHash-CaPdG1BA.js";import{TaskOrchestrator as Cr}from"./packem_shared/TaskOrchestrator-CYj5MLwz.js";import{TaskScheduler as yr,parsePartition as Rr}from"./packem_shared/parsePartition-Bt1jBjZH.js";import{TerminalBuffer as Fr}from"./packem_shared/TerminalBuffer-BtZy7TpT.js";import{T as br}from"./packem_shared/tracked-executor-B90U4Um3.js";import{d as Pr,j as Sr,T as Ir,b as Lr,E as Hr,v as Ar,h as wr,O as Dr}from"./packem_shared/utils-BH2W5Wml.js";import{evaluateWhen as Mr,explainWhen as Gr,getCurrentBranch as Nr,resetBranchCache as Or}from"./packem_shared/getCurrentBranch-D-qoZByx.js";import{getMainWorktreeRoot as Vr,isLinkedWorktree as Wr,resetWorktreeCache as jr}from"./packem_shared/getMainWorktreeRoot-DB9P2wDL.js";import{createInputHandler as Yr}from"./packem_shared/createInputHandler-CkDCpPYy.js";import{expandArguments as Jr}from"./packem_shared/expandArguments-D7qvc6Rp.js";import{expandShortcut as Qr}from"./packem_shared/expandShortcut-BErNHNXZ.js";import{expandTokens as Zr,expandTokensInString as $r}from"./packem_shared/expandTokensInString-DVSFEdWu.js";import{expandWildcard as ro}from"./packem_shared/expandWildcard-DE0dOOZF.js";import{formatTimingTable as to,logTimings as ao}from"./packem_shared/formatTimingTable-CP3rsDwf.js";import{runTeardown as po}from"./packem_shared/runTeardown-DAn1xFWJ.js";import{stripQuotes as mo}from"./packem_shared/stripQuotes-jkZb0CL9.js";import{withRestart as co}from"./packem_shared/withRestart-DKtEGsQA.js";export{R as Cache,Re as CompositeLifeCycle,ve as ConsoleLifeCycle,v as DEFAULT_CACHE_DIRECTORY_NAME,Fe as EmptyLifeCycle,se as FileAccessTracker,me as FingerprintManager,T as HttpRemoteCache,Oe as INPUT_URI_SCHEMES,ur as InProcessTaskHasher,ge as IncrementalFileHasher,Ue as InvalidInputUriError,be as LockfileHasher,He as LogReporter,g as ReapiRemoteCache,Cr as TaskOrchestrator,yr as TaskScheduler,Fr as TerminalBuffer,br as TrackedTaskExecutor,I as V2_AC,L as V2_CAS,H as V2_INDEX,A as V2_ROOT,w as V2_TMP,D as acEntryPath,x as actionDigestForTaskHash,ze as buildEnhancedPath,o as buildForwardDependencyMap,t as buildReverseDependencyMap,_ as casBlobPath,Pr as collectFiles,Ye as collectNodeModulesBinDirs,kr as computeTaskHash,N as containsBlob,h as containsByTaskHash,Sr as createFailureResult,Yr as createInputHandler,Ae as createLogReporter,i as createRemoteCacheBackend,tr as createTaskGraph,re as defaultTaskRunner,ce as detectFrameworks,te as detectScriptShell,E as digestBuffer,P as digestFile,Ke as enforceProjectConstraints,Mr as evaluateWhen,a as expandAffected,Jr as expandArguments,Qr as expandShortcut,Zr as expandTokens,$r as expandTokensInString,ro as expandWildcard,Gr as explainWhen,Ee as extractPackageName,O as fetchBlobToFile,s as filterAffectedTasks,nr as findCycle,mr as findCycles,F as formatCacheSize,to as formatTimingTable,pe as generatePreloadScript,Xe as generateRunSummary,p as getAffectedProjects,n as getChangedFiles,Nr as getCurrentBranch,ir as getDependentTasks,fe as getFrameworkEnvVariables,Ze as getLastRunSummaryPath,cr as getLeafTasks,Vr as getMainWorktreeRoot,ar as getTaskId,fr as getTransitiveDependencies,Ir as hashFile,Lr as hashStrings,le as inferFrameworkEnvPatterns,Wr as isLinkedWorktree,De as isNativeAvailable,_e as loadNativeBindings,ao as logTimings,Ve as looksLikeInputUri,lr as makeAcyclic,B as parseCacheSize,K as parseCommands,We as parseInputUri,Pe as parseNpmLockfile,Rr as parsePartition,Se as parsePnpmLockfile,sr as parseTaskId,Ie as parseYarnLockfile,he as projectGraphToDot,U as putBlobFromBytes,V as putBlobFromFile,$e as readLastRunSummary,Hr as readPackageDeps,Or as resetBranchCache,jr as resetWorktreeCache,c as resolveCacheMode,Ge as resolveOutputs,Ar as resolveTaskCwd,f as resolveTurboEnvCompat,d as retrieveByTaskHash,xr as reverseTaskGraph,$ as runConcurrentFallback,X as runConcurrently,po as runTeardown,wr as sortObjectKeys,u as storeByTaskHash,mo as stripQuotes,M as taskHashIndexPath,Y as toChromeTrace,de as toGraphAscii,ue as toGraphHtml,ke as toGraphJson,Te as toGraphvizDot,W as touchBlob,Dr as uniqueId,j as verifyBlob,hr as walkTaskGraph,qe as withEnhancedPath,co as withRestart,q as writeChromeTrace,er as writeLastRunSummary,rr as writeRunSummary};
@@ -0,0 +1,2 @@
1
+ var I=Object.defineProperty;var b=(s,t)=>I(s,"name",{value:t,configurable:!0});import{createRequire as R}from"node:module";import{parseBytes as X,formatBytes as Y}from"@visulima/humanizer";import{dirname as N,join as u,resolve as x}from"@visulima/path";import{a as G,b as K}from"./archive-CDfGy5Lm.js";import{O as m}from"./utils-BH2W5Wml.js";import{acEntryPath as A,tmpDirectory as B,taskHashIndexPath as z,V2_ROOT as _}from"./V2_ROOT-injxWBrl.js";import{fetchBlobToFile as L,containsBlob as U,putBlobFromFile as Z}from"./containsBlob-DAU8R7GH.js";import{resolveOutputs as Q}from"./resolveOutputs-BBjdaraf.js";const J=R(import.meta.url),k=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,E=b(s=>{if(typeof k<"u"&&k.versions&&k.versions.node){const[t,e]=k.versions.node.split(".").map(Number);if(t>22||t===22&&e>=3||t===20&&e>=16)return k.getBuiltinModule(s)}return J(s)},"__cjs_getBuiltinModule"),{createWriteStream:H}=E("node:fs"),{mkdir:f,writeFile:d,rename:w,rm:l,readFile:v,utimes:q,open:V,stat:O,readdir:S,cp:D}=E("node:fs/promises"),{pipeline:W}=E("node:stream/promises");var tt=Object.defineProperty,C=b((s,t)=>tt(s,"name",{value:t,configurable:!0}),"s");const et=C(async(s,t,e)=>{const r=A(s,t),a=B(s),i=`${a}/${m()}`;await f(a,{recursive:!0}),await f(N(r),{recursive:!0});const n=`${JSON.stringify(e,null,2)}
2
+ `;await d(i,n);try{await w(i,r)}catch(c){throw await l(i,{force:!0}).catch(()=>{}),c}},"writeActionEntry"),at=C(async(s,t)=>{const e=A(s,t);try{const r=await v(e,"utf8"),a=JSON.parse(r),i=new Date;return await q(e,i,i).catch(()=>{}),a}catch{return null}},"readActionEntry"),rt=C(async(s,t,e)=>{const r=z(s,t),a=B(s),i=`${a}/${m()}`;await f(a,{recursive:!0}),await f(N(r),{recursive:!0}),await d(i,e);try{await w(i,r)}catch(n){throw await l(i,{force:!0}).catch(()=>{}),n}},"writeTaskHashIndex"),st=C(async(s,t)=>{try{const e=(await v(z(s,t),"utf8")).trim();return e.length>0?e:null}catch{return null}},"readTaskHashIndex");var it=Object.defineProperty,y=b((s,t)=>it(s,"name",{value:t,configurable:!0}),"d");const ct=10080*60*1e3,nt=".task-runner-cache",ot=y(s=>{if(s.includes("\0"))throw new Error("cacheNamespace: null bytes are not allowed.");if(s.includes("/")||s.includes("\\"))throw new Error(`cacheNamespace: path separators are not allowed (received ${JSON.stringify(s)}).`);if(s==="."||s==="..")throw new Error(`cacheNamespace: "${s}" would escape the cache subtree.`)},"assertSafeNamespace"),$=y(async s=>{try{await l(s,{force:!0,recursive:!0})}catch{}},"removeEntry"),j=y(async s=>{let t=0;try{const e=await S(s,{withFileTypes:!0});for(const r of e){const a=u(s,r.name);if(r.isDirectory())t+=await j(a);else if(r.isFile()){const i=await O(a);t+=i.size}}}catch{}return t},"getDirectorySize"),ut=y(s=>{const t=X(s.trim());if(Number.isNaN(t))throw new TypeError(`Invalid cache size format: "${s}". Expected format like "500MB" or "1GB".`);return t},"parseCacheSize"),kt=y(s=>Y(s,{decimals:1,space:!1}),"formatCacheSize");class Ot{static{b(this,"Z")}static{y(this,"Cache")}#e;#t;#r;#a;#s=Promise.resolve();constructor(t){this.#e=t.workspaceRoot;const e=t.cacheDirectory??u(t.workspaceRoot,nt);t.cacheNamespace!==void 0&&t.cacheNamespace.length>0&&ot(t.cacheNamespace),this.#t=t.cacheNamespace&&t.cacheNamespace.length>0?u(e,"ns",t.cacheNamespace):e,this.#r=t.maxCacheAge??ct,this.#a=t.maxCacheSize?ut(t.maxCacheSize):void 0}get cacheDirectory(){return this.#t}get casRoot(){return this.#t}async getActionResult(t){return at(this.#t,t.hash)}async resolveActionDigestForTaskHash(t){return st(this.#t,t)}async putActionResult(t,e,r,a){await this.#i(a),await et(this.#t,e.hash,r),await rt(this.#t,t,e.hash)}async materializeOutputs(t,e){for(const r of t.outputFiles){const a=x(e,r.path);if(!await L(this.#t,r.digest,a))return!1}return!0}async#i(t){for(const e of t){if(await U(this.#t,e.digest))continue;const r=u(this.#t,_,"tmp",`.put-${m()}`);await f(N(r),{recursive:!0});const a=await e.open();await W(a,H(r)),await Z(this.#t,e.digest,r),await l(r,{force:!0}).catch(()=>{})}}async get(t){const e=u(this.#t,t);try{await v(u(e,".commit"));const r=await v(u(e,"code"),"utf8"),a=Number.parseInt(r.trim(),10);if(Number.isNaN(a))return;let i="";try{i=await v(u(e,"terminalOutput"),"utf8")}catch{}let n;try{const c=await v(u(e,"fingerprint.json"),"utf8");n=JSON.parse(c)}catch{}return{code:a,fingerprint:n,hash:t,terminalOutput:i}}catch{return}}async put(t,e,r,a,i,n){const c=u(this.#t,t),h=u(this.#t,`.tmp-${t}-${m()}`);try{await f(h,{recursive:!0});const o=[d(u(h,"code"),String(a)),d(u(h,"terminalOutput"),e),this.#o(h,r,n)];i&&o.push(d(u(h,"fingerprint.json"),JSON.stringify(i))),await Promise.all(o),await d(u(h,".commit"),"");const p=`${c}.trash-${m()}`;let g=!1;try{await w(c,p),g=!0}catch{}try{await w(h,c)}catch(F){throw g&&await w(p,c).catch(()=>{}),F}g&&$(p).catch(()=>{})}catch{await $(h)}}async restoreOutputs(t,e,r){const a=u(this.#t,t);return lt(a,this.#e,r)}async getByTaskId(t){const e=u(this.#t,".task-index.json");try{const r=await v(e,"utf8"),a=JSON.parse(r)[t];return a?this.get(a):void 0}catch{return}}async setTaskIndex(t,e){const r=this.#s.then(()=>this.#c(t,e));return this.#s=r.catch(()=>{}),r}async#c(t,e){const r=u(this.#t,".task-index.json"),a=u(this.#t,`.task-index-${m()}.tmp`);await f(this.#t,{recursive:!0}),await this.#n(async()=>{let i={};try{const n=await v(r,"utf8");i=JSON.parse(n)}catch{}i[t]=e,await d(a,JSON.stringify(i));try{await w(a,r)}catch{await d(r,JSON.stringify(i)),await l(a,{force:!0})}})}async#n(t){const e=u(this.#t,".task-index.lock"),r=3e4,a=1e4,i=Date.now();for(;;){let n;try{n=await V(e,"wx")}catch(c){if(c.code!=="EEXIST")throw c;const h=await O(e).catch(()=>{});if(h&&Date.now()-h.mtimeMs>r){await l(e,{force:!0}).catch(()=>{});continue}if(Date.now()-i>a)throw new Error(`Timed out waiting for task-index lock at ${e}`,{cause:c});await new Promise(o=>{setTimeout(o,50)});continue}try{return await t()}finally{await n.close().catch(()=>{}),await l(e,{force:!0}).catch(()=>{})}}}async removeOldEntries(){try{const t=await S(this.#t),e=Date.now(),r=[];for(const a of t){if(a.startsWith(".")||a===_)continue;const i=u(this.#t,a);try{const n=await O(i);if(e-n.mtimeMs>this.#r)await $(i);else{const c=await j(i);r.push({mtimeMs:n.mtimeMs,name:a,path:i,size:c})}}catch{}}if(this.#a!==void 0){const a=r.toSorted((n,c)=>n.mtimeMs-c.mtimeMs);let i=0;for(const n of a)i+=n.size;for(const n of a){if(i<=this.#a)break;await $(n.path),i-=n.size}}}catch{}}async clear(){try{await l(this.#t,{force:!0,recursive:!0})}catch{}}async#o(t,e,r){await ht(this.#e,t,e,r)}}const M="outputs.tar.br",ht=y(async(s,t,e,r)=>{if(e.length===0)return;const a=await Q(s,e,r);if(a.length===0)return;const i=u(t,`.outputs-stage-${m()}`),n=u(t,M);try{if(await f(i,{recursive:!0}),(await T(P,a,async c=>{const h=x(s,c),o=u(i,c);try{return await f(N(o),{recursive:!0}),await D(h,o,{preserveTimestamps:!0,recursive:!0}),!0}catch{return!1}})).filter(Boolean).length===0)return;await K(i,n)}finally{await l(i,{force:!0,recursive:!0}).catch(()=>{})}},"archiveOutputsCompressed"),P=16,T=y(async(s,t,e)=>{const r=Array.from({length:t.length});let a=0;const i=y(async()=>{for(;a<t.length;){const c=a;a+=1,r[c]=await e(t[c],c)}},"worker"),n=Array.from({length:Math.min(s,t.length)},()=>i());return await Promise.all(n),r},"runBounded"),lt=y(async(s,t,e)=>{const r=u(s,M);try{await O(r)}catch{return!0}const a=u(s,`.restore-${m()}`),i=e?.preserveMtime??!0,n=[];try{await f(a,{recursive:!0}),await G(r,a,e);const c=(await S(a)).sort(),h=m();for(const o of c){const p=x(t,o);n.push({absoluteOutput:p,backupCreated:!1,backupPath:`${p}.old-${h}`,entry:o,installed:!1,prePositioned:`${p}.restoring-${h}`})}return await T(P,n,async o=>{const p=u(a,o.entry);await f(N(o.absoluteOutput),{recursive:!0}),await l(o.prePositioned,{force:!0,recursive:!0}).catch(()=>{});try{await w(p,o.prePositioned)}catch(g){if(g.code==="EXDEV")await D(p,o.prePositioned,{preserveTimestamps:i,recursive:!0});else throw g}}),await T(P,n,async o=>{try{await O(o.absoluteOutput)}catch{return}await w(o.absoluteOutput,o.backupPath),o.backupCreated=!0}),await T(P,n,async o=>{await w(o.prePositioned,o.absoluteOutput),o.installed=!0}),await Promise.all(n.filter(o=>o.backupCreated).map(({backupPath:o})=>l(o,{force:!0,recursive:!0}).catch(()=>{}))),!0}catch{for(const c of n)if(c.installed){const h=`${c.absoluteOutput}.failed-${m()}`;await w(c.absoluteOutput,h).catch(()=>{}),c.backupCreated&&await w(c.backupPath,c.absoluteOutput).catch(()=>{}),c.installed=!1,await l(h,{force:!0,recursive:!0}).catch(()=>{})}else c.backupCreated&&await w(c.backupPath,c.absoluteOutput).catch(()=>{});return!1}finally{await l(a,{force:!0,recursive:!0}).catch(()=>{});for(const c of n)await l(c.prePositioned,{force:!0,recursive:!0}).catch(()=>{}),!(c.backupCreated&&!c.installed)&&await l(c.backupPath,{force:!0,recursive:!0}).catch(()=>{})}},"restoreOutputsCompressed");export{Ot as Cache,nt as DEFAULT_CACHE_DIRECTORY_NAME,kt as formatCacheSize,ut as parseCacheSize};
@@ -0,0 +1 @@
1
+ var r=Object.defineProperty;var n=(o,s)=>r(o,"name",{value:s,configurable:!0});var c=Object.defineProperty,i=n((o,s)=>c(o,"name",{value:s,configurable:!0}),"o");const l=i(o=>{switch(o){case"failure":return"[failure]";case"local-cache":case"local-cache-kept-existing":case"remote-cache":return"[cache]";case"skipped":return"[skipped]";case"success":return"[success]";default:return"[unknown]"}},"getStatusIcon");class d{static{n(this,"r")}static{i(this,"CompositeLifeCycle")}#s;constructor(s){this.#s=s}startCommand(){for(const s of this.#s)s.startCommand?.()}endCommand(){for(const s of this.#s)s.endCommand?.()}scheduleTask(s){for(const t of this.#s)t.scheduleTask?.(s)}startTasks(s){for(const t of this.#s)t.startTasks?.(s)}endTasks(s){for(const t of this.#s)t.endTasks?.(s)}printTaskTerminalOutput(s,t,e){for(const a of this.#s)a.printTaskTerminalOutput?.(s,t,e)}printCacheMiss(s,t){for(const e of this.#s)e.printCacheMiss?.(s,t)}printCacheDisabledByTask(s){for(const t of this.#s)t.printCacheDisabledByTask?.(s)}printEmptyFingerprintWarning(s,t){for(const e of this.#s)e.printEmptyFingerprintWarning?.(s,t)}printSelfModifyingSkip(s,t){for(const e of this.#s)e.printSelfModifyingSkip?.(s,t)}onTaskStdout(s,t){for(const e of this.#s)e.onTaskStdout?.(s,t)}onTaskStderr(s,t){for(const e of this.#s)e.onTaskStderr?.(s,t)}}class u{static{n(this,"l")}static{i(this,"ConsoleLifeCycle")}#s;constructor(s=!1){this.#s=s}startCommand(){this.#s&&console.log("[task-runner] Starting command execution")}endCommand(){this.#s&&console.log("[task-runner] Command execution complete")}scheduleTask(s){this.#s&&console.log(`[task-runner] Scheduled: ${s.id}`)}startTasks(s){for(const t of s)console.log(`> ${t.id}`)}endTasks(s){for(const t of s){const e=t.startTime&&t.endTime?` (${t.endTime-t.startTime}ms)`:"",a=l(t.status);console.log(`${a} ${t.task.id}${e}`)}}printTaskTerminalOutput(s,t,e){e.trim()&&console.log(e)}printCacheMiss(s,t){this.#s&&console.log(`[task-runner] ${s.id}: ${t}`)}}class h{static{n(this,"u")}static{i(this,"EmptyLifeCycle")}}export{d as CompositeLifeCycle,u as ConsoleLifeCycle,h as EmptyLifeCycle};