@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/caching.md
CHANGED
|
@@ -453,8 +453,17 @@ transitive dependant of one with it (their up-front keys fold a
|
|
|
453
453
|
preliminary key); a glob with no literal prefix reaches every project.
|
|
454
454
|
Before item 584 one such declaration emptied the tier graph-wide.
|
|
455
455
|
`rules.upfrontKeys` (on by default, X-54) refuses at load a task whose
|
|
456
|
-
input globs can match another task's declared outputs,
|
|
457
|
-
|
|
456
|
+
input globs can match another task's declared outputs, unless git
|
|
457
|
+
ignores those outputs whole, so the clauses on declared outputs fire
|
|
458
|
+
only with the rule off. An output git ignores whole is no reach either:
|
|
459
|
+
a key reads only what git lists, so a `**/*` reader beside a gitignored
|
|
460
|
+
`**/dist/**` producer keys up front, the same key before and after the
|
|
461
|
+
build. The run asks git once, beside its walk and only when a reader
|
|
462
|
+
reaches a same-project output: one `git check-ignore` over each such
|
|
463
|
+
output's directory (`dist/`, and a fresh `__vx_probe__/dist/` for a
|
|
464
|
+
glob that starts with `**`), and the walk's listing must hold no file
|
|
465
|
+
the glob matches (a tracked output, a directory a `!` rule takes back);
|
|
466
|
+
anything git cannot answer keeps the key late. Undeclared writes, an
|
|
458
467
|
`outputs.workspaceFiles` producer upstream, a rewriter the key does not
|
|
459
468
|
fold, and runtime probes after a writer still leave a key preliminary.
|
|
460
469
|
The
|
|
@@ -553,7 +562,24 @@ Hard invariants of the remote prefetch:
|
|
|
553
562
|
later `get` finds it as a now-local hit — still reports
|
|
554
563
|
`source: 'remote'`, so the outcome is `cache-hit-remote`.
|
|
555
564
|
- **A remote-read-off policy** (`--no-cache`, `--force`, or
|
|
556
|
-
`--cache-policy=remote:`) fires no prefetch.
|
|
565
|
+
`--cache-policy=remote:`) fires no prefetch. With remote writes on
|
|
566
|
+
(`--force`), the same up-front keys go to one `hasMany` per remote
|
|
567
|
+
the run writes but does not read and that can batch, in the
|
|
568
|
+
background: no task waits for it, only each upload does. An upload
|
|
569
|
+
of a key that remote holds is skipped (an entry is immutable) and is
|
|
570
|
+
counted nowhere. A key the probe did not cover, or a remote with no
|
|
571
|
+
`hasMany`, asks `has` for that key inside its upload job; a probe
|
|
572
|
+
that fails uploads, as before.
|
|
573
|
+
- **No `has` before a `put`.** An entry is immutable: a remote's `put`
|
|
574
|
+
of a key it holds keeps the stored bytes, and a wire that would
|
|
575
|
+
overwrite checks inside (`turboCache()` asks HEAD unless a 404 or a
|
|
576
|
+
batch answer this run said the key is absent; `reapi()` looks the
|
|
577
|
+
action up beside its upload and keeps a stored result; Nx servers
|
|
578
|
+
answer 409). `ctx.cache.put` and a run's own entries send the `put`
|
|
579
|
+
alone.
|
|
580
|
+
- **`--dry` batches too.** The plan derives every key first, then asks
|
|
581
|
+
each remote with `hasMany` once; a remote without it is asked `has`
|
|
582
|
+
per key.
|
|
557
583
|
- **Never fail.** Every remote path (get / put / ingest / prefetch)
|
|
558
584
|
catches all errors and degrades to a cache miss. A remote 500, a
|
|
559
585
|
network drop, a corrupt artifact, or a failed integrity check can
|
|
@@ -573,16 +599,16 @@ fire-and-forget background upload**. The task's outcome (and its
|
|
|
573
599
|
dependents) never wait on upload latency — the uploads race alongside
|
|
574
600
|
the rest of the run and are drained before `cache.close()`, so a
|
|
575
601
|
short run still ships every artifact before the process exits. Upload
|
|
576
|
-
failures
|
|
602
|
+
failures are warned once per failure class and are otherwise ignored (the task
|
|
577
603
|
already succeeded; the only loss is the remote entry).
|
|
578
604
|
|
|
579
605
|
An upload is the outputs as the task wrote them; secret masking does
|
|
580
606
|
not reach file contents, so a task whose outputs embed a secret is one
|
|
581
607
|
to leave uncached ([security](./security.md)).
|
|
582
608
|
|
|
583
|
-
### Planning probes (`--dry`
|
|
609
|
+
### Planning probes (`--dry`)
|
|
584
610
|
|
|
585
|
-
The planning
|
|
611
|
+
The planning path (`vx run --dry`) predicts hits without
|
|
586
612
|
side effects: against a remote cache they use a **lightweight
|
|
587
613
|
existence probe** — no artifact download, no local ingest. A predicted
|
|
588
614
|
`hit-remote` means the artifact exists remotely; the bytes move only
|
|
@@ -615,8 +641,8 @@ remote executor's own store.
|
|
|
615
641
|
The CLI maps three flags to a policy (precedence: start all-on → apply
|
|
616
642
|
`--cache-policy` → `--no-cache` forces all off → `--force` forces both reads
|
|
617
643
|
off): `--no-cache` = everything off (no read, no write, no output
|
|
618
|
-
clean); `--force` = reads off / writes on (re-execute
|
|
619
|
-
|
|
644
|
+
clean); `--force` = reads off / writes on (re-execute, outputs cleaned;
|
|
645
|
+
a key already stored, locally or in a remote, is kept as it is); `--cache-policy=<spec>` = explicit per-layer control.
|
|
620
646
|
Off CI, unless a spec names the remote, `remoteWrite` starts off: a key
|
|
621
647
|
holds only declared inputs, so a laptop's undeclared tool or file could
|
|
622
648
|
replay on CI. See `docs/cli.md` § Cache control.
|
|
@@ -665,7 +691,10 @@ is on):
|
|
|
665
691
|
Until 2026-09-27 (A-3) the rename came first, and a commit refused
|
|
666
692
|
past the busy timeout left the new bytes beside the old rows: every
|
|
667
693
|
later hit on the key failed the task as a corrupt artifact.
|
|
668
|
-
A
|
|
694
|
+
A `--force` save of a key the index already holds is skipped, so
|
|
695
|
+
`--force` rewrites nothing. A re-save (a key dropped as corrupt, or
|
|
696
|
+
two writers that both found it absent) first moves the previous
|
|
697
|
+
artifact aside under
|
|
669
698
|
a temp name and unlinks it after the commit: ext4 flushes the
|
|
670
699
|
incoming file when a rename replaces one, 0.55 ms a save on the main
|
|
671
700
|
thread against 0.04 (a forced 1,000-task run 4.01 s → 3.46 s,
|
|
@@ -839,10 +868,10 @@ Skipped when:
|
|
|
839
868
|
on, so it DOES clean (the saved snapshot must be clean).
|
|
840
869
|
- `cache.outputs.clean` is `false` (on the task, else the workspace's
|
|
841
870
|
`cache.outputs.clean`): the command sees last run's outputs (tsc's
|
|
842
|
-
`.tsbuildinfo`).
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
cleans before its restore.
|
|
871
|
+
`.tsbuildinfo`). You opt out of the clean-tree guarantee: the save
|
|
872
|
+
stores every file the outputs match after the run, so a leftover from
|
|
873
|
+
an older build is cached and restored everywhere. A retry cleans as
|
|
874
|
+
usual; a hit still cleans before its restore.
|
|
846
875
|
|
|
847
876
|
A declared output the process cannot remove (a `dist/` another user
|
|
848
877
|
wrote, a read-only checkout) fails the task with `cannot remove declared
|
|
@@ -1192,7 +1221,8 @@ in `~/.vx/<id>/cache`, and each workspace keeps only its own index in
|
|
|
1192
1221
|
its `.vx/cache`: every checkout of the repository hits what another
|
|
1193
1222
|
saved (a second clone, a worktree), and none reads another's history.
|
|
1194
1223
|
Task timings are shared too: `task_durations`, what a duration forecast
|
|
1195
|
-
reads, so a new worktree has one on its first run.
|
|
1224
|
+
reads, so a new worktree has one on its first run. So are plugins' own
|
|
1225
|
+
entries (`plugin_blobs`, a plugin's `ctx.cache`).
|
|
1196
1226
|
The id is Nx 23's: 16 hex of a sha256 of the remote (`origin`, then
|
|
1197
1227
|
`upstream`, `base`, the first; `host/owner/repo` in lower case, so ssh
|
|
1198
1228
|
and https agree) and the workspace's path in the repository; with no
|
|
@@ -1204,7 +1234,7 @@ owner-only; vx closes one of yours that others can read (chmod 700), and one oth
|
|
|
1204
1234
|
~/.vx/<id>/cache/ the shared store
|
|
1205
1235
|
├── store.db entries, entry_stdout, output_files,
|
|
1206
1236
|
│ entry_inputs, task_durations,
|
|
1207
|
-
│ store_meta; artifacts
|
|
1237
|
+
│ plugin_blobs, store_meta; artifacts
|
|
1208
1238
|
│ of at most 32 KiB compressed (v33)
|
|
1209
1239
|
└── <hash>.tar.zst the larger artifacts (below)
|
|
1210
1240
|
|
|
@@ -1469,9 +1499,9 @@ keep). The artifacts stay: each is indexed again from its own bytes
|
|
|
1469
1499
|
when its task next asks for its key (below).
|
|
1470
1500
|
|
|
1471
1501
|
```sql
|
|
1472
|
-
-- src/cache/schema.ts (SCHEMA_VERSION = '
|
|
1502
|
+
-- src/cache/schema.ts (SCHEMA_VERSION = 'v40', in cache.ts)
|
|
1473
1503
|
-- With a shared store, entries, entry_stdout, output_files, entry_inputs,
|
|
1474
|
-
-- store_meta and
|
|
1504
|
+
-- store_meta, task_durations, task_outcomes, blob_sizes and plugin_blobs live in its store.db, attached as `store`; the rest is
|
|
1475
1505
|
-- the workspace's cache.db. A named cache dir holds all of them.
|
|
1476
1506
|
|
|
1477
1507
|
CREATE TABLE schema_meta (
|
|
@@ -1526,7 +1556,8 @@ CREATE TABLE runs (
|
|
|
1526
1556
|
timed_out INTEGER, -- 1 when vx's own timeout killed it
|
|
1527
1557
|
sandbox_violations INTEGER, -- the sandbox's violation count
|
|
1528
1558
|
not_ready TEXT, -- 'timeout' | 'exited' | 'spawn' (persistent task)
|
|
1529
|
-
restored INTEGER
|
|
1559
|
+
restored INTEGER, -- v31, on a hit: 1 = outputs restored, 0 = up to date
|
|
1560
|
+
remote_error TEXT -- v40: each remote read or write of the key that failed
|
|
1530
1561
|
);
|
|
1531
1562
|
|
|
1532
1563
|
-- Two indexes, both append-only under a run's inserts: every row of a run
|
|
@@ -1537,10 +1568,6 @@ CREATE TABLE runs (
|
|
|
1537
1568
|
-- the history reader bounds its scan by rowid instead (see history.md).
|
|
1538
1569
|
CREATE INDEX runs_started_at ON runs(started_at);
|
|
1539
1570
|
CREATE INDEX runs_run_id ON runs(run_id);
|
|
1540
|
-
-- The one keyed index, PARTIAL over failed rows: a green run's inserts only
|
|
1541
|
-
-- evaluate its predicate, and the flakiness probe after a miss
|
|
1542
|
-
-- (failure-mode.ts, "did this key ever fail?") reads a few leaves.
|
|
1543
|
-
CREATE INDEX runs_failed ON runs(hash) WHERE status = 'failed';
|
|
1544
1571
|
|
|
1545
1572
|
-- Every non-group, non-aborted outcome of a run gets a row, so
|
|
1546
1573
|
-- `invocations.task_count` always equals `COUNT(*)` here for that run_id
|
|
@@ -1575,7 +1602,8 @@ CREATE TABLE file_hashes (
|
|
|
1575
1602
|
-- The size of each index blob the enumeration checked against the
|
|
1576
1603
|
-- worktree size git recorded (§ Cache key derivation, A-60): fixed for
|
|
1577
1604
|
-- its OID, so a warm run asks git for none. Swept with file_hashes by
|
|
1578
|
-
-- seen_at, the time the row was written.
|
|
1605
|
+
-- seen_at, the time the row was written. v38: in the store, so a worktree
|
|
1606
|
+
-- reads what another learned.
|
|
1579
1607
|
CREATE TABLE blob_sizes (
|
|
1580
1608
|
oid TEXT PRIMARY KEY,
|
|
1581
1609
|
size INTEGER NOT NULL,
|
|
@@ -1630,13 +1658,13 @@ CREATE TABLE output_dirs (
|
|
|
1630
1658
|
|
|
1631
1659
|
-- v22 (Tier 3): one header row per `vx run` invocation. The `runs`
|
|
1632
1660
|
-- table is per-task; this is the per-invocation record carrying the
|
|
1633
|
-
-- command, git/CI/host context,
|
|
1661
|
+
-- command, git/CI/host context, and run-level counts. Recorded
|
|
1634
1662
|
-- atomically alongside `runs` via recordRunBundle (one transaction).
|
|
1635
1663
|
CREATE TABLE invocations (
|
|
1636
1664
|
run_id TEXT PRIMARY KEY, -- UUIDv7, == runs.run_id
|
|
1637
1665
|
command TEXT NOT NULL, -- full argv, e.g. "vx run build --all"
|
|
1638
1666
|
requested_tasks TEXT NOT NULL, -- JSON string[] of options.tasks
|
|
1639
|
-
cache_policy TEXT NOT NULL, --
|
|
1667
|
+
cache_policy TEXT NOT NULL, -- the --cache-policy spec, e.g. "local:rw,remote:r"
|
|
1640
1668
|
concurrency INTEGER NOT NULL,
|
|
1641
1669
|
flow TEXT, -- 'focused' | 'broad' | NULL (programmatic)
|
|
1642
1670
|
started_at INTEGER NOT NULL, -- ms-epoch
|
|
@@ -1659,8 +1687,7 @@ CREATE TABLE invocations (
|
|
|
1659
1687
|
host TEXT, -- os.hostname()
|
|
1660
1688
|
os TEXT, -- process.platform
|
|
1661
1689
|
arch TEXT, -- process.arch
|
|
1662
|
-
vx_version TEXT NOT NULL
|
|
1663
|
-
tags TEXT NOT NULL DEFAULT '{}' -- JSON object {k:v} from --tag
|
|
1690
|
+
vx_version TEXT NOT NULL
|
|
1664
1691
|
);
|
|
1665
1692
|
CREATE INDEX invocations_started ON invocations(started_at);
|
|
1666
1693
|
CREATE INDEX invocations_branch ON invocations(branch);
|
|
@@ -1696,6 +1723,8 @@ CREATE TABLE store_meta (
|
|
|
1696
1723
|
-- v36: each executed success's duration, appended in the run's history
|
|
1697
1724
|
-- transaction, in the store so every worktree forecasts from it.
|
|
1698
1725
|
-- source: 'branch:<name>'; the forecast reads the newest five per task.
|
|
1726
|
+
-- v37: 'remote' rows are a default-branch commit's timings a plugin
|
|
1727
|
+
-- imported, one per (sha, task).
|
|
1699
1728
|
CREATE TABLE task_durations (
|
|
1700
1729
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1701
1730
|
project TEXT NOT NULL,
|
|
@@ -1706,6 +1735,33 @@ CREATE TABLE task_durations (
|
|
|
1706
1735
|
recorded_at INTEGER NOT NULL
|
|
1707
1736
|
);
|
|
1708
1737
|
CREATE INDEX task_durations_task ON task_durations(project, task, source, id);
|
|
1738
|
+
CREATE UNIQUE INDEX task_durations_remote
|
|
1739
|
+
ON task_durations(sha, project, task) WHERE source = 'remote';
|
|
1740
|
+
|
|
1741
|
+
-- v38: the flaky record (failure-mode.ts), in the store so a key that
|
|
1742
|
+
-- passed in one worktree and failed in another is flaky in both. Every
|
|
1743
|
+
-- executed success or failure that names its key (keyed, cached, not run
|
|
1744
|
+
-- behind a failure), and a key's first hit: a later hit replays a pass on
|
|
1745
|
+
-- record, so a warm run on passed keys writes no row (one index probe,
|
|
1746
|
+
-- ~1 ms per 1,000 hits). Pruned by age with the run history.
|
|
1747
|
+
CREATE TABLE task_outcomes (
|
|
1748
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1749
|
+
project TEXT NOT NULL,
|
|
1750
|
+
task TEXT NOT NULL,
|
|
1751
|
+
hash TEXT NOT NULL,
|
|
1752
|
+
status TEXT NOT NULL,
|
|
1753
|
+
attempts INTEGER,
|
|
1754
|
+
recorded_at INTEGER NOT NULL
|
|
1755
|
+
);
|
|
1756
|
+
CREATE INDEX task_outcomes_hash ON task_outcomes(hash, status);
|
|
1757
|
+
|
|
1758
|
+
-- v37: a plugin's own entries (`ctx.cache`), by core's key for its
|
|
1759
|
+
-- name; written once, pruned by age with the run history.
|
|
1760
|
+
CREATE TABLE plugin_blobs (
|
|
1761
|
+
key TEXT PRIMARY KEY,
|
|
1762
|
+
bytes BLOB NOT NULL,
|
|
1763
|
+
at INTEGER NOT NULL
|
|
1764
|
+
);
|
|
1709
1765
|
|
|
1710
1766
|
-- v33: an artifact of at most 32 KiB compressed, its exact <hash>.tar.zst
|
|
1711
1767
|
-- bytes, written in the transaction that writes its entry rows. In the
|
|
@@ -2114,7 +2170,7 @@ breaking footer).
|
|
|
2114
2170
|
migration), so this costs one cold rebuild.
|
|
2115
2171
|
- **SCHEMA v21 → v22 (no `CACHE_VERSION` bump)**: Tier-3 dashboard
|
|
2116
2172
|
tables — `invocations` (one header row per `vx run` with command,
|
|
2117
|
-
git/CI/host context,
|
|
2173
|
+
git/CI/host context, and run-level counts, recorded with `runs`
|
|
2118
2174
|
via `Cache.recordRunBundle`) and `entry_inputs` (one row per cache-key
|
|
2119
2175
|
component, keyed by the cache-ENTRY hash — the input-fingerprint
|
|
2120
2176
|
moat). `entry_inputs` is written **inside the entry-save transaction,
|