@vzn/vx 0.0.15 → 0.0.18
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/README.md +91 -130
- package/index.ts +10 -0
- package/launcher.mjs +10 -11
- package/package.json +19 -5
- package/plugins/local-cache/index.ts +2 -0
- package/plugins/local-executor/index.ts +2 -0
- package/plugins/schedule-history/index.ts +2 -0
- package/src/bin.ts +2 -2
- package/src/cache/archive.ts +557 -0
- package/src/cache/cache.ts +929 -250
- package/src/cache/cas-backend.ts +20 -2
- package/src/cache/chained-cache.ts +202 -0
- package/src/cache/digest.ts +0 -15
- package/src/cache/index.ts +13 -3
- package/src/cache/inputs.ts +445 -41
- package/src/cache/layered-cache.ts +129 -30
- package/src/cache/tar-stream.ts +358 -0
- package/src/cli/cache.ts +36 -10
- package/src/cli/help.ts +167 -128
- package/src/cli/index.ts +74 -43
- package/src/cli/info.ts +30 -0
- package/src/cli/last.ts +140 -0
- package/src/cli/migrate-emit.ts +21 -0
- package/src/cli/migrate-nx.ts +23 -0
- package/src/cli/migrate-scripts.ts +127 -0
- package/src/cli/migrate-turbo.ts +43 -6
- package/src/cli/migrate.ts +119 -33
- package/src/cli/plan-format.ts +58 -3
- package/src/cli/plugin-commands.ts +96 -0
- package/src/cli/prune.ts +291 -0
- package/src/cli/run.ts +272 -80
- package/src/cli/upgrade.ts +7 -6
- package/src/cli/watch.ts +259 -61
- package/src/cli/why.ts +193 -0
- package/src/config.ts +40 -23
- package/src/exec/env.ts +7 -1
- package/src/exec/executor.ts +239 -0
- package/src/exec/index.ts +19 -1
- package/src/exec/runner.ts +116 -29
- package/src/exec/sandbox-runtime.ts +194 -24
- package/src/graph/index.ts +3 -1
- package/src/graph/scheduler.ts +92 -18
- package/src/graph/task-graph.ts +220 -6
- package/src/index.ts +82 -84
- package/src/orchestrator/deferred-outputs.ts +144 -0
- package/src/orchestrator/download-policy.ts +171 -0
- package/src/orchestrator/events.ts +30 -0
- package/src/orchestrator/execute-task.ts +328 -94
- package/src/orchestrator/failure-mode.ts +61 -0
- package/src/orchestrator/framed-output.ts +87 -35
- package/src/orchestrator/history.ts +78 -31
- package/src/orchestrator/index.ts +43 -90
- package/src/orchestrator/local-shortcircuit.ts +22 -0
- package/src/orchestrator/logger.ts +196 -14
- package/src/orchestrator/metrics.ts +57 -1376
- package/src/orchestrator/missing-plugin.ts +9 -0
- package/src/orchestrator/options.ts +22 -4
- package/src/orchestrator/plan.ts +144 -1
- package/src/orchestrator/plugin-host.ts +199 -119
- package/src/orchestrator/plugin.ts +144 -57
- package/src/orchestrator/prepare.ts +220 -69
- package/src/orchestrator/remote-prefetch.ts +27 -8
- package/src/orchestrator/resources.ts +20 -34
- package/src/orchestrator/run-artifacts.ts +41 -16
- package/src/orchestrator/run-context.ts +167 -29
- package/src/orchestrator/run-report.ts +73 -46
- package/src/orchestrator/run.ts +590 -122
- package/src/orchestrator/stable-keys.ts +74 -33
- package/src/orchestrator/status-line.ts +47 -8
- package/src/orchestrator/summary.ts +22 -1
- package/src/orchestrator/tally.ts +78 -35
- package/src/orchestrator/task-hash.ts +105 -11
- package/src/orchestrator/task-log-buffer.ts +291 -0
- package/src/orchestrator/telemetry-host.ts +24 -6
- package/src/orchestrator/telemetry.ts +181 -21
- package/src/orchestrator/upstream.ts +72 -31
- package/src/orchestrator/verify.ts +12 -2
- package/src/plugins/local-cache/index.ts +11 -0
- package/src/plugins/local-executor/index.ts +45 -0
- package/src/plugins/schedule-history/index.ts +109 -0
- package/src/util/edit-distance.ts +21 -0
- package/src/util/errors.ts +15 -1
- package/src/util/index.ts +7 -2
- package/src/util/num.ts +37 -0
- package/src/util/paths.ts +43 -0
- package/src/util/settle.ts +48 -0
- package/src/util/size.ts +5 -1
- package/src/util/tail.ts +66 -0
- package/src/util/timing.ts +63 -0
- package/src/workspace/affected.ts +142 -15
- package/src/workspace/config-cache.ts +304 -0
- package/src/workspace/config-eval.ts +210 -0
- package/src/workspace/config-imports.ts +161 -0
- package/src/workspace/filter.ts +22 -4
- package/src/workspace/fingerprint.ts +16 -1
- package/src/workspace/index.ts +15 -3
- package/src/workspace/lockfile.ts +13 -2
- package/src/workspace/nested-dirs.ts +21 -7
- package/src/workspace/package-graph.ts +23 -20
- package/src/workspace/project-loader.ts +503 -59
- package/src/workspace/workspace.ts +213 -72
- package/src/cache/tar.ts +0 -343
- package/src/cli/backend.ts +0 -23
- package/src/cli/mcp-rpc.ts +0 -292
- package/src/cli/mcp.ts +0 -92
- package/src/orchestrator/devframe-surface.ts +0 -74
- package/src/orchestrator/predict.ts +0 -106
- package/src/orchestrator/protocol.ts +0 -156
- package/src/orchestrator/run-state.ts +0 -145
- package/src/orchestrator/wire-render.ts +0 -92
- package/src/orchestrator/wire.ts +0 -212
package/README.md
CHANGED
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
**The fastest way to build a monorepo.**
|
|
4
4
|
|
|
5
5
|
vx runs your task graph, remembers every result, and never does the
|
|
6
|
-
same work twice. Fully cached runs finish in milliseconds —
|
|
7
|
-
across
|
|
8
|
-
|
|
6
|
+
same work twice. Fully cached runs finish in milliseconds — 76 ms
|
|
7
|
+
across 46 packages, 559 ms across a 1,090-package graph of 3,270 tasks,
|
|
8
|
+
where Turborepo takes 760 ms and Nx 3.59 s on the identical workspace —
|
|
9
|
+
and a cold build of that graph burns 34 s of CPU in vx, 73 s in Turborepo
|
|
10
|
+
and 114 minutes in Nx.
|
|
11
|
+
Measured, reproducible, on hardware you own
|
|
12
|
+
([benchmarks](docs/benchmarks.md)).
|
|
9
13
|
|
|
10
14
|
One binary. No daemon. No Node. Nothing to babysit.
|
|
11
15
|
|
|
@@ -15,9 +19,6 @@ architecture, caching, and the full CLI / config reference.
|
|
|
15
19
|
```sh
|
|
16
20
|
# From npm — ships the prebuilt standalone binary (no Bun required):
|
|
17
21
|
npm install -g @vzn/vx # or: pnpm add -g @vzn/vx · bun add -g @vzn/vx
|
|
18
|
-
|
|
19
|
-
# Or the zero-dependency install script (no Node/npm needed):
|
|
20
|
-
curl -fsSL https://raw.githubusercontent.com/vznjs/vx/main/install.sh | sh
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
```ts
|
|
@@ -45,6 +46,7 @@ export default defineProject({
|
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
```sh
|
|
49
|
+
vx init # scaffold vx.workspace.ts + a vx.config.ts per package from scripts
|
|
48
50
|
vx run build # cwd project + its workspace deps
|
|
49
51
|
vx run test --all # every project that declares `test`
|
|
50
52
|
vx run ci --affected # only what changed since origin/HEAD
|
|
@@ -52,58 +54,6 @@ vx watch lint # re-run on file changes
|
|
|
52
54
|
vx run build --dry # show the plan, don't execute
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
## Beyond a task runner — what shipped in the 2026-06 platform arc
|
|
56
|
-
|
|
57
|
-
vx now ships an **open platform**, not just a CLI. Every surface
|
|
58
|
-
below is built into the binary; no external services required.
|
|
59
|
-
|
|
60
|
-
```sh
|
|
61
|
-
vx mcp # Model Context Protocol server (stdio)
|
|
62
|
-
# — Claude Code / Cursor / Continue.dev talk to vx as a typed tool
|
|
63
|
-
|
|
64
|
-
npm i -g @vzn/vx-cloud # the service CLI — also a standalone binary, no Bun
|
|
65
|
-
vx-cloud serve --ui --open # team backend + embedded dashboard (token-authenticated)
|
|
66
|
-
vx-cloud agent --url https://ci.acme.dev # join a distributed-execution pool (Nx-Agents-style DTE)
|
|
67
|
-
vx-cloud connect https://ci.acme.dev # one-URL analytics + remote cache for every `vx run`
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Open platform highlights
|
|
71
|
-
|
|
72
|
-
- **Provider-neutral core.** `vx` runs tasks and nothing else — the
|
|
73
|
-
dashboard, remote cache, distribution, and telemetry all arrive via
|
|
74
|
-
PLUGINS declared in `vx.workspace.ts`. `@vzn/vx-cloud` is the
|
|
75
|
-
first-party one; anyone can write another against the same seams
|
|
76
|
-
(backend / cache / telemetry).
|
|
77
|
-
- **MCP for AI agents, twice.** `vx mcp` (stdio, reads your real
|
|
78
|
-
`cache.db`: `getCacheStats`, `getRunHistory`, `explainCacheKey`,
|
|
79
|
-
`whyDidThisRerun`) and `POST /mcp` on any `vx-cloud serve` — local
|
|
80
|
-
or hosted, behind the bearer token.
|
|
81
|
-
- **Provable cache correctness.** `vx run --verify` re-runs each
|
|
82
|
-
cacheable task and byte-compares outputs; `--verify=inputs` runs it
|
|
83
|
-
sandboxed against the declared inputs and names any undeclared read.
|
|
84
|
-
The only runner that PROVES a cache entry safe instead of hoping.
|
|
85
|
-
- **Distributed CI (DTE).** `vx-cloud agent` joins a session-keyed
|
|
86
|
-
pool; a `vx run` fans tasks out across same-commit agents, outputs
|
|
87
|
-
propagate through the shared artifact store, and a standing pool
|
|
88
|
-
multiplexes concurrent runs with fair scheduling.
|
|
89
|
-
- **Remote cache, one URL.** `vx-cloud connect <url>` wires analytics
|
|
90
|
-
ingest AND a Turborepo-wire-compatible artifact store (HMAC signing,
|
|
91
|
-
trusted/untrusted tiers derived from the token). Third-party Turbo
|
|
92
|
-
cache servers work via two env vars.
|
|
93
|
-
- **OTel CI/CD spans.** Declare `otel()` from `@vzn/vx-otel` in
|
|
94
|
-
`vx.workspace.ts` — OTLP/HTTP traces + metrics with ZERO
|
|
95
|
-
OpenTelemetry SDK dependency; runs flow to Grafana / Honeycomb /
|
|
96
|
-
Datadog, including `--verify` hermeticity verdicts as span status.
|
|
97
|
-
- **Dashboard embedded in the `vx-cloud` binary.** Runs, flamegraphs,
|
|
98
|
-
live run cockpit with the task DAG, per-task logs + artifacts,
|
|
99
|
-
cache-key diffs ("why did this re-run?"), flaky-task detection.
|
|
100
|
-
Nothing to build or install; Docker image on ghcr for hosting.
|
|
101
|
-
- **Predictive scheduling.** Opt in with `predictive: true` — the
|
|
102
|
-
scheduler reads run history and starts the longest expected critical
|
|
103
|
-
path first.
|
|
104
|
-
|
|
105
|
-
Each surface lives behind a design doc under `docs/design/`.
|
|
106
|
-
|
|
107
57
|
## A cache that actually understands your build
|
|
108
58
|
|
|
109
59
|
Every task runner caches. vx caches _correctly_ — and stops work
|
|
@@ -138,14 +88,10 @@ with the invariant that keeps it valid —
|
|
|
138
88
|
`--verify=inputs` sandboxes it against the declared inputs and fails
|
|
139
89
|
loud naming any undeclared read (completeness). No other runner can
|
|
140
90
|
prove a cache entry safe.
|
|
141
|
-
- **
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
bearer token — a fork-PR artifact can never feed a trusted build.
|
|
146
|
-
- **Corruption can't go live.** Artifacts are validated before they
|
|
147
|
-
enter the store (zstd-bomb and oversize downloads refused); bad
|
|
148
|
-
bytes degrade to a cache miss, never a crash.
|
|
91
|
+
- **Corruption can't go live.** A remote artifact is verified against
|
|
92
|
+
its content digest and validated before it enters the store
|
|
93
|
+
(zstd-bomb and oversize downloads refused); bad bytes degrade to a
|
|
94
|
+
cache miss, never a wrong hit and never a crash.
|
|
149
95
|
- **Clean exits.** SIGINT/SIGTERM reap every child process — no
|
|
150
96
|
orphaned dev servers in CI.
|
|
151
97
|
- **Readiness you can bound.** Persistent tasks gate downstream work
|
|
@@ -183,33 +129,59 @@ TypeScript config with real imports · task graph with `^task`
|
|
|
183
129
|
resolution that bridges packages without the task · multi-task runs
|
|
184
130
|
with one shared graph · pnpm-style filters and `--affected` ·
|
|
185
131
|
watch mode · `--dry` / `--graph` plans · persistent dev servers ·
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
`vx
|
|
190
|
-
|
|
191
|
-
turbo.json or an Nx graph.
|
|
132
|
+
retries, timeouts, `--continue` modes · per-layer cache control
|
|
133
|
+
(`--cache=local:r,remote:`) · `vx why` explains a re-run from the
|
|
134
|
+
persisted input fingerprints · `vx last` replays a recorded run ·
|
|
135
|
+
`vx prune` cuts a Docker-ready workspace subset · `vx info`,
|
|
136
|
+
`--summarize`, `--profile` Chrome traces, `--report` · `vx cache prune`
|
|
137
|
+
with TTL and size caps · `vx migrate` from turbo.json or an Nx graph.
|
|
138
|
+
|
|
139
|
+
## A pipeline with seams — plugins decide what happens
|
|
140
|
+
|
|
141
|
+
Core is the pipeline: discover projects, evaluate configs, build the
|
|
142
|
+
task graph, derive keys, schedule, execute, cache, observe. Plugins
|
|
143
|
+
declared in `vx.workspace.ts` hook each stage, Vite-style, on one
|
|
144
|
+
`VxPlugin` object:
|
|
145
|
+
|
|
146
|
+
| Stage | Hook | A plugin can… |
|
|
147
|
+
| --------- | -------------------------- | ----------------------------------------------------------- |
|
|
148
|
+
| workspace | `config(ws, ctx)` | edit the workspace config before it is used |
|
|
149
|
+
| project | `project(config, ctx)` | add, remove or rewrite a project's tasks (keyed like yours) |
|
|
150
|
+
| graph | `graph(nodes, ctx)` | add or drop edges, mark tasks requested |
|
|
151
|
+
| key | `key(task, ctx)` | fold extra material into the cache key (named in `vx why`) |
|
|
152
|
+
| schedule | `schedule(nodes, ctx)` | decide which ready task runs first |
|
|
153
|
+
| execute | `executor(ctx)` | decide WHERE a task's command runs (local, a REAPI worker) |
|
|
154
|
+
| store | `cache(ctx)` | decide where artifacts live (local, a shared remote) |
|
|
155
|
+
| observe | `telemetry(ctx)` / `setup` | receive every run record, or the raw event bus |
|
|
156
|
+
| cli | `commands` | add verbs to `vx` |
|
|
157
|
+
|
|
158
|
+
Core applies **no plugin by default** — even its own local executor and
|
|
159
|
+
cache are plugins your workspace declares, which is what makes "replace
|
|
160
|
+
any part" real rather than promised. First-party plugins:
|
|
161
|
+
[`@vzn/vx-reapi`](packages/vx-reapi) (Bazel Remote Execution API —
|
|
162
|
+
remote cache and remote execution against NativeLink, BuildBuddy,
|
|
163
|
+
Buildbarn or bazel-remote), [`@vzn/vx-otel`](packages/vx-otel)
|
|
164
|
+
(OpenTelemetry traces + metrics + logs, zero SDK deps),
|
|
165
|
+
[`@vzn/vx-github`](packages/vx-github) (Actions job summary + Checks
|
|
166
|
+
API), [`@vzn/vx-mcp`](packages/vx-mcp) (`vx mcp` — a read-only Model
|
|
167
|
+
Context Protocol server for AI coding agents, no SDK), and
|
|
168
|
+
`@vzn/vx/plugins/schedule-history` (order by learned critical path). Nothing distributed ships in this repo; the seams are how you
|
|
169
|
+
build it.
|
|
192
170
|
|
|
193
171
|
## How it compares
|
|
194
172
|
|
|
195
|
-
| | vx | Turborepo | Nx
|
|
196
|
-
| ------------------------- | --------------------------------------------------------------------- | ------------------------------ |
|
|
197
|
-
| Fully cached, 100 pkgs¹ | **144 ms** | 279 ms | 583+ ms
|
|
198
|
-
| Config | TypeScript, evaluated into the cache key | JSON (static) | JSON (static)
|
|
199
|
-
| Output ownership | **Strict** — wiped before exec AND restore | Additive (stale files survive) | Additive
|
|
200
|
-
| Clean-tree hashing | **Zero reads** (git index OIDs) | git OIDs | re-hash / daemon
|
|
201
|
-
| Daemon required for speed | **No** | Optional | Yes
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
| Dashboard SPA | **Yes** — embedded in `vx-cloud serve --ui`: runs, logs, DAG, flaky | No | Paid |
|
|
208
|
-
| Self-hosted cloud | **Yes** — `vx-cloud` binary or the ghcr Docker image; one stack | Vercel-only | No (proprietary) |
|
|
209
|
-
| Plugin API | **Yes** — backend / cache / telemetry seams | No | Yes (TS-tied) |
|
|
210
|
-
| Predictive scheduling | **Yes** (opt-in: `predictive: true`) | No | No |
|
|
211
|
-
| OTel CI/CD spans | **Yes** — `otel()` plugin, zero OTel-SDK deps | No | Paid |
|
|
212
|
-
| Install | **Single binary** — npm or 1 curl line, no Node/Bun needed | npm + Node | npm + Node |
|
|
173
|
+
| | vx | Turborepo | Nx |
|
|
174
|
+
| ------------------------- | --------------------------------------------------------------------- | ------------------------------ | ---------------- |
|
|
175
|
+
| Fully cached, 100 pkgs¹ | **144 ms** | 279 ms | 583+ ms |
|
|
176
|
+
| Config | TypeScript, evaluated into the cache key | JSON (static) | JSON (static) |
|
|
177
|
+
| Output ownership | **Strict** — wiped before exec AND restore | Additive (stale files survive) | Additive |
|
|
178
|
+
| Clean-tree hashing | **Zero reads** (git index OIDs) | git OIDs | re-hash / daemon |
|
|
179
|
+
| Daemon required for speed | **No** | Optional | Yes |
|
|
180
|
+
| Per-task sandbox | **Yes** — kernel-level, opt-in | No | No |
|
|
181
|
+
| Provable cache safety | **Yes** — `--verify` (determinism) + `--verify=inputs` (completeness) | No | No |
|
|
182
|
+
| Plugin API | **Yes** — executor / cache / telemetry seams | No | Yes (TS-tied) |
|
|
183
|
+
| OTel CI/CD spans | **Yes** — `otel()` plugin, zero OTel-SDK deps | No | Paid |
|
|
184
|
+
| Install | **Single binary** — npm or 1 curl line, no Node/Bun needed | npm + Node | npm + Node |
|
|
213
185
|
|
|
214
186
|
¹ Wall-clock, direct binaries, same machine and workspace — full
|
|
215
187
|
methodology and more scenarios in
|
|
@@ -259,7 +231,7 @@ Differences to know:
|
|
|
259
231
|
- vx requires `cache.inputs.files` when caching is enabled (no default `$TURBO_DEFAULT$`).
|
|
260
232
|
- vx defaults caching **off**; opt in per task by adding the `cache` block.
|
|
261
233
|
- Persistent tasks: `persistent: { readyWhen: 'regex' }` (Turbo uses just `persistent: true`).
|
|
262
|
-
- Remote
|
|
234
|
+
- Remote caching is a plugin, not a built-in — connect one and every `vx run` reads through it.
|
|
263
235
|
|
|
264
236
|
Side-by-side feature matrix + every known gap: [`docs/comparison.md`](./docs/comparison.md).
|
|
265
237
|
|
|
@@ -268,16 +240,16 @@ Side-by-side feature matrix + every known gap: [`docs/comparison.md`](./docs/com
|
|
|
268
240
|
`bin.ts → cli/index.ts` dispatches subcommands.
|
|
269
241
|
`orchestrator/run.ts:run()` calls `prepareRun()` which discovers the
|
|
270
242
|
workspace, loads configs, builds the package + task graph, opens the
|
|
271
|
-
cache (local SQLite + optional remote layer), and installs plugins
|
|
243
|
+
cache (local SQLite + an optional remote layer), and installs plugins
|
|
272
244
|
from `vx.workspace.ts`. The two-tier scheduler runs the graph in
|
|
273
245
|
topological order with bounded concurrency (confirmed cache hits
|
|
274
246
|
restore ahead of their deps); each task hits the cache (hash → get →
|
|
275
247
|
restore on hit; spawn → save on miss) or short-circuits as a group /
|
|
276
248
|
persistent. Every observation flows through one event bus — the
|
|
277
|
-
terminal renderer subscribes directly, and
|
|
249
|
+
terminal renderer subscribes directly, and plugins receive the
|
|
278
250
|
versioned telemetry contract (`TelemetryRecord` / `RunSummaryRecord`)
|
|
279
|
-
— that's how
|
|
280
|
-
Core never imports a plugin; the arrow only points plugin → core.
|
|
251
|
+
— that's how telemetry and cache plugins export without core knowing
|
|
252
|
+
them. Core never imports a plugin; the arrow only points plugin → core.
|
|
281
253
|
Every module has a docs page; every interface is a swappable seam.
|
|
282
254
|
|
|
283
255
|
Read [`docs/architecture.md`](./docs/architecture.md) for the module
|
|
@@ -285,9 +257,8 @@ map; the design record lives under [`docs/design/`](./docs/design/).
|
|
|
285
257
|
|
|
286
258
|
## Documentation
|
|
287
259
|
|
|
288
|
-
Full technical docs live under [`docs/`](./docs/)
|
|
289
|
-
|
|
290
|
-
**Core**
|
|
260
|
+
Full technical docs live under [`docs/`](./docs/) and on the
|
|
261
|
+
[documentation site](https://vznjs.github.io/vx/):
|
|
291
262
|
|
|
292
263
|
- [`docs/architecture.md`](./docs/architecture.md) — module map + data flow
|
|
293
264
|
- [`docs/schema.md`](./docs/schema.md) — every config field
|
|
@@ -297,52 +268,42 @@ Full technical docs live under [`docs/`](./docs/):
|
|
|
297
268
|
- [`docs/comparison.md`](./docs/comparison.md) — Turbo / Nx / vite-task feature matrix
|
|
298
269
|
- [`docs/modules/`](./docs/modules/) — one reference page per source module
|
|
299
270
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
- [`architecture-north-star-2026-06.md`](./docs/design/architecture-north-star-2026-06.md) — the unified vision
|
|
303
|
-
- [`architecture-review-2026-06.md`](./docs/design/architecture-review-2026-06.md) — review + applied checklist
|
|
304
|
-
- [`wire-protocol-2026-06.md`](./docs/design/wire-protocol-2026-06.md) — JSON-RPC 2.0 + OTel envelope (shipped)
|
|
305
|
-
- [`distributed-ci-2026-06.md`](./docs/design/distributed-ci-2026-06.md) — original coordinator/worker (superseded by `vx-cloud agent` DTE — `distributed-execution-2026-07.md`)
|
|
306
|
-
- [`vx-cloud-2026-06.md`](./docs/design/vx-cloud-2026-06.md) — original CF cloud (superseded by the standalone `vx-cloud` service)
|
|
307
|
-
- [`extension-protocol-2026-06.md`](./docs/design/extension-protocol-2026-06.md) — subscriber/inspector/driver/plugin (Phase 1 shipped)
|
|
308
|
-
- [`predictive-execution-2026-06.md`](./docs/design/predictive-execution-2026-06.md) — history-aware scheduling (Phase A-B shipped)
|
|
309
|
-
- [`docs/progress/implementation-log-2026-06.md`](./docs/progress/implementation-log-2026-06.md) — phase-by-phase narrative
|
|
271
|
+
The design record lives under [`docs/design/`](./docs/design/); the
|
|
272
|
+
maintainers' handoff is [`docs/STATUS.md`](./docs/STATUS.md).
|
|
310
273
|
|
|
311
274
|
## Status
|
|
312
275
|
|
|
313
276
|
**Pre-alpha.** The schema is settling; we bump `CACHE_VERSION` rather
|
|
314
|
-
than maintain back-compat.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
277
|
+
than maintain back-compat. **~2,500 core tests plus the package suites; CI green on every commit**;
|
|
278
|
+
the project dogfoods itself (`vx run ci`). Published on npm:
|
|
279
|
+
[`@vzn/vx`](https://www.npmjs.com/package/@vzn/vx) (a prebuilt standalone
|
|
280
|
+
binary).
|
|
318
281
|
|
|
319
282
|
Production readiness for the **core task runner**: the semantics are
|
|
320
|
-
solid. The main operational rough edge
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
|
325
|
-
|
|
|
326
|
-
|
|
|
327
|
-
|
|
|
328
|
-
| `vx
|
|
329
|
-
|
|
|
330
|
-
|
|
|
331
|
-
|
|
|
332
|
-
|
|
|
333
|
-
| Dashboard SPA (embedded in `vx-cloud`) | **iterating** | runs/logs/DAG/flaky live; data-first entity redesign in progress |
|
|
334
|
-
| OTel export (`@vzn/vx-otel`) | **shippable** | declare `otel()` in `vx.workspace.ts`; OTLP traces + metrics |
|
|
283
|
+
solid; it is dogfooded continuously. The main operational rough edge
|
|
284
|
+
is Windows (unsupported).
|
|
285
|
+
|
|
286
|
+
| Surface | Maturity | Notes |
|
|
287
|
+
| ------------------------------------------------ | -------------------- | ---------------------------------------------------------------------------- |
|
|
288
|
+
| Core task runner + caching | **production-ready** | dogfooded continuously; ~2,500 core tests + the package suites, green |
|
|
289
|
+
| `vx run --verify` (provable cache correctness) | **shippable** | determinism + input-completeness proofs; CI-gate recipe in docs |
|
|
290
|
+
| Plugin pipeline (9 hooks, `commands` included) | **shippable** | crash-isolated, re-validated; core's own executor + cache are plugins |
|
|
291
|
+
| `vx init` / `vx migrate` (scripts, Turbo, Nx) | **shippable** | one config per package, TODOs where a source cannot say |
|
|
292
|
+
| REAPI remote cache + execution (`@vzn/vx-reapi`) | **shippable** | Bazel AC + CAS + Execute; NativeLink / BuildBuddy / Buildbarn / bazel-remote |
|
|
293
|
+
| OTel export (`@vzn/vx-otel`) | **shippable** | OTLP traces + metrics + logs, zero SDK deps |
|
|
294
|
+
| GitHub Actions (`@vzn/vx-github`) | **shippable** | job summary + Checks API run |
|
|
295
|
+
| MCP server (`@vzn/vx-mcp`) | **shippable** | `vx mcp` — read-only tools for AI agents, no SDK |
|
|
335
296
|
|
|
336
297
|
## Development
|
|
337
298
|
|
|
338
299
|
```sh
|
|
339
300
|
git clone https://github.com/vznjs/vx && cd vx
|
|
340
301
|
bun install
|
|
341
|
-
bun src/bin.ts run ci
|
|
342
|
-
bun src/bin.ts run build
|
|
302
|
+
bun packages/vx/src/bin.ts run ci --all # lint + test + docs build, every package
|
|
303
|
+
bun packages/vx/src/bin.ts run build --filter @vzn/vx # cross-target binaries → packages/vx/dist/
|
|
343
304
|
```
|
|
344
305
|
|
|
345
|
-
vx is self-hosted: every dev task routes through `bun src/bin.ts run <task>` per
|
|
306
|
+
vx is self-hosted: every dev task routes through `bun packages/vx/src/bin.ts run <task>` per each package's own `vx.config.ts`. No `package.json` scripts; CI invokes vx directly. Start with [`docs/STATUS.md`](docs/STATUS.md) — the living handoff — and `CLAUDE.md`.
|
|
346
307
|
|
|
347
308
|
## License
|
|
348
309
|
|
package/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Root entry shim. Bun 1.4.0's `--compile` binaries resolve an on-disk
|
|
2
|
+
// package by directory convention (`<pkg>/index.ts`, `<pkg>/<subpath>/index.ts`)
|
|
3
|
+
// and ignore package.json `exports` / `main` (measured 2026-09-03: an
|
|
4
|
+
// entry of `./src/index.ts` resolved to the root `index.ts` regardless of the
|
|
5
|
+
// manifest, and a package with no root file was "not found"). Without this
|
|
6
|
+
// file every `import … from '@vzn/vx'` in a workspace config fails under the
|
|
7
|
+
// standalone binary. The exports map still wins everywhere else and points
|
|
8
|
+
// at the same module, so this is one extra hop for the binary and nothing
|
|
9
|
+
// for anyone else.
|
|
10
|
+
export * from './src/index.js'
|
package/launcher.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// npm launcher for a vx command — the entry a published package's `bin` points
|
|
3
3
|
// at. It execs the prebuilt standalone binary shipped as a per-platform
|
|
4
|
-
// optionalDependency, so end users get the command WITHOUT installing Bun.
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// optionalDependency, so end users get the command WITHOUT installing Bun.
|
|
5
|
+
// Everything is derived from this package's OWN name, read from the
|
|
6
|
+
// package.json sitting beside this file, so any package built by
|
|
7
|
+
// scripts/build-npm.ts can carry it:
|
|
7
8
|
//
|
|
8
|
-
// @vzn/vx
|
|
9
|
-
// @vzn/vx-cloud → platform pkg @vzn/vx-cloud-<key>, binary `vx-cloud`
|
|
9
|
+
// @vzn/vx → platform pkg @vzn/vx-<key>, binary `vx`
|
|
10
10
|
//
|
|
11
11
|
// Resolution order:
|
|
12
12
|
// 1. the matching <name>-<platform> optionalDependency's binary (the normal
|
|
@@ -26,11 +26,10 @@ const require = createRequire(import.meta.url)
|
|
|
26
26
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
27
27
|
const pkg = require('./package.json')
|
|
28
28
|
|
|
29
|
-
// Derive the platform-package prefix + binary basename from this package's
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// entry: `src/bin.ts` for vx, `src/cli/bin.ts` for vx-cloud.
|
|
29
|
+
// Derive the platform-package prefix + binary basename from this package's
|
|
30
|
+
// name. `base` is the unscoped name — the command AND the binary filename
|
|
31
|
+
// inside the platform package. `vxSourceEntry` (a package.json field) is the
|
|
32
|
+
// source-mode entry, `src/bin.ts` by default.
|
|
34
33
|
const name = pkg.name
|
|
35
34
|
const base = name.replace(/^@[^/]+\//, '')
|
|
36
35
|
const sourceEntry = pkg.vxSourceEntry ?? 'src/bin.ts'
|
|
@@ -86,7 +85,7 @@ process.stderr.write(
|
|
|
86
85
|
`${base}: no prebuilt binary for ${key}.\n` +
|
|
87
86
|
` Supported platforms: ${supported}.\n` +
|
|
88
87
|
` If your platform should be supported, reinstall so npm fetches the\n` +
|
|
89
|
-
` matching ${name}-${key} optionalDependency, or install Bun (>=1.
|
|
88
|
+
` matching ${name}-${key} optionalDependency, or install Bun (>=1.4) to\n` +
|
|
90
89
|
` run ${base} from source.\n`,
|
|
91
90
|
)
|
|
92
91
|
process.exit(1)
|
package/package.json
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "An open, extensible monorepo task runner.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
8
|
"types": "./src/index.ts",
|
|
9
9
|
"import": "./src/index.ts"
|
|
10
|
+
},
|
|
11
|
+
"./plugins/local-executor": {
|
|
12
|
+
"types": "./src/plugins/local-executor/index.ts",
|
|
13
|
+
"import": "./src/plugins/local-executor/index.ts"
|
|
14
|
+
},
|
|
15
|
+
"./plugins/local-cache": {
|
|
16
|
+
"types": "./src/plugins/local-cache/index.ts",
|
|
17
|
+
"import": "./src/plugins/local-cache/index.ts"
|
|
18
|
+
},
|
|
19
|
+
"./plugins/schedule-history": {
|
|
20
|
+
"types": "./src/plugins/schedule-history/index.ts",
|
|
21
|
+
"import": "./src/plugins/schedule-history/index.ts"
|
|
10
22
|
}
|
|
11
23
|
},
|
|
12
24
|
"types": "./src/index.ts",
|
|
@@ -17,15 +29,17 @@
|
|
|
17
29
|
"node": ">=18"
|
|
18
30
|
},
|
|
19
31
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
32
|
+
"@vzn/vx-linux-x64": "0.0.18",
|
|
33
|
+
"@vzn/vx-linux-arm64": "0.0.18",
|
|
34
|
+
"@vzn/vx-darwin-x64": "0.0.18",
|
|
35
|
+
"@vzn/vx-darwin-arm64": "0.0.18"
|
|
24
36
|
},
|
|
25
37
|
"dependencies": {
|
|
26
38
|
"@anthropic-ai/sandbox-runtime": "^0.0.56"
|
|
27
39
|
},
|
|
28
40
|
"files": [
|
|
41
|
+
"index.ts",
|
|
42
|
+
"plugins",
|
|
29
43
|
"src",
|
|
30
44
|
"launcher.mjs",
|
|
31
45
|
"README.md",
|
package/src/bin.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { run } from './cli/index.js'
|
|
3
|
-
import {
|
|
3
|
+
import { isUserError } from './util/index.js'
|
|
4
4
|
|
|
5
5
|
// Wrapped in an explicit async main so `bun build --compile` accepts
|
|
6
6
|
// the file. The compile target doesn't allow top-level await.
|
|
@@ -12,7 +12,7 @@ async function main(): Promise<void> {
|
|
|
12
12
|
// print the message only; the stack is noise the user can't act
|
|
13
13
|
// on. Everything else gets the full stack so internal bugs are
|
|
14
14
|
// debuggable.
|
|
15
|
-
if (err
|
|
15
|
+
if (isUserError(err)) {
|
|
16
16
|
process.stderr.write(`vx: ${err.message}\n`)
|
|
17
17
|
} else {
|
|
18
18
|
const message = err instanceof Error ? (err.stack ?? err.message) : String(err)
|