@vzn/vx 0.0.637 → 0.0.639
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.
- package/docs/caching.md +84 -28
- package/docs/cli.md +273 -408
- package/docs/execution.md +19 -44
- package/docs/features.md +13 -15
- package/docs/patterns.md +5 -7
- package/docs/schema.md +68 -61
- package/package.json +5 -5
- package/schemas/last.json +7 -4
- package/schemas/plan.json +2 -2
- package/skills/vx/SKILL.md +19 -6
- package/src/bin.ts +13 -7
- package/src/cache/cache.ts +60 -11
- package/src/cache/git-inputs.ts +6 -0
- package/src/cache/index.ts +10 -2
- package/src/cache/inputs.ts +0 -24
- package/src/cache/layer.ts +32 -12
- package/src/cache/layered-cache.ts +112 -315
- package/src/cache/plugin-cache.ts +240 -0
- package/src/cache/policy.ts +9 -0
- package/src/cache/remote-lane.ts +383 -0
- package/src/cache/run-history.ts +92 -8
- package/src/cache/run-store.ts +77 -0
- package/src/cache/schema.ts +44 -13
- package/src/cache/scoped-cache.ts +22 -2
- package/src/cli/cache.ts +33 -16
- package/src/cli/completions.ts +11 -7
- package/src/cli/foreign-flags.ts +10 -22
- package/src/cli/help.ts +22 -38
- package/src/cli/index.ts +25 -11
- package/src/cli/info.ts +8 -6
- package/src/cli/init.ts +14 -15
- package/src/cli/last.ts +20 -10
- package/src/cli/lock.ts +39 -27
- package/src/cli/plan-format.ts +10 -61
- package/src/cli/plugin-commands.ts +77 -6
- package/src/cli/plugin-templates.ts +1 -1
- package/src/cli/run.ts +31 -191
- package/src/cli/select.ts +18 -9
- package/src/cli/show.ts +72 -40
- package/src/cli/task-verb.ts +4 -4
- package/src/cli/upgrade.ts +132 -39
- package/src/cli/watch-cycle.ts +2 -1
- package/src/cli/watch-filter.ts +7 -2
- package/src/cli/watch-judge.ts +6 -1
- package/src/cli/watch.ts +73 -34
- package/src/cli/why.ts +14 -5
- package/src/cli/workspace-config.ts +2 -2
- package/src/config.ts +0 -6
- package/src/exec/executor.ts +1 -1
- package/src/exec/sandbox-runtime.ts +1 -1
- package/src/exec/sandbox-violations.ts +3 -1
- package/src/graph/index.ts +9 -1
- package/src/graph/priorities.ts +1 -1
- package/src/graph/scheduler.ts +12 -16
- package/src/graph/task-graph.ts +119 -21
- package/src/graph/task-status.ts +95 -0
- package/src/{orchestrator → history}/failure-mode.ts +20 -11
- package/src/{orchestrator → history}/history.ts +61 -5
- package/src/history/index.ts +48 -0
- package/src/{orchestrator → history}/metrics.ts +14 -23
- package/src/{orchestrator → history}/miss-reason.ts +1 -1
- package/src/index.ts +21 -29
- package/src/orchestrator/affected-tasks.ts +8 -3
- package/src/orchestrator/doctor.ts +2 -2
- package/src/orchestrator/execute-args.ts +80 -0
- package/src/orchestrator/execute-task.ts +47 -429
- package/src/orchestrator/fingerprint-watch.ts +2 -2
- package/src/orchestrator/index.ts +3 -74
- package/src/orchestrator/miss-save.ts +33 -3
- package/src/orchestrator/options.ts +1 -36
- package/src/orchestrator/output-host.ts +4 -3
- package/src/orchestrator/persistent-task.ts +321 -0
- package/src/orchestrator/persistent.ts +130 -3
- package/src/orchestrator/placement.ts +3 -3
- package/src/orchestrator/plan.ts +18 -5
- package/src/orchestrator/plugin-host.ts +77 -47
- package/src/orchestrator/plugin.ts +86 -14
- package/src/orchestrator/prepare.ts +74 -31
- package/src/orchestrator/projects.ts +3 -0
- package/src/orchestrator/remote-prefetch.ts +23 -6
- package/src/orchestrator/run-artifacts.ts +5 -177
- package/src/orchestrator/run-context.ts +55 -0
- package/src/orchestrator/run-failures.ts +15 -3
- package/src/orchestrator/run-records.ts +36 -4
- package/src/orchestrator/run-report.ts +81 -179
- package/src/orchestrator/run-settings.ts +1 -16
- package/src/orchestrator/run-stop.ts +153 -0
- package/src/orchestrator/run.ts +313 -555
- package/src/orchestrator/sandbox-fix.ts +0 -16
- package/src/orchestrator/signals.ts +14 -6
- package/src/orchestrator/stable-keys.ts +107 -3
- package/src/orchestrator/steps.ts +50 -0
- package/src/orchestrator/task-hash.ts +3 -16
- package/src/orchestrator/task-log-buffer.ts +1 -1
- package/src/orchestrator/task-process.ts +94 -0
- package/src/orchestrator/telemetry-host.ts +1 -1
- package/src/orchestrator/telemetry.ts +6 -83
- package/src/{orchestrator → report}/events.ts +41 -8
- package/src/{orchestrator → report}/forecast.ts +35 -2
- package/src/{orchestrator → report}/framed-output.ts +39 -34
- package/src/report/index.ts +36 -0
- package/src/{orchestrator → report}/logger.ts +166 -21
- package/src/{orchestrator → report}/status-line.ts +84 -7
- package/src/{orchestrator → report}/summary.ts +179 -63
- package/src/report/tally.ts +83 -0
- package/src/settings.ts +13 -23
- package/src/{orchestrator → util}/colors.ts +49 -4
- package/src/util/config-frame.ts +31 -2
- package/src/util/errors.ts +32 -0
- package/src/util/git-ignored.ts +143 -0
- package/src/util/index.ts +25 -3
- package/src/util/refusal-notice.ts +111 -0
- package/src/util/report.ts +39 -0
- package/src/util/settle.ts +14 -39
- package/src/util/tail.ts +1 -1
- package/src/util/ui.ts +197 -0
- package/src/workspace/affected.ts +20 -23
- package/src/workspace/dependency-rules.ts +12 -4
- package/src/workspace/migration.ts +87 -91
- package/src/workspace/workspace.ts +5 -4
- package/schemas/summary.json +0 -133
- package/src/cache/chained-cache.ts +0 -276
- package/src/orchestrator/tally.ts +0 -112
- /package/src/{orchestrator → report}/path-links.ts +0 -0
- /package/src/{orchestrator → report}/plain-output.ts +0 -0
- /package/src/{orchestrator → report}/terminal-signals.ts +0 -0
package/docs/execution.md
CHANGED
|
@@ -24,7 +24,7 @@ terminal and a task succeeding or failing. Read it alongside
|
|
|
24
24
|
│ PROCESS — always. (A whole-run `backend` seam existed until
|
|
25
25
|
│ 2026-08; it moved the scheduler server-side, which is why it
|
|
26
26
|
│ went. Per-task placement is the `executor` capability.)
|
|
27
|
-
│ --dry
|
|
27
|
+
│ --dry short-circuits into planRun instead.
|
|
28
28
|
│
|
|
29
29
|
├─ Prepare (src/orchestrator/prepare.ts:prepareRun — shared with planRun)
|
|
30
30
|
│ 1. findWorkspaceRoot(cwd) — the directory of the nearest
|
|
@@ -155,7 +155,7 @@ terminal and a task succeeding or failing. Read it alongside
|
|
|
155
155
|
│ signal, forward it (SIGHUP as SIGTERM) to everything
|
|
156
156
|
│ in liveChildren + persistentRegistry (and kill any
|
|
157
157
|
│ running cache.inputs.runtime probe, C-65), wait
|
|
158
|
-
│
|
|
158
|
+
│ 2 s for their groups, SIGKILL
|
|
159
159
|
│ what is still there, let the run finish its own
|
|
160
160
|
│ end (flush, teardown, cache close), then
|
|
161
161
|
│ die of the signal (SIGINT → 130, SIGTERM → 143,
|
|
@@ -303,11 +303,10 @@ terminal and a task succeeding or failing. Read it alongside
|
|
|
303
303
|
2. Run summary footer (projects / tasks / cache meters + info +
|
|
304
304
|
time + result) — counts only real tasks (with `exec`); group tasks
|
|
305
305
|
don't pollute the totals; failure frames replay just above it.
|
|
306
|
-
3. Optional --
|
|
307
|
-
and --profile Chrome-trace JSON (default profile.json).
|
|
306
|
+
3. Optional --profile Chrome-trace JSON (default profile.json).
|
|
308
307
|
4. recordRunBundle — one transaction writing a `runs` row per real
|
|
309
308
|
task plus the `invocations` header row (command, git/CI/host
|
|
310
|
-
context,
|
|
309
|
+
context, counts). Group + aborted tasks skipped; a run
|
|
311
310
|
a signal stopped records nothing.
|
|
312
311
|
5. Telemetry: emit the RunSummaryRecord to every active sink +
|
|
313
312
|
await their flush (crash-isolated; skipped when no sink).
|
|
@@ -325,11 +324,7 @@ terminal and a task succeeding or failing. Read it alongside
|
|
|
325
324
|
alive, Ctrl-C reaps the process group. That first exit ends the
|
|
326
325
|
session: the others are torn down (SIGTERM, grace, SIGKILL) and
|
|
327
326
|
a non-zero exit makes the run exit 1, so a script's `vx run dev`
|
|
328
|
-
fails when the server it started fell over.
|
|
329
|
-
`failed` with its own exit in the rewritten `--summarize` and in the
|
|
330
|
-
report `--report-file` writes; one a Ctrl-C stopped does not. The
|
|
331
|
-
stdout `--report` prints above the footer, so it reads as the
|
|
332
|
-
footer does, before the wait. Under
|
|
327
|
+
fails when the server it started fell over. Under
|
|
333
328
|
`holdPersistent` (the watch loop) run() instead returns them on
|
|
334
329
|
`RunSummary.persistent`, still running, for the caller to stop;
|
|
335
330
|
one that dies on its own after that is said, its `stop()` is not.
|
|
@@ -543,21 +538,20 @@ Every surface uses one outcome vocabulary: task axis `success` /
|
|
|
543
538
|
`failed` / `skipped` / `aborted` (+ `running` live), cache axis
|
|
544
539
|
`miss` / `up-to-date` (fresh) / `local` / `remote`. The `--verbosity 1`
|
|
545
540
|
table spells the combinations out as `success` / `restored-local` /
|
|
546
|
-
`restored-remote` / `up-to-date
|
|
547
|
-
Status and Cache columns.
|
|
541
|
+
`restored-remote` / `up-to-date`.
|
|
548
542
|
|
|
549
543
|
The colors / framing modules:
|
|
550
544
|
|
|
551
|
-
- `
|
|
545
|
+
- `util/colors.ts` — ANSI truecolor (`ansi-16m`), gated by
|
|
552
546
|
`NO_COLOR` / `FORCE_COLOR` / `isTTY`. Programmatic-logger callers
|
|
553
547
|
always see plain text.
|
|
554
|
-
- `
|
|
548
|
+
- `report/framed-output.ts` — the `┌─` frames, the glyph grid
|
|
555
549
|
(`formatTaskRow`), one-liners, persistent markers.
|
|
556
|
-
- `
|
|
550
|
+
- `report/status-line.ts` — the serialized writer + the worker
|
|
557
551
|
region.
|
|
558
|
-
- `
|
|
552
|
+
- `report/logger.ts` — composes them; resolves the output view
|
|
559
553
|
and applies the per-flow visibility policy.
|
|
560
|
-
- `
|
|
554
|
+
- `report/summary.ts` — the closing footer (wordmark rule,
|
|
561
555
|
projects/tasks/cache meters, info and time rows).
|
|
562
556
|
|
|
563
557
|
## Concurrency
|
|
@@ -617,9 +611,9 @@ snapshot is clean). `--cache-policy=<spec>` gives per-layer control. Full
|
|
|
617
611
|
semantics: [`cli.md` § Cache control](./cli.md#cache-control---cache-policy---no-cache---force)
|
|
618
612
|
and [`caching.md` § Cache policy](./caching.md#cache-policy-readwrite-axes).
|
|
619
613
|
|
|
620
|
-
## Planning
|
|
614
|
+
## Planning path (`--dry`)
|
|
621
615
|
|
|
622
|
-
|
|
616
|
+
`--dry` short-circuits execution. The planner (`orchestrator/plan.ts`)
|
|
623
617
|
runs the same setup steps — workspace discovery, config load, package
|
|
624
618
|
graph, task graph — and the same per-task hash derivation, then
|
|
625
619
|
probes the cache. The probe is read-only; against a remote layer it
|
|
@@ -628,8 +622,6 @@ deliberate side effect: `cache.inputs.runtime` / `workspaceRuntime`
|
|
|
628
622
|
probe commands DO run, because predicting a key requires resolving
|
|
629
623
|
them — keep runtime inputs side-effect-free.
|
|
630
624
|
|
|
631
|
-
The two flags differ only in output format:
|
|
632
|
-
|
|
633
625
|
- `--dry[=text|json]` → text (default) or JSON list of predicted
|
|
634
626
|
outcomes per task: `hit-local`, `hit-remote`, `miss`, `no-cache`,
|
|
635
627
|
`group`. Formatter: `cli/plan-format.ts:formatPlanText` /
|
|
@@ -639,36 +631,19 @@ The two flags differ only in output format:
|
|
|
639
631
|
executors is a plugin-factory call, the same class the cache capability
|
|
640
632
|
already makes at plan time; a plugin that throws costs the label, never
|
|
641
633
|
the plan.
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
`formatGraphDot`.
|
|
645
|
-
|
|
646
|
-
Mutually exclusive: `--dry` and `--graph` together is a parse error.
|
|
647
|
-
Combining either with `--summarize`, `--profile`, `--report` or
|
|
648
|
-
`--report-file` is a parse error (those need a real run; the last two
|
|
649
|
-
were accepted and wrote nothing until item 992).
|
|
634
|
+
Combining it with `--profile` is a parse error (the profile needs a
|
|
635
|
+
real run).
|
|
650
636
|
|
|
651
637
|
## Run artifacts
|
|
652
638
|
|
|
653
|
-
- **`--summarize[=<path>]`** — per-run JSON to
|
|
654
|
-
`<cacheDir>/runs/<run_id>.json` by default (or the explicit path).
|
|
655
|
-
Mirrors the `runs` table shape — one task entry per real task, hits
|
|
656
|
-
included, with status, hash, duration, cpu_ms, peak RSS, hrtime spans
|
|
657
|
-
(bigint serialized as strings to preserve ns precision).
|
|
658
639
|
- **`--profile[=<path>]`** — Chrome-trace JSON of every task's
|
|
659
640
|
wallclock span. Default path: `profile.json` (cwd-relative). One
|
|
660
641
|
`tid` per project so concurrent tasks render on distinct lanes.
|
|
661
642
|
Open with `chrome://tracing` or https://ui.perfetto.dev.
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
Writers live in `orchestrator/run-artifacts.ts:writeRunSummary` /
|
|
668
|
-
`writeRunProfile` and `orchestrator/run-report.ts`. A `--summarize` or
|
|
669
|
-
`--profile` write error is surfaced via `log.status`, a `--report-file`
|
|
670
|
-
one on stderr (`cli/run.ts`); neither changes the run's exit code — the
|
|
671
|
-
run already happened.
|
|
643
|
+
|
|
644
|
+
The writer is `orchestrator/run-artifacts.ts:writeRunProfile`. A write error is surfaced via `log.status` and does
|
|
645
|
+
not change the run's exit code — the run already happened. A CI job
|
|
646
|
+
summary is `@vzn/vx-ci`'s.
|
|
672
647
|
|
|
673
648
|
## Why each rule
|
|
674
649
|
|
package/docs/features.md
CHANGED
|
@@ -26,7 +26,7 @@ config key or an environment variable is missing here.
|
|
|
26
26
|
- **Task picker** — `vx run` with no task in a terminal lists tasks to pick. [page](https://vznjs.github.io/vx/features/task-picker/) · post: [The small things](https://vznjs.github.io/vx/blog/the-small-things/)
|
|
27
27
|
- **Typo hints** — an unknown task, project or filter suggests the nearest name. [page](https://vznjs.github.io/vx/features/filter-hints/) · post: [The small things](https://vznjs.github.io/vx/blog/the-small-things/)
|
|
28
28
|
- **Turbo and Nx spellings** (`-t`, `-p`, `--exclude`, `--parallel`, `--base`, `--dry-run`, `--skip-nx-cache`) — accepted, or refused naming the vx spelling. [page](https://vznjs.github.io/vx/features/turbo-nx-flags/) · post: [Flags you already know](https://vznjs.github.io/vx/blog/flags-you-already-know/)
|
|
29
|
-
- **Ctrl-C leaves nothing running**
|
|
29
|
+
- **Ctrl-C leaves nothing running** — the whole process tree stops, then teardown runs. [page](https://vznjs.github.io/vx/features/ctrl-c/) · post: [Ctrl-C leaves nothing running](https://vznjs.github.io/vx/blog/ctrl-c/)
|
|
30
30
|
- **Longest chain first** — the scheduler starts the critical path first; `@vzn/vx-schedule-history` learns it from past runs. [page](https://vznjs.github.io/vx/features/critical-path/) · post: [Bitsets, popcount, and a scheduler tick](https://vznjs.github.io/vx/blog/bitsets-and-the-scheduler/)
|
|
31
31
|
- **Schedule strategy** (`--schedule`, `run.schedule`, `VX_RUN_SCHEDULE`) — pick the order with no timings: most work waiting (default), longest chain, most direct dependents, or ready order; plugins still lead. [page](https://vznjs.github.io/vx/features/critical-path/) · post: [Which task runs first?](https://vznjs.github.io/vx/blog/scheduling-strategies/#pick-the-guess)
|
|
32
32
|
- **No daemon** — every run starts cold and still answers in milliseconds. [page](https://vznjs.github.io/vx/features/no-daemon/) · post: [No daemon, on purpose](https://vznjs.github.io/vx/blog/no-daemon/)
|
|
@@ -47,23 +47,20 @@ config key or an environment variable is missing here.
|
|
|
47
47
|
- **Run summary** — one block: projects, tasks, cache, time; nothing prints below it. [page](https://vznjs.github.io/vx/features/run-summary/) · post: [A run you can read](https://vznjs.github.io/vx/blog/a-run-you-can-read/)
|
|
48
48
|
- **Per-task table** (`--verbosity`) — a per-task summary after the run. [page](https://vznjs.github.io/vx/features/per-task-table/) · post: [One failure, and exactly what it takes down](https://vznjs.github.io/vx/blog/when-a-build-fails/)
|
|
49
49
|
- **Failed output kept for agents** — a failure's full log is saved and pointed to. [page](https://vznjs.github.io/vx/features/failed-output-kept/) · post: [Built for the agent at the keyboard](https://vznjs.github.io/vx/blog/built-for-agents/)
|
|
50
|
-
- **Markdown report** (`--report`, `--report-file`) — a run report for a PR or `$GITHUB_STEP_SUMMARY`. [page](https://vznjs.github.io/vx/features/markdown-report/) · post: [Output that fits the run](https://vznjs.github.io/vx/blog/output-that-fits-the-run/)
|
|
51
|
-
- **Run JSON** (`--summarize`) — per-run JSON for scripts, with the time the cache saved (`savedMs`). [page](https://vznjs.github.io/vx/features/run-json/) · post: [See inside a run](https://vznjs.github.io/vx/blog/see-inside-a-run/)
|
|
52
50
|
- **Trace profile** (`--profile`) — Chrome-trace JSON of the run. [page](https://vznjs.github.io/vx/features/profile/) · post: [Output that fits the run](https://vznjs.github.io/vx/blog/output-that-fits-the-run/)
|
|
53
51
|
- **Run branch** (`--branch`, `VX_RUN_BRANCH`) — name the branch a run records in its history and forecasts from; unset, git's branch, then the CI provider's. no post
|
|
54
|
-
- **Run tags** (`--tag`) — label a run; recorded in history. [page](https://vznjs.github.io/vx/features/run-tags/) · post: [See inside a run](https://vznjs.github.io/vx/blog/see-inside-a-run/)
|
|
55
52
|
- **Stage timing** (`VX_DEBUG_TIMING`) — vx's own stage table, for performance work. [page](https://vznjs.github.io/vx/features/stage-timing/) · post: [See inside a run](https://vznjs.github.io/vx/blog/see-inside-a-run/)
|
|
56
53
|
- **Output flows** — what is printed follows the run's intent (focused, broad or CI); a truthy `CI` wins. [page](https://vznjs.github.io/vx/features/output-flows/) · post: [Output that fits the run](https://vznjs.github.io/vx/blog/output-that-fits-the-run/)
|
|
57
54
|
- **Cache-aware glyphs** — each task line's glyph shows ran, fresh, restored locally or remotely, failed, skipped or persistent. [page](https://vznjs.github.io/vx/features/cache-glyphs/) · post: [Output that fits the run](https://vznjs.github.io/vx/blog/output-that-fits-the-run/)
|
|
58
55
|
- **GitHub Actions log groups** — on Actions, each task's block folds in a `::group::` with its outcome and time. [page](https://vznjs.github.io/vx/features/actions-log-groups/) · post: [The basics, done carefully](https://vznjs.github.io/vx/blog/the-basics/)
|
|
59
|
-
- **Colors** (`NO_COLOR`, `FORCE_COLOR`) — truecolor output, forced on or off by env. [page](https://vznjs.github.io/vx/features/colors/) · post: [The basics, done carefully](https://vznjs.github.io/vx/blog/the-basics/)
|
|
56
|
+
- **Colors** (`NO_COLOR`, `FORCE_COLOR`) — truecolor output, forced on or off by env; `TERM=dumb` prints plain, with no live region. [page](https://vznjs.github.io/vx/features/colors/) · post: [The basics, done carefully](https://vznjs.github.io/vx/blog/the-basics/)
|
|
60
57
|
- **Signal-named exits** — a failure reads `exit 137, 128 + SIGKILL`. [page](https://vznjs.github.io/vx/features/signal-exits/) · post: [When a task misbehaves](https://vznjs.github.io/vx/blog/tasks-that-misbehave/)
|
|
58
|
+
- **vx's own steps as rows** — on a terminal, what vx does around the tasks (`vx:uploads`, `<plugin>:teardown`) shows as a running row once it passes 150 ms, then a list row; never counted as a task. no post
|
|
61
59
|
- **Plain output off a TTY** — no live region, and a missing task lists tasks instead of opening the picker. [page](https://vznjs.github.io/vx/features/plain-off-tty/) · post: [The basics, done carefully](https://vznjs.github.io/vx/blog/the-basics/)
|
|
62
60
|
|
|
63
61
|
## Plan and explain
|
|
64
62
|
|
|
65
63
|
- **Dry run** (`--dry`) — the task graph and the predicted hits and misses, text or JSON (with the predicted wall time and its critical path), nothing runs. [page](https://vznjs.github.io/vx/features/dry-run/) · post: [See the plan before you run it](https://vznjs.github.io/vx/blog/dry-run/)
|
|
66
|
-
- **Graph** (`--graph`) — the task graph as Graphviz DOT. [page](https://vznjs.github.io/vx/features/task-graph/) · post: [See inside a run](https://vznjs.github.io/vx/blog/see-inside-a-run/)
|
|
67
64
|
- **vx why** (`vx why`, `--run`) — why a task re-ran, down to the file, env var or config that changed, and the task that wrote a moved input. [page](https://vznjs.github.io/vx/features/vx-why/) · post: [Why did this re-run?](https://vznjs.github.io/vx/blog/why-did-this-rerun/)
|
|
68
65
|
- **vx show** (`vx show`) — every project, a project's or a task's resolved config, read from the lock as a run reads it. [page](https://vznjs.github.io/vx/features/vx-show/) · post: [See what a task really is](https://vznjs.github.io/vx/blog/vx-show/)
|
|
69
66
|
- **vx last** (`vx last`, `--list`, `--failed`, `--log`, `--stats`, `--branch`) — replay a recorded run's summary, list recent runs, print one task's output, or per-task history stats (p50 as the live estimate forecasts it on a branch, p99, pass and hit rate, failure mode, peak RSS). [page](https://vznjs.github.io/vx/features/vx-last/) · post: [The last run, on request](https://vznjs.github.io/vx/blog/vx-last/)
|
|
@@ -75,7 +72,7 @@ config key or an environment variable is missing here.
|
|
|
75
72
|
- **Docs for agents** (`llms.txt`, `llms-full.txt`) — the whole site as markdown for coding agents. [page](https://vznjs.github.io/vx/features/llms-txt/) · post: [Built for the agent at the keyboard](https://vznjs.github.io/vx/blog/built-for-agents/)
|
|
76
73
|
- **vx docs** (`vx docs`, `--limit`) — search the CLI, config and cache reference offline; it ships inside vx. [page](https://vznjs.github.io/vx/features/vx-docs/) · post: [The reference, offline](https://vznjs.github.io/vx/blog/vx-docs-offline/)
|
|
77
74
|
- **Affected reasons** (`--affected --dry`) — each kept task says the changed file or the dependency chain that reached it, text or JSON. [page](https://vznjs.github.io/vx/features/affected-reasons/) · post: [See inside a run](https://vznjs.github.io/vx/blog/see-inside-a-run/)
|
|
78
|
-
- **Agent skill** (`skills/vx/SKILL.md`, `npx skills add vznjs/vx
|
|
75
|
+
- **Agent skill** (`skills/vx/SKILL.md`, `npx skills add vznjs/vx`) — an installable skill that teaches a coding agent to run, debug and query vx through the CLI's `--format json`; copy it from `node_modules/@vzn/vx/skills/vx/` to match the installed version. [page](https://vznjs.github.io/vx/features/agent-skill/) · post: [Built for the agent at the keyboard](https://vznjs.github.io/vx/blog/built-for-agents/)
|
|
79
76
|
|
|
80
77
|
## Cache
|
|
81
78
|
|
|
@@ -83,7 +80,7 @@ config key or an environment variable is missing here.
|
|
|
83
80
|
- **Inputs** (`cache.inputs.env`, `cache.inputs.runtime`, `cache.inputs.tasks`, `cache.inputs.workspaceFiles`, `cache.inputs.workspaceRuntime`) — env vars, tool versions, upstream tasks and workspace files in the key. [page](https://vznjs.github.io/vx/features/key-inputs/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
84
81
|
- **Outputs** (`cache.outputs.files`, `cache.outputs.workspaceFiles`) — what a hit restores. [page](https://vznjs.github.io/vx/features/cache-outputs/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
85
82
|
- **Input stability** (`cache.inputStability`, workspace `cache.inputStability`, `VX_CACHE_INPUT_STABILITY_STRATEGY`, `VX_CACHE_INPUT_STABILITY_SEVERITY`) — an input written while the command runs withholds the save, on CI too, and the saves of every task that ran over its outputs; `strategy: 'mutable'` accepts a task's identical rewrite of its own input, `'unchecked'` skips the check; `severity: 'error'` fails the run instead of warning. no post
|
|
86
|
-
- **Keep outputs on a miss** (`cache.outputs.clean`, workspace `cache.outputs.clean
|
|
83
|
+
- **Keep outputs on a miss** (`cache.outputs.clean`, workspace `cache.outputs.clean`) — `false` leaves a task's outputs in place for a tool that reads its last output (tsc's `.tsbuildinfo`) and caches everything the outputs then hold, leftovers included (an opt-out of the clean-tree guarantee). no post
|
|
87
84
|
- **Outputs are exactly the snapshot** (`run.rules.exclusiveOutputs`, `VX_RUN_RULES_EXCLUSIVE_OUTPUTS`) — a hit leaves the tree as the run did; two tasks may not own one output without an edge. [page](https://vznjs.github.io/vx/features/strict-outputs/) · post: [The tree is exactly the snapshot](https://vznjs.github.io/vx/blog/strict-output-ownership/)
|
|
88
85
|
- **Keys from git's index** — tracked clean files hash by their blob id, no read. [page](https://vznjs.github.io/vx/features/keys-from-git/) · post: [Your cache key is already in git's index](https://vznjs.github.io/vx/blog/keys-from-git/)
|
|
89
86
|
- **Config keyed as evaluated** — the key sees the resolved config object. [page](https://vznjs.github.io/vx/features/typescript-config/) · post: [Configs are programs](https://vznjs.github.io/vx/blog/resolved-config-hashing/)
|
|
@@ -91,7 +88,7 @@ config key or an environment variable is missing here.
|
|
|
91
88
|
- **Lockfile-aware keys** (`@vzn/vx-lockfile`: `pnpm()`, `bun()`, `npm()`, `yarn()`) — a bump re-keys only the projects whose closure changed; each also adds every member with a `package.json` as a project named by its `name`, gives vx the project edges the lockfile records (core reads no `package.json`), keys each package's `package.json` as an input and folds its manager's install settings (`.npmrc`, `bunfig.toml`, `pnpm-workspace.yaml`, `.yarnrc.yml`) into every task. Core keys no package file, so without one an install re-keys nothing; `npm()` reads `npm-shrinkwrap.json` first, and `bun()` refuses a lone `bun.lockb`. [page](https://vznjs.github.io/vx/features/lockfile-keys/) · post: [A lockfile bump should re-key two tasks](https://vznjs.github.io/vx/blog/lockfile-aware-keys/)
|
|
92
89
|
- **Upfront keys** (`run.rules.upfrontKeys`, `VX_RUN_RULES_UPFRONT_KEYS`) — refuses an input glob a same-project task's outputs could match, so every key is known before anything runs. [page](https://vznjs.github.io/vx/features/upfront-keys/) · post: [Cascade through dependencies by folding input keys, never outputs](https://vznjs.github.io/vx/blog/cascade-through-inputs/)
|
|
93
90
|
- **Dependency rules** (`run.rules.dependencies`) — `vx lock` refuses a project depending on one a tag or name rule denies or does not allow, every broken edge named (`VX_E_DEPENDENCY_RULE`). [schema](https://vznjs.github.io/vx/schema/) · post: [Say which projects may depend on which](https://vznjs.github.io/vx/blog/dependency-rules/)
|
|
94
|
-
- **Cache controls** (`--no-cache`, `--force`, `--cache-policy`, `--cache-policy`, `VX_CACHE_POLICY`, `cache.policy`) — off,
|
|
91
|
+
- **Cache controls** (`--no-cache`, `--force`, `--cache-policy`, `--cache-policy`, `VX_CACHE_POLICY`, `cache.policy`) — off, re-run past it, or per-layer read/write. [page](https://vznjs.github.io/vx/features/cache-controls/) · post: [The cache on your terms](https://vznjs.github.io/vx/blog/the-cache-on-your-terms/)
|
|
95
92
|
- **Cache location** (`--cache-dir`, `cache.dir`, `VX_CACHE_DIR`) — where the cache lives. [page](https://vznjs.github.io/vx/features/cache-location/) · post: [The cache on your terms](https://vznjs.github.io/vx/blog/the-cache-on-your-terms/)
|
|
96
93
|
- **Cache scope** (`cache.scope`, `VX_CACHE_SCOPE`, `--cache-scope`) — a scope reads the default entries, then its own, and writes only its own. [page](https://vznjs.github.io/vx/features/cache-scope/) · post: [The cache on your terms](https://vznjs.github.io/vx/blog/the-cache-on-your-terms/)
|
|
97
94
|
- **Cache pruning** (`vx cache clean`, `--older-than`, `--max-size`, `--global`, `--dry-run`, `cache.retention`, `maxSize`, `olderThan`, `VX_CACHE_RETENTION_MAX_SIZE`, `VX_CACHE_RETENTION_OLDER_THAN`) — evict by age or size, LRU; with no bound, clear this repo's store (shared by its checkouts) and run history; `--global` clears every repo's store. [page](https://vznjs.github.io/vx/features/cache-prune/) · post: [One command to know your workspace](https://vznjs.github.io/vx/blog/know-your-workspace/)
|
|
@@ -101,7 +98,7 @@ config key or an environment variable is missing here.
|
|
|
101
98
|
- **Hits replay both streams** — stdout and stderr come back in the order the run printed them. [page](https://vznjs.github.io/vx/features/both-streams/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
102
99
|
- **Restore lane** — cache restores run on their own lane, up to twice `--concurrency`. [page](https://vznjs.github.io/vx/features/restore-lane/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
103
100
|
- **Line-ending-correct keys** — files git filters (`eol`, `core.autocrlf`) key on the bytes the build sees. [page](https://vznjs.github.io/vx/features/line-endings/) · post: [Your cache key is already in git's index](https://vznjs.github.io/vx/blog/keys-from-git/)
|
|
104
|
-
- **Background remote uploads** — remote writes drain at the end of the run and never fail the build. [page](https://vznjs.github.io/vx/features/background-uploads/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
101
|
+
- **Background remote uploads** — remote writes drain at the end of the run and never fail the build; the footer counts them running (`⇡`) and failed (`✗`). [page](https://vznjs.github.io/vx/features/background-uploads/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
105
102
|
- **Bring your own remote cache** (plugin `cache`) — plug any cache server in through one interface. [page](https://vznjs.github.io/vx/features/custom-remote-cache/) · post: [Extend vx in an afternoon](https://vznjs.github.io/vx/blog/extend-vx/)
|
|
106
103
|
|
|
107
104
|
## Correctness
|
|
@@ -109,7 +106,7 @@ config key or an environment variable is missing here.
|
|
|
109
106
|
- **Sandboxed tasks** (`exec.sandbox`: `allow`, `deny`, `ignore`, `weakerNetworkIsolation`, `weakerWhenNested`) — a task reads and writes only what it declares; `allow` names `read`, `write`, `network`, `unixSockets`, `localBinding`, `pty`, `systemInfo`, `gitConfig`, `machLookup`. [page](https://vznjs.github.io/vx/features/sandbox/) · post: [The sandbox](https://vznjs.github.io/vx/blog/the-sandbox/)
|
|
110
107
|
- **Env isolation** (`exec.env`: `define`, `passThrough`, `secret`, `VX_DEBUG_DUMPABLE`) — a task sees only the env it names; secrets are masked; vx hides its own env from tasks (Linux and macOS). [page](https://vznjs.github.io/vx/features/env-isolation/) · post: [A task sees only the env it names](https://vznjs.github.io/vx/blog/env-isolation/)
|
|
111
108
|
- **vx lock** (`vx lock`, `--check`, `--format json`, `lock.reviewFiles`, `VX_LOCK_REVIEW_FILES`) — find the projects (every directory holding a `vx.config`), freeze what their configs evaluate to and check the graph rules once; only `vx lock` evaluates configs: runs, `vx show` and `vx info` read the lock and never write it; a pretty `vx.lock.json` beside each config shows reviewers what it resolves to. [page](https://vznjs.github.io/vx/features/vx-lock/) · post: [vx lock: freezing what the key sees](https://vznjs.github.io/vx/blog/lock-and-frozen/)
|
|
112
|
-
- **Flaky detection** — a task
|
|
109
|
+
- **Flaky detection** — a task whose key fails after it passed is reported flaky, judged on every worktree's record of the repo. [page](https://vznjs.github.io/vx/features/flaky-detection/) · post: [Flaky is a claim](https://vznjs.github.io/vx/blog/flaky-tasks/)
|
|
113
110
|
- **Project boundaries** — globs never cross into another project. [page](https://vznjs.github.io/vx/features/project-boundaries/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
114
111
|
- **Artifact integrity checks** — a CRC-32, a key match and an outputs-only check on every artifact; damage is a miss. [page](https://vznjs.github.io/vx/features/artifact-integrity/) · post: [What goes into a key, and what comes back](https://vznjs.github.io/vx/blog/inside-a-cache-hit/)
|
|
115
112
|
- **Sandbox names what to grant** — a refused write is named beside the failed task with the path to allow. [page](https://vznjs.github.io/vx/features/sandbox-grants/) · post: [Guard rails that tell you the fix](https://vznjs.github.io/vx/blog/guard-rails/)
|
|
@@ -118,12 +115,12 @@ config key or an environment variable is missing here.
|
|
|
118
115
|
|
|
119
116
|
## Daily work
|
|
120
117
|
|
|
121
|
-
- **Watch mode** (`vx watch`, `--poll`, `watch.poll`, `VX_WATCH_POLL`) — re-run what a change affects, on content, not events. [page](https://vznjs.github.io/vx/features/watch/) · post: [Watch: a content gate](https://vznjs.github.io/vx/blog/watch-mode/)
|
|
122
|
-
- **Dev servers in the graph** (`exec.persistent`, `readyWhen
|
|
118
|
+
- **Watch mode** (`vx watch`, `--poll`, `watch.poll`, `VX_WATCH_POLL`, `VX_DEBUG_WATCH`) — re-run what a change affects, on content, not events. [page](https://vznjs.github.io/vx/features/watch/) · post: [Watch: a content gate](https://vznjs.github.io/vx/blog/watch-mode/)
|
|
119
|
+
- **Dev servers in the graph** (`exec.persistent`, `readyWhen`) — a server is a node; dependents start when it is ready. [page](https://vznjs.github.io/vx/features/dev-servers/) · post: [Dev servers as graph nodes](https://vznjs.github.io/vx/blog/dev-servers-in-the-graph/)
|
|
123
120
|
- **Interactive tasks** (`exec.interactive`) — a task that owns the terminal. [page](https://vznjs.github.io/vx/features/interactive-tasks/) · post: [When a task misbehaves](https://vznjs.github.io/vx/blog/tasks-that-misbehave/)
|
|
124
121
|
- **Shell completions** (`vx completions`) — bash, zsh, fish. [page](https://vznjs.github.io/vx/features/completions/) · post: [The small things](https://vznjs.github.io/vx/blog/the-small-things/)
|
|
125
122
|
- **Project-local vx** (`VX_HANDED_OFF`) — a global vx hands every call to the project's own `@vzn/vx`. [page](https://vznjs.github.io/vx/cli/#which-vx-runs)
|
|
126
|
-
- **vx upgrade** (`vx upgrade`) — upgrade vx the way it was installed: a verified binary, or its package manager. [page](https://vznjs.github.io/vx/features/upgrade/) · post: [An upgrade you can trust](https://vznjs.github.io/vx/blog/upgrade-you-can-trust/)
|
|
123
|
+
- **vx upgrade** (`vx upgrade`) — upgrade vx the way it was installed: a verified binary, or its package manager. Inside a project, the project's vx and the global vx that ran it move together. [page](https://vznjs.github.io/vx/features/upgrade/) · post: [An upgrade you can trust](https://vznjs.github.io/vx/blog/upgrade-you-can-trust/)
|
|
127
124
|
- **Help and version** (`vx help`, `vx version`) — every verb's reference. [page](https://vznjs.github.io/vx/features/help-and-version/) · post: [An upgrade you can trust](https://vznjs.github.io/vx/blog/upgrade-you-can-trust/)
|
|
128
125
|
- **Did-you-mean** — a mistyped flag or verb gets the nearest valid spelling. [page](https://vznjs.github.io/vx/features/did-you-mean/) · post: [The small things](https://vznjs.github.io/vx/blog/the-small-things/)
|
|
129
126
|
- **Task typed as a verb** — `vx build app` answers with the exact `vx run` command that does it. [page](https://vznjs.github.io/vx/features/task-as-verb/) · post: [The small things](https://vznjs.github.io/vx/blog/the-small-things/)
|
|
@@ -169,7 +166,7 @@ config key or an environment variable is missing here.
|
|
|
169
166
|
- **Remote cache and execution** (`@vzn/vx-reapi`, `exec.remote`) — Bazel REAPI cache and workers; the scheduler stays here. [page](https://vznjs.github.io/vx/features/remote-execution/) · post: [Remote execution without moving the scheduler](https://vznjs.github.io/vx/blog/remote-execution/)
|
|
170
167
|
- **OpenTelemetry** (`@vzn/vx-otel`) — each run exported to your OpenTelemetry backend, never breaking it. [page](https://vznjs.github.io/vx/features/opentelemetry/) · post: [Observability that cannot break a run](https://vznjs.github.io/vx/blog/telemetry-never-breaks-a-run/)
|
|
171
168
|
- **vx history** (`@vzn/vx-schedule-history`, `vx history`) — what the scheduler learned per task. [page](https://vznjs.github.io/vx/features/vx-history/) · post: [A scheduler that learns from your runs](https://vznjs.github.io/vx/blog/a-scheduler-that-learns/)
|
|
172
|
-
- **Setup and teardown hooks** (`setup`, `teardown`) — plugin code around the run, bounded by a timeout. [page](https://vznjs.github.io/vx/features/setup-teardown/) · post: [Extend vx in an afternoon](https://vznjs.github.io/vx/blog/extend-vx/)
|
|
169
|
+
- **Setup and teardown hooks** (`setup`, `teardown`, `RunReport`, `ctx.cache.getRun`) — plugin code around the run, bounded by a timeout; on a run that writes a remote, vx keeps failed tasks' logs and outputs and uncached tasks' logs there, and `teardown` gets the run, its CI job and every task with the names to read them by, which a plugin verb reads back through its read-only `ctx.cache`. [page](https://vznjs.github.io/vx/features/setup-teardown/) · post: [Extend vx in an afternoon](https://vznjs.github.io/vx/blog/extend-vx/)
|
|
173
170
|
- **REAPI TLS, mTLS and headers** — connect to hosted servers such as BuildBuddy the way Bazel does. [page](https://vznjs.github.io/vx/features/reapi-tls/) · post: [A remote server you can trust in production](https://vznjs.github.io/vx/blog/reapi-in-production/)
|
|
174
171
|
- **REAPI execution records** — a repeat remote execution skips the worker and replays outputs and stdout. [page](https://vznjs.github.io/vx/features/reapi-action-cache/) · post: [A remote server you can trust in production](https://vznjs.github.io/vx/blog/reapi-in-production/)
|
|
175
172
|
- **REAPI verified downloads and deadlines** — a corrupt blob or a wedged server degrades to a miss, never a hang. [page](https://vznjs.github.io/vx/features/reapi-safety/) · post: [A remote server you can trust in production](https://vznjs.github.io/vx/blog/reapi-in-production/)
|
|
@@ -177,3 +174,4 @@ config key or an environment variable is missing here.
|
|
|
177
174
|
- **OTel live export** (`otel({ live })`) — spans and metrics stream as tasks end, so a dashboard follows a CI run live. [page](https://vznjs.github.io/vx/features/otel-live/) · post: [Watch a CI run while it runs](https://vznjs.github.io/vx/blog/otel-live/)
|
|
178
175
|
- **Memory-aware admission** (`@vzn/vx-schedule-history`) — tasks are packed by the peak memory learned from past runs. [page](https://vznjs.github.io/vx/features/memory-admission/) · post: [A scheduler that learns from your runs](https://vznjs.github.io/vx/blog/a-scheduler-that-learns/)
|
|
179
176
|
- **CI timings file** (`@vzn/vx-schedule-history`, `file`) — one JSON file of learned task times a CI cache carries between runners, so a fresh runner orders by real times. [page](https://vznjs.github.io/vx/features/critical-path/) · post: [Carry the scheduler's memory between CI runners](https://vznjs.github.io/vx/blog/ci-timings-file/)
|
|
177
|
+
- **Shared timings** (`@vzn/vx-schedule-history`, `defaultBranch`) — CI on the default branch writes task timings to the remote cache; a branch with none imports its merge-base's. Plugins keep their own entries there through `ctx.cache`. [page](https://vznjs.github.io/vx/features/critical-path/)
|
package/docs/patterns.md
CHANGED
|
@@ -161,19 +161,17 @@ Turbo-aware cache server can transit our blobs unchanged.
|
|
|
161
161
|
| `--concurrency <n>` | Turbo | `src/cli/run.ts` |
|
|
162
162
|
| `--no-cache` (all off) / `--force` (reads off, writes on) — distinct, not synonyms | Turbo-adjacent | `src/cli/run.ts` |
|
|
163
163
|
| `--dry` / `--dry=json` (plan output) | Turbo | `src/orchestrator/plan.ts` |
|
|
164
|
-
| `--graph[=<path>]` (DOT) | Turbo + Nx | `src/cli/plan-format.ts` |
|
|
165
|
-
| `--summarize[=<path>]` (per-run JSON) | Turbo | `src/orchestrator/run-artifacts.ts` |
|
|
166
164
|
| `--profile[=<path>]` (Chrome-trace) | Turbo | `src/orchestrator/run-artifacts.ts` |
|
|
167
165
|
| `--affected[=<base>]` | Turbo + Nx | `src/workspace/affected.ts` |
|
|
168
166
|
| `watch <task>` subcommand | Turbo + Nx | `src/cli/watch.ts` |
|
|
169
167
|
|
|
170
168
|
### Output presentation
|
|
171
169
|
|
|
172
|
-
| Pattern | Source | vx source
|
|
173
|
-
| ---------------------------------------------------- | ------------------------------------------------ |
|
|
174
|
-
| Framed per-task blocks (`┌─ … └─`) | Turbo | `src/
|
|
175
|
-
| End-of-run summary footer (task/cache meters + time) | Turbo-adjacent (vx renders meters, not a banner) | `src/
|
|
176
|
-
| Per-task output buffered until task finishes | Turbo | `src/
|
|
170
|
+
| Pattern | Source | vx source |
|
|
171
|
+
| ---------------------------------------------------- | ------------------------------------------------ | --------------------------------------------- |
|
|
172
|
+
| Framed per-task blocks (`┌─ … └─`) | Turbo | `src/report/framed-output.ts` |
|
|
173
|
+
| End-of-run summary footer (task/cache meters + time) | Turbo-adjacent (vx renders meters, not a banner) | `src/report/summary.ts` |
|
|
174
|
+
| Per-task output buffered until task finishes | Turbo | `src/report/framed-output.ts` ("Turbo-style") |
|
|
177
175
|
|
|
178
176
|
(There is no `>>> FULL TURBO`-style all-cached banner — a fully-green
|
|
179
177
|
cache meter carries the message.)
|
package/docs/schema.md
CHANGED
|
@@ -376,7 +376,7 @@ for it to exit. Instead it considers the task "ready":
|
|
|
376
376
|
The trailing partial line is tested too, so prompt-style banners
|
|
377
377
|
without a newline (`printf 'Listening on :3000'`) count, and so does
|
|
378
378
|
output read up to 250 ms after the shell exits. A server
|
|
379
|
-
not ready after 10 s
|
|
379
|
+
not ready after 10 s is said once, naming
|
|
380
380
|
the pattern it waits for, and whether `exec.timeout` bounds the wait.
|
|
381
381
|
|
|
382
382
|
```ts
|
|
@@ -609,7 +609,7 @@ replays, the command a cache entry stores (what `vx why` prints and a
|
|
|
609
609
|
remote cache receives), the `$ command` line, telemetry records,
|
|
610
610
|
`vx show`, the hashes `vx why` gives for such a variable in
|
|
611
611
|
`cache.inputs.env` (its value, unsalted: the row names it and its change), an executor's error, a plugin's warning or failure (a remote's reply; the failure masked in the error `run()` rejects with), a failed `cache.inputs` runtime probe's error (its command and output), and the run's own invocation line that `vx last` prints (a
|
|
612
|
-
secret passed after `--`)
|
|
612
|
+
secret passed after `--`). So are every string of a
|
|
613
613
|
task `vx show` prints (a runtime probe, `readyWhen`, the description),
|
|
614
614
|
the description `--dry` and the task picker print, a runtime probe's
|
|
615
615
|
command as the run history stores it and `vx why` names its row (two
|
|
@@ -676,8 +676,8 @@ Semantics:
|
|
|
676
676
|
edge from a `package.json`) and the cross-project `pkg#task` edges.
|
|
677
677
|
With no plugin returning `deps` the workspace has no edge source and
|
|
678
678
|
a `'^name'` is refused (`VX_E_DEPENDS_ON`: "`^build` needs project
|
|
679
|
-
edges; add pnpm()/bun()/npm()/yarn()
|
|
680
|
-
`deps`"): it would resolve to nothing and fold no upstream into the
|
|
679
|
+
edges; add pnpm()/bun()/npm()/yarn() and install so its lockfile
|
|
680
|
+
exists, or a plugin that returns `deps`"): it would resolve to nothing and fold no upstream into the
|
|
681
681
|
key. With one, a project with no deps is a leaf; each path stops at the first dep
|
|
682
682
|
that declares the task and an edge is added to it (Turbo/Nx
|
|
683
683
|
direct-deps parity). The holder's own `dependsOn` is responsible
|
|
@@ -881,7 +881,7 @@ lockfile change when a lockfile plugin (`@vzn/vx-lockfile`) is declared.
|
|
|
881
881
|
Always applied to every glob pass (regardless of what you wrote):
|
|
882
882
|
|
|
883
883
|
- **gitignore filter** — workspace-root + project `.gitignore`.
|
|
884
|
-
- **Always-ignored** — `.git/**`, `.vx/cache/**`,
|
|
884
|
+
- **Always-ignored** — `.git/**`, `.vx/cache/**`,
|
|
885
885
|
`.vx/projects.lock.json`, `vx.lock.json`, `*.bun-build`, and Bun's cross-compile extraction
|
|
886
886
|
directory `.<16 hex>-<8 hex>.tmp/**`, and vx's own restore temp
|
|
887
887
|
`.vx-tmp-*`, at any depth.
|
|
@@ -892,8 +892,8 @@ Always applied to every glob pass (regardless of what you wrote):
|
|
|
892
892
|
itself via its own output. A path an output `!` entry takes back is
|
|
893
893
|
no output, so it stays an input (A-44). Another task's outputs are
|
|
894
894
|
not excluded for you: an input glob that can match them is refused
|
|
895
|
-
while `rules.upfrontKeys` is on (X-54)
|
|
896
|
-
`['**/*', '!dist/**']
|
|
895
|
+
while `rules.upfrontKeys` is on (X-54), unless git ignores them
|
|
896
|
+
whole. Write the exclusion, `['**/*', '!dist/**']`, or ignore `dist/`. An input entry the task's OWN outputs take
|
|
897
897
|
back whole is always refused (X-55): vx removes outputs before a run,
|
|
898
898
|
so a formatter declaring `src/**` as both would delete its sources. A
|
|
899
899
|
task that rewrites files in place declares no outputs.
|
|
@@ -937,7 +937,7 @@ backslash separator (`src\**`, `src\*.ts`) or a drive (`C:\src\**`,
|
|
|
937
937
|
backslash stays an escape.
|
|
938
938
|
|
|
939
939
|
Still applied: the always-ignored set (`.git/**`, `.vx/cache/**`,
|
|
940
|
-
|
|
940
|
+
`.vx/projects.lock.json`, `vx.lock.json`, `*.bun-build`, `.<16 hex>-<8 hex>.tmp/**`, `.vx-tmp-*`),
|
|
941
941
|
untracked files under `node_modules/`, and the task's own declared
|
|
942
942
|
outputs, `outputs.workspaceFiles` and the `outputs.files` its globs reach
|
|
943
943
|
in its own project (a task never invalidates itself).
|
|
@@ -1186,10 +1186,10 @@ run is a no-op too.
|
|
|
1186
1186
|
|
|
1187
1187
|
**`clean: false`** keeps the outputs on a miss instead of wiping them
|
|
1188
1188
|
first, for a tool that reads its own last output (tsc's
|
|
1189
|
-
`.tsbuildinfo`).
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
still restores bit-identically. Omitted → the workspace's
|
|
1189
|
+
`.tsbuildinfo`). It opts out of the clean-tree guarantee: the save
|
|
1190
|
+
stores every file the outputs match after the run, so a file an older
|
|
1191
|
+
build left behind is cached and restored on every machine. A retry
|
|
1192
|
+
still starts clean, and a hit still restores bit-identically. Omitted → the workspace's
|
|
1193
1193
|
`cache.outputs.clean`, else `true`.
|
|
1194
1194
|
|
|
1195
1195
|
A **`!` entry takes a path back** from what the positive globs select
|
|
@@ -1259,7 +1259,11 @@ and so are `dist//**` and `dist/./app.js` (item 441) — and a literal
|
|
|
1259
1259
|
entry is read as the file OR its whole tree, the same rule the resolver
|
|
1260
1260
|
uses, so `dist` collides with `dist/app.js` (item 442). A whole subtree
|
|
1261
1261
|
collides with any glob whose literal head lies inside it: `dist/**` with
|
|
1262
|
-
`dist/extra/**` or `dist/*.js` (item 941).
|
|
1262
|
+
`dist/extra/**` or `dist/*.js` (item 941). Two globs a path built from
|
|
1263
|
+
either one matches are one too: `**/*` and `**/dist/**` both match
|
|
1264
|
+
`x/dist/x`. A pair is no overlap where one task's `!` output entry
|
|
1265
|
+
takes the other's glob back whole: `['**/dist', '!types/**']` beside
|
|
1266
|
+
`types/**` (a `!` entry is never cleaned or captured). Globs that only _might_
|
|
1263
1267
|
overlap (`dist/*` and `dist/sub/**`) are let through; there, last
|
|
1264
1268
|
restore wins. A workspace output is also compared with every other
|
|
1265
1269
|
project's `files` outputs, read from the root: `packages/b/dist/a.txt`
|
|
@@ -1642,9 +1646,6 @@ export default defineWorkspace({
|
|
|
1642
1646
|
affectedBase: 'origin/main',
|
|
1643
1647
|
schedule: 'most-work',
|
|
1644
1648
|
continue: 'deps-ok',
|
|
1645
|
-
killGrace: '2s',
|
|
1646
|
-
teardownTimeout: '3s',
|
|
1647
|
-
readyNotice: '10s',
|
|
1648
1649
|
rules: {
|
|
1649
1650
|
exclusiveOutputs: true,
|
|
1650
1651
|
upfrontKeys: true,
|
|
@@ -1676,7 +1677,7 @@ task's value over all of them; the input-stability variables are the one
|
|
|
1676
1677
|
exception, overriding every task for the run. A duration carries its
|
|
1677
1678
|
unit (`'500ms'`, `'30s'`, `'10m'`, `'2h'`, `'30d'`), and a bare number is
|
|
1678
1679
|
refused naming the forms with units; a size carries one too (`'10GB'`).
|
|
1679
|
-
`debug.timing`, `debug.dumpable`, `config.workerTimeout` and `run.outputLogs` are read
|
|
1680
|
+
`debug.timing`, `debug.watch`, `debug.dumpable`, `config.workerTimeout` and `run.outputLogs` are read
|
|
1680
1681
|
before the workspace loads, so they have a variable (and a flag) only.
|
|
1681
1682
|
None is folded into a cache key. `vx info` lists every setting not at its
|
|
1682
1683
|
default and where it came from.
|
|
@@ -1685,35 +1686,33 @@ default and where it came from.
|
|
|
1685
1686
|
|
|
1686
1687
|
<!-- settings table: generated by tests/settings.test.ts -->
|
|
1687
1688
|
|
|
1688
|
-
| Setting | Variable | Flag
|
|
1689
|
-
| ---------------------------------------------- | ----------------------------------- |
|
|
1690
|
-
| `run.concurrency` | `VX_RUN_CONCURRENCY` | `--concurrency`
|
|
1691
|
-
| `run.schedule` | `VX_RUN_SCHEDULE` | `--schedule`
|
|
1692
|
-
| `run.affectedBase` | `VX_RUN_AFFECTED_BASE` | —
|
|
1693
|
-
| `run.branch` (variable or flag only) | `VX_RUN_BRANCH` | `--branch`
|
|
1694
|
-
| `run.timeout` | `VX_RUN_TIMEOUT` | `--timeout`
|
|
1695
|
-
| `run.retries` | `VX_RUN_RETRIES` | `--retries`
|
|
1696
|
-
| `run.continue` | `VX_RUN_CONTINUE` | `--continue`
|
|
1697
|
-
| `run.outputLogs` (variable or flag only) | `VX_RUN_OUTPUT_LOGS` | `--output-logs`
|
|
1698
|
-
| `run.
|
|
1699
|
-
| `run.
|
|
1700
|
-
| `
|
|
1701
|
-
| `
|
|
1702
|
-
| `
|
|
1703
|
-
| `cache.
|
|
1704
|
-
| `cache.
|
|
1705
|
-
| `cache.
|
|
1706
|
-
| `cache.
|
|
1707
|
-
| `cache.
|
|
1708
|
-
| `cache.
|
|
1709
|
-
| `
|
|
1710
|
-
| `
|
|
1711
|
-
| `
|
|
1712
|
-
| `
|
|
1713
|
-
| `watch
|
|
1714
|
-
| `
|
|
1715
|
-
| `debug.timing` (variable or flag only) | `VX_DEBUG_TIMING` | — | true or false | false | Print the run's stage timings to stderr. |
|
|
1716
|
-
| `debug.dumpable` (variable or flag only) | `VX_DEBUG_DUMPABLE` | — | true or false | false | Linux: keep vx dumpable, so strace or a debugger can read its memory and `/proc/<pid>/fd`, and an unsandboxed task its env. |
|
|
1689
|
+
| Setting | Variable | Flag | Value | Default | What it does |
|
|
1690
|
+
| ---------------------------------------------- | ----------------------------------- | ------------------ | ----------------------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1691
|
+
| `run.concurrency` | `VX_RUN_CONCURRENCY` | `--concurrency` | a positive integer, or a share of the cores like '50%' | the cores this process may use | Tasks at once: a positive integer, or a share of the cores (`'50%'`). |
|
|
1692
|
+
| `run.schedule` | `VX_RUN_SCHEDULE` | `--schedule` | one of 'most-work', 'critical-path', 'direct-dependents', 'ready-order' | most-work | Which ready task starts first when there are more than workers. |
|
|
1693
|
+
| `run.affectedBase` | `VX_RUN_AFFECTED_BASE` | — | a non-blank string | origin/HEAD, then the trunk, else HEAD~1 | The git ref a bare `--affected` compares with. |
|
|
1694
|
+
| `run.branch` (variable or flag only) | `VX_RUN_BRANCH` | `--branch` | a non-blank string | git's branch, then the CI provider's | The branch a run records in its history and forecasts from. Flag and env only: a committed branch would be wrong on every other branch. |
|
|
1695
|
+
| `run.timeout` | `VX_RUN_TIMEOUT` | `--timeout` | a duration like '500ms', '30s' or '5m', at most 24 days | none | A task's time limit, for tasks without their own `exec.timeout` (`'30m'`). A task's own `exec.timeout` beats it. |
|
|
1696
|
+
| `run.retries` | `VX_RUN_RETRIES` | `--retries` | a non-negative integer | 0 | Re-runs of a failed task, for tasks without their own `exec.retries`. A task's own `exec.retries` beats it. |
|
|
1697
|
+
| `run.continue` | `VX_RUN_CONTINUE` | `--continue` | one of 'never', 'deps-ok', 'always' | deps-ok | What a failed task takes down: `never` stops the run, `deps-ok` skips its dependents, `always` runs them too. |
|
|
1698
|
+
| `run.outputLogs` (variable or flag only) | `VX_RUN_OUTPUT_LOGS` | `--output-logs` | one of 'full', 'errors-only', 'hash-only', 'none' | `full` on CI, else by what the run selects | Which task output the run prints. Chosen before the workspace loads, so flag and env only. |
|
|
1699
|
+
| `run.rules.exclusiveOutputs` | `VX_RUN_RULES_EXCLUSIVE_OUTPUTS` | — | true or false | true | Refuse two tasks whose outputs overlap even when an edge orders them. |
|
|
1700
|
+
| `run.rules.upfrontKeys` | `VX_RUN_RULES_UPFRONT_KEYS` | — | true or false | true | Refuse a task whose inputs can match another task's outputs. |
|
|
1701
|
+
| `cache.dir` | `VX_CACHE_DIR` | `--cache-dir` | a non-blank string | .vx/cache, entries in ~/.vx/<repo>/cache | Where the cache lives, relative to the workspace root; named, it holds the whole cache. |
|
|
1702
|
+
| `cache.retention.maxSize` | `VX_CACHE_RETENTION_MAX_SIZE` | — | a size like '500MB' or '10GB' | none | Evict least-recently-used entries at each run's end until the cache is under this (`'10GB'`). |
|
|
1703
|
+
| `cache.retention.olderThan` | `VX_CACHE_RETENTION_OLDER_THAN` | — | a duration like '45s', '12h' or '30d' | none | Evict entries unused for this long at each run's end (`'30d'`). |
|
|
1704
|
+
| `cache.policy` | `VX_CACHE_POLICY` | `--cache-policy` | a non-blank string | every layer reads and writes | Which layers a run reads and writes (`'local:rw,remote:r'`); `--no-cache` and `--force` apply on top. |
|
|
1705
|
+
| `cache.scope` | `VX_CACHE_SCOPE` | `--cache-scope` | a non-blank string | none (the default keys) | Where cache writes land (`'pr-123'`): reads try the default key, then the scope's. |
|
|
1706
|
+
| `cache.download` | `VX_CACHE_DOWNLOAD` | `--cache-download` | one of 'all', 'toplevel', 'none' | all | Which remote hits land on disk: every one, only the requested tasks, or none. |
|
|
1707
|
+
| `cache.inputStability.strategy` | `VX_CACHE_INPUT_STABILITY_STRATEGY` | — | one of 'immutable', 'mutable', 'unchecked' | immutable | What a write to an input during the command means for the save, for tasks without their own. A task's own `cache.inputStability.strategy` beats it. |
|
|
1708
|
+
| `cache.inputStability.severity` | `VX_CACHE_INPUT_STABILITY_SEVERITY` | — | one of 'warn', 'error' | warn | Whether a skipped save warns or fails the task, for tasks without their own. A task's own `cache.inputStability.severity` beats it. |
|
|
1709
|
+
| `cache.outputs.clean` | — | — | true or false | true | Remove a task's declared outputs before it runs on a miss, for tasks without their own. A task's own `cache.outputs.clean` beats it. |
|
|
1710
|
+
| `lock.reviewFiles` | `VX_LOCK_REVIEW_FILES` | — | true or false | true | `vx lock` writes each project's resolved config, pretty, to `vx.lock.json` beside its `vx.config`, for review; vx never reads it. |
|
|
1711
|
+
| `watch.poll` | `VX_WATCH_POLL` | `vx watch --poll` | true or false | false | Poll for changes from the start instead of the OS watcher. |
|
|
1712
|
+
| `config.workerTimeout` (variable or flag only) | `VX_CONFIG_WORKER_TIMEOUT` | — | a duration like '500ms', '30s' or '5m', at most 24 days | 30s | How long one config evaluation may take. |
|
|
1713
|
+
| `debug.timing` (variable or flag only) | `VX_DEBUG_TIMING` | — | true or false | false | Print the run's stage timings to stderr. |
|
|
1714
|
+
| `debug.watch` (variable or flag only) | `VX_DEBUG_WATCH` | — | true or false | false | `vx watch`: say on stderr each time the loop arms, with the projects it watches. |
|
|
1715
|
+
| `debug.dumpable` (variable or flag only) | `VX_DEBUG_DUMPABLE` | — | true or false | false | Linux: keep vx dumpable, so strace or a debugger can read its memory and `/proc/<pid>/fd`, and an unsandboxed task its env. |
|
|
1717
1716
|
|
|
1718
1717
|
<!-- /settings table -->
|
|
1719
1718
|
|
|
@@ -1734,9 +1733,6 @@ interface RunSettings {
|
|
|
1734
1733
|
timeout?: Duration
|
|
1735
1734
|
retries?: number
|
|
1736
1735
|
continue?: 'never' | 'deps-ok' | 'always'
|
|
1737
|
-
killGrace?: Duration
|
|
1738
|
-
teardownTimeout?: Duration
|
|
1739
|
-
readyNotice?: Duration
|
|
1740
1736
|
/** Graph rules `vx lock` checks, never a run; each on unless set to false. */
|
|
1741
1737
|
rules?: { exclusiveOutputs?: boolean; upfrontKeys?: boolean; dependencies?: DependencyRule[] }
|
|
1742
1738
|
}
|
|
@@ -1774,11 +1770,6 @@ interface CacheSettings {
|
|
|
1774
1770
|
- **`run.continue`** — what a failed task takes down: `never` stops
|
|
1775
1771
|
dispatch, `deps-ok` (the default) skips its dependents, `always` runs
|
|
1776
1772
|
them (`docs/cli.md` § Failure propagation).
|
|
1777
|
-
- **`run.killGrace`**, **`run.teardownTimeout`**, **`run.readyNotice`**
|
|
1778
|
-
— the SIGTERM → SIGKILL grace (2 s), the bound on each plugin's
|
|
1779
|
-
end-of-run flush and teardown (3 s; there is no "no limit"), and how
|
|
1780
|
-
long a persistent task may wait for `readyWhen` before vx says what it
|
|
1781
|
-
waits for (10 s).
|
|
1782
1773
|
- **`run.rules`** — checked by `vx lock` and `vx lock --check` only;
|
|
1783
1774
|
no run checks them.
|
|
1784
1775
|
- **`cache.dir`** — unset, the workspace keeps its index and history in
|
|
@@ -1904,7 +1895,17 @@ false in .vx/workspace.ts to let it wait for its producer.` Such a key
|
|
|
1904
1895
|
the schedule (`caching.md` § Local restore tier). The upstream's key
|
|
1905
1896
|
already reaches the reader through `dependsOn`. A `!` entry that
|
|
1906
1897
|
takes the whole output back clears it, and an output the reader's
|
|
1907
|
-
`!` entries take back no longer holds its key back either.
|
|
1898
|
+
`!` entries take back no longer holds its key back either. Nor does
|
|
1899
|
+
an output git ignores whole: a key reads only what git lists, so
|
|
1900
|
+
`**/*` beside a gitignored `**/dist/**` passes and keys up front. Git
|
|
1901
|
+
is asked, never a `.gitignore` read: `git check-ignore` on the
|
|
1902
|
+
output's directory (for `**/dist/**`, `dist/` and a fresh
|
|
1903
|
+
`__vx_probe__/dist/`), and no tracked or listed file may match it,
|
|
1904
|
+
so a tracked output is still refused. A glob no few paths stand for
|
|
1905
|
+
(`*.js`) is refused as before. `vx lock` asks once for every
|
|
1906
|
+
overlapped output; a run asks once beside its git walk for the
|
|
1907
|
+
stability gate, so a rule changed after the lock keys the reader
|
|
1908
|
+
late until the next `vx lock` refuses it. A task's
|
|
1908
1909
|
own outputs, a task with no `cache`, and a group are exempt. Off,
|
|
1909
1910
|
the key waits for its producer, as before.
|
|
1910
1911
|
- **`dependencies`** — which workspace projects a project may depend
|
|
@@ -2263,16 +2264,22 @@ opens it on click), and the lines up to it with a caret under the field
|
|
|
2263
2264
|
(`util/config-frame.ts`):
|
|
2264
2265
|
|
|
2265
2266
|
```
|
|
2266
|
-
|
|
2267
|
+
✗ vx lock lock not written
|
|
2267
2268
|
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2269
|
+
packages/b/vx.config.ts:4:15
|
|
2270
|
+
tasks.build.exec has unknown field "comand"
|
|
2271
|
+
allowed: …
|
|
2272
|
+
|
|
2273
|
+
2 | tasks: {
|
|
2274
|
+
3 | build: {
|
|
2275
|
+
> 4 | exec: { comand: 'mkdir -p dist' },
|
|
2276
|
+
| ^
|
|
2277
|
+
|
|
2278
|
+
fix use command
|
|
2272
2279
|
```
|
|
2273
2280
|
|
|
2274
2281
|
A field the file does not hold (a required one missing, or one a plugin
|
|
2275
|
-
set) prints the
|
|
2282
|
+
set) prints without the frame. The table below lists the messages
|
|
2276
2283
|
a user meets most:
|
|
2277
2284
|
|
|
2278
2285
|
| Symptom | Cause |
|