Skip to content
vxvx
GitHubBlueskydev.toRSS

Upstream bug ledger

Real Turborepo and Nx bug reports in vx’s scope, each checked against vx and, where vx could have it, held by a test. The survey (2026-09-24) read the two trackers for stale cache hits, key instability, restore and save faults, graph and filter errors, signal and teardown bugs, watch and output faults, and remote-cache failures, then asked of each: does vx have it, and would a test notice if it came back? Where no test would, one was written (item 745); where vx had the bug, it was fixed and the fix’s tests are cited here.

A row is one upstream report, or a few that report one fault. Its verdict is one of:

  • covered: the cited tests would fail if vx had the bug. Rows the survey found untested say “written for this ledger”.
  • n/a: the bug cannot occur in vx; the note says why. A test is cited where one pins the reason.
  • fixed-in-item-N: vx had the bug; STATUS item N fixed it, and its tests are cited. A fix pinned only by a template-titled loop, which the law cannot cite, names the loop in the note.
  • open (id): vx has the bug and the fix is not in yet; the id names it: new: for a fault writing the ledger found, limit: <page> § <heading> for a documented limit, naming the heading that states it.

Every citation is file › "title", the file relative to the repository root and the title exactly as written in the test. tests/upstream-ledger.unsafe.test.ts parses both tables and fails when a cited title is not an it(…) or test(…) title in that file, when a covered row cites nothing, or when an open (limit: …) row names no heading of its page, so a renamed or deleted test cannot leave a row claiming a pin it lost.

issue class verdict vx test note
turborepo#14059 stale-hit:env-undeclared n/a packages/vx/tests/orchestrator.test.ts › “undeclared env vars do not leak to the child” taskEnv (packages/vx/src/orchestrator/task-process.ts) gives a task the essential allowlist, its passThrough names, its define pairs, the bin dirs on PATH and vx’s two run markers (VX_RUN_WORKSPACE, VX_RUN_TASK); no other host variable.
turborepo#10690 stale-hit:env-global covered packages/vx/tests/orchestrator.test.ts › “inputs.env affects the cache key; exec.env.passThrough alone does not”
turborepo#4645, turborepo#1099 stale-hit:env-unset fixed-in-item-739 packages/vx/tests/orchestrator.test.ts › “a declared env name UNSET and set to the empty string are different keys”
turborepo#548 stale-hit:env-many covered packages/vx/tests/orchestrator.test.ts › “a change to the LAST of thirteen declared env names misses” written for this ledger (item 745)
turborepo#9659, turborepo#10826 env:exclusion-ignored n/a There is no workspace-level env layer: WORKSPACE_FIELDS (src/workspace/config-schema.ts:33) has no env field. CLAUDE.md § Rejected lists globalEnv; comparison.md § Likely-worth-adding item 4 rejects globalPassThroughEnv with it.
turborepo#4428 stale-hit:dotenv covered packages/vx/tests/inputs.test.ts › “src/* folds the dotfile src/.env”
turborepo#13948, turborepo#886 stale-hit:global-input-dropped covered packages/vx/tests/stale-hit-memo.test.ts › “a workspace output written mid-run reaches a consumer whose partition was read before it”
turborepo#13918 stale-hit:dep-output-snapshot covered packages/vx/tests/stale-hit-memo.test.ts › “a wiped output stops counting as a consumer input on the cache-miss path”
turborepo#13788, turborepo#8051, turborepo#7821 stale-hit:hash-before-deps fixed-in-item-743 packages/vx/tests/undeclared-writes.test.ts › “seeds A, B, B, A build A, B, B, A: the up-front key is not taken before the producer ran”<br>packages/vx/tests/undeclared-writes.test.ts › “the first run keys the file the producer created, not the run-start listing without it”<br>packages/vx/tests/undeclared-writes.test.ts › “a TRACKED input the producer rewrites is keyed on its new bytes, not its index OID”<br>packages/vx/tests/undeclared-writes.test.ts › “an unsandboxed uncached producer makes its same-project reader unstable” An uncached producer’s writes into its project: a reader there is no longer keyed up front, and the run-start git facts are dropped once the producer exits.
turborepo#10111 stale-hit:task-mutates-inputs fixed-in-item-743 packages/vx/tests/inputs-moved.test.ts › “is not saved under the key of the bytes it rewrote, so restoring them re-runs it”<br>packages/vx/tests/inputs-moved.test.ts › “an input the task deletes: the entry is withheld”<br>packages/vx/tests/in-run-writes.test.ts › “seeds A, B, B, A build A, B, B, A: its reader is not restored ahead of it”<br>packages/vx/tests/in-run-writes.test.ts › “under a read-only cache policy the rewrite still drops what the run knew of the project” A miss re-checks its inputs before it saves; an input its own command changed withholds the save with one status line. A same-project reader folding no key of it is keyed after it, not up front, and a run that saves nothing still drops what it knew of the project (item 750).
turborepo#1146 stale-hit:edit-during-run fixed-in-item-743 packages/vx/tests/inputs-moved.test.ts › “while the command runs: the entry is withheld, and the restored file rebuilds”<br>packages/vx/tests/inputs-moved.test.ts › “before the task starts, a TRACKED input: its index OID is not trusted past the edit”<br>packages/vx/tests/inputs-moved.test.ts › “before the task starts, an UNTRACKED input: the key re-derived at the command differs”<br>packages/vx/tests/inputs-moved.test.ts › “edited and reverted while the command runs: still withheld, and the next run rebuilds” An input edited and reverted while the command runs is seen too (item 1015). Not seen: a file added under an input glob mid-run.
turborepo#1473, turborepo#7540, turborepo#1323 stale-hit:tracked-dirty covered packages/vx/tests/git-oid.test.ts › “edit changes the key; reverting restores the ORIGINAL key before any commit”
turborepo#1280, turborepo#4185, turborepo#9574 stale-hit:no-vcs covered packages/vx/tests/inputs.test.ts › “the FALLBACK enumeration refuses a non-git dir too, not just the populate”<br>packages/vx/tests/no-git-on-path.test.ts › “vx run build --affected is one line naming the install”<br>packages/vx/tests/no-git-on-path.test.ts › “vx run build --affected=HEAD is one line naming the install”<br>packages/vx/tests/no-git-on-path.test.ts › “vx run build --all is one line naming the install”
turborepo#12554 key-unstable:gitignore-dirty covered packages/vx/tests/inputs.test.ts › “gitignored files are excluded (workspace-root .gitignore)”
turborepo#2560 key-unstable:gitignored-in-glob covered packages/vx/tests/orchestrator.test.ts › “gitignored files do not contribute to the default input set”
turborepo#7784 key-unstable:outputs-as-inputs covered packages/vx/tests/local-shortcircuit.test.ts › “codegen-into-shared-project dependent is NOT restore-tier (stays exec-tier)”
turborepo#9676 key-overbroad:unlisted-file covered packages/vx/tests/parity-turbo.test.ts › “a file outside inputs changes nothing (Turbo: inputs narrows the default)”
turborepo#13384 key-overbroad:workspace-wide-deps covered packages/vx/tests/orchestrator-run.test.ts › “sibling-package input isolation: editing one package does not bust an unrelated sibling”
turborepo#11025 key-overbroad:passthrough-args covered packages/vx/tests/orchestrator-run.test.ts › “forwardArgs do NOT pollute upstream cache keys (dep stays cached across user-args changes)”
turborepo#9218 key-overbroad:negation-via-dep covered packages/vx/tests/orchestrator.test.ts › “a negated input still excludes when a same-project upstream writes into the inputs” written for this ledger (item 745)
turborepo#8112, turborepo#4522 glob:negation covered packages/vx/tests/inputs-resolution.test.ts › “position is irrelevant: a negation listed FIRST still subtracts”<br>packages/vx/tests/orchestrator.test.ts › “composing ‘**/*’ with negation works as union-then-subtract”
turborepo#1913, turborepo#3087 stale-hit:input-outside-project covered packages/vx/tests/project-loader.test.ts › “rejects .. path segments in inputs.files”
turborepo#169 stale-hit:upstream-source covered packages/vx/tests/sandbox-grants.unsafe.test.ts › “an unkeyed sibling is withheld and the read reported, with the hint (project link)”<br>packages/vx/tests/parity-turbo.test.ts › “an inputs change misses — and cascades to dependents, which fold upstream inputs”
turborepo#2606 stale-hit:lockfile-resolution covered packages/vx-lockfile/tests/discover.test.ts › “with bun() declared, the edit moves the key”<br>packages/vx-lockfile/tests/pnpm.test.ts › “a dependency bump re-keys only the projects that reach it”
turborepo#12252 key-unstable:lockfile-order covered packages/vx-lockfile/tests/pnpm.test.ts › “is independent of YAML key order”<br>packages/vx/tests/lockfile-claim.test.ts › “the order a COMPONENT pops its members in does not move its digest”
turborepo#5081 key-unstable:binary-file covered packages/vx/tests/git-oid.test.ts › “matches git hash-object for empty and binary content”
turborepo#5217 key-unstable:checkout-path covered packages/vx/tests/git-subdir-workspace.test.ts › “the main checkout and a linked worktree at a longer path derive the same keys” written for this ledger (item 745)
turborepo#13651 stale-hit:absolute-path-output n/a packages/vx/tests/cache-dir-selection.test.ts › “the second checkout, at another and longer path, restores what the first saved” An artifact holds outputs by project-relative path (outputs/<rel>, caching.md § Cache write), so a hit restores into the checkout that asks, a shared cache.dir included.
turborepo#702 key-collision:project covered packages/vx/tests/task-hash-derive.test.ts › “a different task id yields a different key”
turborepo#1010 stale-hit:cache-disabled covered packages/vx/tests/parity-turbo.test.ts › “a task that loses its cache: true moves its key and executes instead of replaying the old entry” written for this ledger (item 745)
turborepo#9681 force:ignored-with-remote covered packages/vx/tests/cli.test.ts › “--force skips reads but keeps writes (re-execute + refresh)”<br>packages/vx/tests/layered-cache.test.ts › “get() with remote reads off is a plain local miss: no remote GET, null”
turborepo#3127 remote:force-no-overwrite n/a packages/vx/tests/orchestrator-remote.test.ts › “--force re-executes but leaves the artifact the remote holds, and the next cold run is served it” by design: an entry is immutable (2026-10-15), so --force re-executes and refreshes the disk but never re-sends a key a remote holds; a bad entry is removed at the server, or a changed input gives a new key
turborepo#13430, turborepo#12645, turborepo#11216 restore:symlink-tree covered packages/vx/tests/output-shape.test.ts › “a symlink to a directory, or a dangling one, is cached and comes back as the link”
turborepo#13042 save:symlink-output-root covered packages/vx/tests/output-shape.test.ts › “saves through the link, hits, and a hit restores the file the link leads to” written for this ledger (item 745)
turborepo#1070 save:dangling-symlink covered packages/vx/tests/output-shape.test.ts › “a symlink to a directory, or a dangling one, is cached and comes back as the link”
turborepo#7410 restore:long-path covered packages/vx/tests/artifact-roundtrip.test.ts › “a cache hit restores the produced tree byte- and mode-identically”
turborepo#156, turborepo#1236 restore:file-mode covered packages/vx/tests/artifact-roundtrip.test.ts › “a cache hit restores the produced tree byte- and mode-identically”
turborepo#10951 restore:stale-extra-files covered packages/vx/tests/stale-hit.test.ts › “a STRAY file in a declared output dir is not “up-to-date” — the set must match”
turborepo#6754 save:partial-on-abort covered packages/vx/tests/execute-task.test.ts › “an aborted task is never cached — its partial outputs are not replayed next run”
turborepo#12786 save:detached-descendant open (limit: packages/vx/docs/caching.md § Cache write) packages/vx/tests/runner.test.ts › “returns promptly when a backgrounded grandchild holds the pipe open (no hang)” Not a fix: item 742 only documented it. The outputs are what exists when the command exits (caching.md § Cache write); a descendant the command detached has left the process group vx tracks, so the command must wait for it.
turborepo#6749 restore:skipped-under-uncached covered packages/vx/tests/parity-turbo.test.ts › “an uncached task over a cached dependency restores the deleted outputs of the dependency first” written for this ledger (item 745)
turborepo#8476 restore:wrong-destination covered packages/vx/tests/overlapping-outputs.test.ts › “upstream MISS + dependant HIT: build re-runs and wipes dist, individual restores its own rows after”
turborepo#944, turborepo#10400, turborepo#3185, turborepo#3393 save:output-outside-project covered packages/vx/tests/project-loader.test.ts › “rejects .. path segments in outputs.files (data-loss vector)”
turborepo#839 cache-corruption:hardlink n/a An entry is one <hash>.tar.zst and a restore extracts fresh bytes from it (caching.md § Storage layout, § Cache lookup → restore).
turborepo#10875 restore:needless-rewrite covered packages/vx/tests/overlapping-outputs.test.ts › “both miss, then both hit up-to-date: the tree is the cold tree, twice”
turborepo#6136 save:task-name-chars n/a Entries are stored by key, never by task name: one artifact is <hash>.tar.zst (caching.md § Storage layout).
turborepo#9345 hash:non-utf8-name fixed-in-item-739 packages/vx/tests/stale-hit-git.test.ts › “a name that holds U+FFFD as a character is an input like any other”<br>packages/vx/tests/stale-hit-git.test.ts › “an output by that name fails the save by name, so no hit restores a tree without it”
turborepo#531, turborepo#6729, turborepo#13732 hash:directory-entry covered packages/vx/tests/git-oid.test.ts › “a tracked symlink to a directory is an input: retargeting it moves the key, clean or dirty”
turborepo#1103 hash:git-noise covered packages/vx/tests/stale-hit-git.test.ts › “git warning on stderr during the attribute check leaves the key where a quiet git puts it” written for this ledger (item 745)
turborepo#939 logs:replay-order covered packages/vx/tests/output-flow.test.ts › “a replayed dependency frame closes before its live dependent frame opens” written for this ledger (item 745)
turborepo#3272, turborepo#972 logs:replay-mode covered packages/vx/tests/output-flow.test.ts › “cache hit with replayed stdout → silent”
turborepo#12302 remote:integrity covered packages/vx-reapi/tests/integrity.test.ts › “readBlob refuses bytes that do not hash to the requested digest”<br>packages/vx-migrate/tests/turbo-cache.test.ts › “signs uploads and refuses a download whose tag does not verify”
turborepo#487, turborepo#2096, turborepo#8772 remote:upload-failure-silent covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a 413: green, one warning naming the upload, its artifact and the server”<br>packages/vx-migrate/tests/remote-cache-degrade.test.ts › “an upload past its deadline: green, one warning naming the upload and the deadline” written for this ledger (item 745)
turborepo#2081 remote:unreachable-silent covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a closed port: green, the task executes, and ONE warning names the request and the server”<br>packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a host that does not resolve: green, the task executes, and ONE warning names the request and the server” written for this ledger (item 745)
turborepo#6765, turborepo#7359 remote:auth-failure covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “six projects, one warning — what the adopter reads”
turborepo#5055, turborepo#6921 remote:crash covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a corrupt artifact degrades to a miss — never a half-restored output”<br>packages/vx/tests/layered-cache.test.ts › “get() that resolves the wrong shape is named as the plugin bug and degraded to a miss”
turborepo#12346 remote:upload-skipped covered packages/vx/tests/orchestrator-remote.test.ts › “a cached dependency of an uncached requested task is uploaded and later served remotely” written for this ledger (item 745)
turborepo#8418 remote:layer-selection-ignored covered packages/vx/tests/orchestrator-remote.test.ts › “local:,remote:rw re-executes over a LOCAL-only entry and uploads the result” written for this ledger (item 745)
turborepo#9177 remote:wire-content-length covered packages/vx-migrate/tests/turbo-cache.test.ts › “put → has / hasMany / get round trip with the spec’s headers and query”<br>packages/vx-migrate/tests/nx-cache.test.ts › “put → get round trip; a miss is 404 → null; a second put of the same hash is the spec’s 409 and fine”
none (found checking turborepo#1103 and turborepo#5081) stale-hit:xdg-attributes fixed-in-item-739 packages/vx/tests/stale-hit-git.test.ts › “takes both files from a git that names them, and nothing else”<br>packages/vx/tests/stale-hit-git.test.ts › “mirrors the global lookup for a git that does not name it”
turborepo#135 graph:same-package-dep-ignored covered packages/vx/tests/parity-turbo.test.ts › “"dependsOn": ["build"] — a bare name waits on the same package’s task”
turborepo#1212 graph:same-package-dep-expands-to-all covered packages/vx/tests/parity-turbo.test.ts › “"dependsOn": ["build"] — a bare name waits on the same package’s task”
turborepo#9589, turborepo#11147 graph:missing-task-still-pulls-deps covered packages/vx/tests/task-selection.test.ts › “a project without the requested task contributes none of its dependencies” written for this ledger (item 745)
turborepo#10109 graph:caret-through-missing-task covered packages/vx/tests/task-graph.test.ts › “^name passes through deps that lack the task to deeper holders (sparse bridge)”
turborepo#10705 graph:caret-upstream-empty covered packages/vx/tests/parity-turbo.test.ts › “"dependsOn": ["^build"] — a package builds after every workspace dependency builds”
turborepo#10785 graph:catalog-protocol-edge-missing n/a pinned with item 734, after the survey ran; core reads no manifest edge since the language-agnostic core’s PR 3: edges are what the lockfile plugin reads the manager installed, a catalog: entry already resolved to the package it installed
turborepo#6744 graph:workspace-path-alias fixed-in-item-734 core reads no manifest edge since the language-agnostic core’s PR 3: edges are what the lockfile plugin reads the manager installed; pinned by the row loop in packages/vx-lockfile/tests/discover-parity.test.ts (“bun(): a workspace: path and a workspace: alias link their target, not their key”)
turborepo#4214, turborepo#8989 graph:range-mismatch-treated-as-local fixed-in-item-734 packages/vx-lockfile/tests/discover-parity.test.ts › “pnpm installs a plain range from the registry, though the workspace package satisfies it” core reads no manifest edge since the language-agnostic core’s PR 3: edges are what the lockfile plugin reads the manager installed
turborepo#12640, turborepo#1601 graph:peer-dep-edges fixed-in-item-734 core reads no manifest edge since the language-agnostic core’s PR 3: edges are what the lockfile plugin reads the manager installed; pinned by the row loop in packages/vx-lockfile/tests/discover-parity.test.ts (“yarn(): an installed registry entry, not a workspace peer of its key, decides the edge”)
turborepo#9619 graph:root-task-shorthand-with-filter covered packages/vx/tests/task-selection.test.ts › “the workspace root listed as a project keeps its task under a negated filter” written for this ledger (item 745)
turborepo#7899 graph:root-task-depends-on-workspace-task n/a docs/schema.md § dependsOn: “Same-project ('name') — name must exist in this project’s tasks map; missing is a hard error at graph-build time.”
turborepo#9072 graph:root-task-bare-dep-resolves-to-root n/a docs/schema.md § dependsOn: “Same-project ('name') — name must exist in this project’s tasks map; missing is a hard error at graph-build time.”
turborepo#5847 graph:package-override-drops-base-deps n/a comparison.md § Config schema comparison: “Target defaults / inheritance” (Turbo extends, Nx targetDefaults) is “rejected by design — presets are TS imports”. There is no inherited task to merge.
turborepo#10454 graph:plan-lists-missing-task covered packages/vx/tests/cli.test.ts › “a --dry typo beside good tasks names ONLY the typo”
turborepo#262, turborepo#973, turborepo#675 cycle:package-cycle-hangs covered packages/vx/tests/task-graph.test.ts › “detects a cross-project cycle”
turborepo#1117 cycle:self-dependency-hangs covered packages/vx/tests/package-graph.test.ts › “a project that names ITSELF is not its own dependency”
turborepo#1163 cycle:false-positive-without-task-cycle covered packages/vx/tests/task-graph.test.ts › “a package cycle between projects that makes no task cycle builds”
turborepo#8484 persistent:depends-on-persistent covered packages/vx/tests/persistent.test.ts › “a persistent task over a persistent upstream starts after it, and both stay up for the run” written for this ledger (item 745)
turborepo#4291 persistent:concurrency-check-counts-missing n/a docs/schema.md § persistent: “The runner spawns the command but does NOT wait for it to exit.” / “Downstream unblocks on ready, not on exit.”
turborepo#4195 persistent:starves-concurrency covered packages/vx/tests/persistent.test.ts › “persistent task with concurrency=1 does not block downstream forever”
turborepo#4438 persistent:parallel-flag-validation n/a docs/cli.md § Flags has no --parallel, and docs/schema.md § persistent: “The runner spawns the command but does NOT wait for it to exit.”
turborepo#8915 exec:dev-server-exits-early fixed-in-item-740 packages/vx/tests/keep-alive.test.ts › “a server that exits on stdin EOF stays up while vx runs” A persistent task reads a stdin pipe vx holds open, so a server that exits on EOF (esbuild --watch) stays up.
turborepo#12502 exec:child-hangs-under-runner covered packages/vx/tests/terminal.unsafe.test.ts › “cannot open /dev/tty, fails that open at once, and the run completes” written for this ledger (item 745)
turborepo#9651 exec:pre-post-lifecycle-scripts n/a docs/execution.md § One command per task: “exec.command is a single shell command — there’s no multi-step sequence.”
turborepo#1744 exec:passthrough-args-leak-to-deps covered packages/vx/tests/orchestrator-run.test.ts › “arguments after -- reach the named task command and never its dependency” written for this ledger (item 745)
turborepo#339 concurrency:limit-ignored covered packages/vx/tests/scheduler.test.ts › “serializes execution with concurrency = 1”
turborepo#2887 concurrency:limit-lost-after-failure covered packages/vx/tests/scheduler.test.ts › “failing tasks keep the concurrency cap, under deps-ok and always alike” written for this ledger (item 745)
turborepo#12251 concurrency:deadlock-high-core-count covered packages/vx/tests/scheduler.test.ts › “a worker count far above the task count, the default on 96 cores included, completes” written for this ledger (item 745)
turborepo#10013 exit:parallel-should-continue covered packages/vx/tests/scheduler.test.ts › “deps-ok (default): a failure skips dependents, siblings run — unchanged pin”
turborepo#454 exit:continue-masks-failure covered packages/vx/tests/parity-turbo.test.ts › “--continue runs dependents past a failure; the run is still red”
turborepo#567 exit:false-failure covered packages/vx/tests/git-subdir-workspace.test.ts › “passes under a plain, an -a and a partial commit and keys from the working tree” written for this ledger (item 745)
turborepo#4227 exit:signal-death-exits-zero covered packages/vx/tests/signal-death.test.ts › “a SIGKILL the runner saw is named with the OOM killer and a kill”
turborepo#5298, turborepo#5454, turborepo#5098, turborepo#11056 exit:failure-reported-success covered packages/vx/tests/cli.test.ts › “exits 1 when a task fails”
turborepo#5403 exit:continue-runs-dependents-of-failed covered packages/vx/tests/parity-turbo.test.ts › “a failure skips its dependents and reds the run (Turbo --continue=dependencies-successful; vx default)”
turborepo#4504 exit:continue-failure-summary-missing covered packages/vx/tests/output-flow.test.ts › “deferred frames at runEnd: exactly one blank line between, one after”
turborepo#9693 exit:interrupt-code-not-tasks n/a docs/cli.md § vx run, exit-code table: 130 / 143 / 129 is “Interrupted (SIGINT / SIGTERM / SIGHUP)”.
turborepo#444, turborepo#9694, turborepo#10020, turborepo#4274 signal:sigint-not-forwarded fixed-in-item-740 packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a one-shot task as SIGINT”<br>packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a ready persistent task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT during the initial run reaches its task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT while idle reaches the dev server it holds as SIGINT”<br>packages/vx/tests/signal-handling.test.ts › “SIGTERM to vx reaches a one-shot task as SIGTERM” vx forwards the signal it received, SIGINT for Ctrl-C, where it sent SIGTERM for all.
turborepo#12652, turborepo#13097 signal:sigint-through-sh-wrapper fixed-in-item-740 packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a one-shot task as SIGINT”<br>packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a ready persistent task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT during the initial run reaches its task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT while idle reaches the dev server it holds as SIGINT” The task’s own sh now gets SIGINT, so its trap … INT runs.
turborepo#9666 signal:parent-sigkill-orphans-children fixed-in-item-860 packages/vx/tests/keep-alive-sigkill.test.ts › “a SIGKILLed vx takes an unsandboxed persistent task’s backgrounded server with it”<br>packages/vx/tests/keep-alive-sigkill.test.ts › “a SIGKILLed vx takes an unsandboxed one-shot task’s backgrounded child with it”<br>packages/vx/tests/sandbox-lifecycle.unsafe.test.ts › “a traced sandboxed one-shot task’s children die with vx”<br>packages/vx/tests/sandbox-lifecycle.unsafe.test.ts › “a sandboxed server’s backgrounded and setsid children die with vx”<br>packages/vx/tests/keep-alive.test.ts › “the stdin ends when vx is SIGKILLed, so a server that watches it goes too” A group guard (kill-tree.md, item 860): one sh per vx process reads a pipe only vx writes, lists each spawn’s process group while vx holds it, and SIGKILLs the listed groups when vx’s end closes. It is started at the first spawn, so a warm run pays nothing, and a 600-task cold run is a tie. A Linux sandboxed server already went with vx through --die-with-parent (item 801); a traced sandboxed one-shot, whose strace outlived vx, now goes too. What escapes is a process that left the group with setsid, unsandboxed. PR_SET_PDEATHSIG was measured and refused: +1.2 ms a spawn, and it kills only the process it is set on.
turborepo#1626 signal:sighup-orphans-children covered packages/vx/tests/task-tree-kill.test.ts › “SIGHUP to vx reaps the grandchild and exits 129”<br>packages/vx/tests/task-tree-kill.test.ts › “SIGHUP gives the grandchild its SIGTERM cleanup, not only a death”
turborepo#12786 signal:escaped-descendant-early-complete open (limit: packages/vx/docs/caching.md § Cache write) packages/vx/tests/runner.test.ts › “returns promptly when a backgrounded grandchild holds the pipe open (no hang)” docs/modules/kill-tree.md § What it does NOT do: “Reach a daemon that called setsid itself”. The outputs are what exists when the command exits (caching.md § Cache write); a descendant the command detached has left the process group vx tracks, so the command must wait for it.
turborepo#12920 signal:ctrl-c-no-exit covered packages/vx/tests/keep-alive.test.ts › “SIGINT after the summary exits 130 and takes the server down” written for this ledger (item 745)
turborepo#14043 signal:shutdown-output-after-exit covered packages/vx/tests/signal-handling.test.ts › “at the moment vx exits on a signal every task process is gone and its pipes are closed” written for this ledger (item 745)
turborepo#13907 output:unbounded-buffering covered packages/vx/tests/output-flow.test.ts › “the tail is bounded and says how much of the head it dropped”
turborepo#2564 output:prefix-colour-nondeterministic covered packages/vx/tests/framed-output.test.ts › “is the same escape in another process and in any discovery order” written for this ledger (item 745)
turborepo#897 output:replay-loses-colour n/a docs/schema.md § ExecEnv: “CI / FORCE_COLOR / TERM (stdout bytes, and vx caches and replays stdout)… if one does, say so explicitly” (fold it via inputs.env).
turborepo#8961 output:runner-noise-on-stderr covered packages/vx/tests/ci-output.test.ts › “a green run writes nothing to stderr: a miss and a hit, with CI set and without” written for this ledger (item 745)
turborepo#972 output:replay-notice-when-suppressed covered packages/vx/tests/output-flow.test.ts › “errors-only: success and hits silent, failures framed”
turborepo#10739 output:errors-only-empty-groups covered packages/vx/tests/output-flow.test.ts › “resolveOutputView attaches gha only when GITHUB_ACTIONS is truthy”
turborepo#9441 watch:output-mode-ignored covered packages/vx/tests/cli.test.ts › “re-runs the task after a file change, then exits on SIGINT”
turborepo#1319, turborepo#2939 filter:exclusion-vs-dependsOn n/a docs/cli.md § vx run: “By default only the project containing the current working directory is selected — dependsOn still expands so the project’s upstream workspace deps run too.”
turborepo#8672 filter:negation-drops-root-task covered packages/vx/tests/filter.test.ts › “a negated name or path keeps the root project” written for this ledger (item 745)
turborepo#9043 filter:path-glob-with-exclusion covered packages/vx/tests/filter.test.ts › “a path glob minus one path selects every other app and nothing else” written for this ledger (item 745)
turborepo#8599 filter:leading-dot-slash-path covered packages/vx/tests/filter.test.ts › “--filter ./apps/web selects the member pnpm-workspace.yaml lists as ./apps/*” written for this ledger (item 745)
turborepo#958 filter:no-match-runs-everything covered packages/vx/tests/parity-turbo.test.ts › “a --filter that matches no package refuses the run (Turbo: exits 1 too)”
turborepo#9277, turborepo#11428 select:cwd-inference-nondeterministic covered packages/vx/tests/cli.test.ts › “is the deepest project containing the cwd, the same on every run” written for this ledger (item 745)
turborepo#4107 filter:intermittent-task-omission covered packages/vx/tests/persistent.test.ts › “every one of thirteen persistent tasks a filter selects starts at concurrency 2” written for this ledger (item 745)
turborepo#1528 filter:changed-prefix-match covered packages/vx/tests/affected.test.ts › “a change in a sibling-prefix project dir selects exactly that project”
turborepo#1055 filter:changed-selects-nothing covered packages/vx/tests/parity-turbo.test.ts › “--filter=[HEAD~1] selects the packages with changed files since a ref”
turborepo#1333 filter:changed-root-package-not-found covered packages/vx/tests/affected.test.ts › “still selects the importer one hop out”
turborepo#11409, turborepo#12594 filter:git-range-mishandled covered packages/vx/tests/affected.test.ts › “refuses the range %j before git sees it”
turborepo#9096 filter:name-plus-git-unchanged-errors n/a docs/cli.md § Filter DSL lists [<git-ref>] only as its own selector (“Projects whose files changed since <git-ref>”).
turborepo#9234, turborepo#1609 filter:changed-omits-dependents covered packages/vx/tests/affected-dependents.test.ts › “an edit to lib selects lib AND app, never tool”
turborepo#3432 filter:since-merge-base-vs-direct-diff n/a docs/cli.md § --affected: “The diff runs from the merge base of the ref and HEAD, not from the ref itself, so a branch whose base has moved on sees only its own changes — never the files other people landed on main since it forked (Turbo and Nx do the same).”
turborepo#3965 filter:changed-includes-unchanged covered packages/vx/tests/affected.test.ts › “ignores changes outside any project directory”
turborepo#9578 filter:root-by-name covered packages/vx/tests/filter.test.ts › “the root project is selected by its name, and …name adds its dependents” written for this ledger (item 745)
turborepo#13636 affected:filter-not-applied-to-tasks n/a docs/cli.md § Selection: “Combining: every include (--filter <pat>, --affected) is taken first and every ! exclude after them all, as pnpm does, so an exclude removes what any include added, whichever side of it it sits (items 955, 979).”
turborepo#4559, turborepo#9208 affected:shallow-clone-missing-object covered packages/vx/tests/affected-base-notes.test.ts › “in a real depth-2 clone, --affected=HEAD~1 and …[HEAD^] select the change and its dependents” written for this ledger (item 745)
turborepo#9320, turborepo#12650 affected:base-ref-only-remote covered packages/vx/tests/affected.test.ts › “the remote’s HEAD branch names the base branch when origin/HEAD is set”
turborepo#10862, turborepo#10688 affected:unrelated-packages-selected covered packages/vx/tests/affected-dependents.test.ts › “an edit to lib selects lib AND app, never tool”
turborepo#10869, turborepo#11144 affected:root-manifest-change-selects-all covered packages/vx/tests/affected.test.ts › “an unclaimed root file does not widen”
turborepo#2862, turborepo#8125 affected:lockfile-change-selects-all covered packages/vx-lockfile/tests/pnpm.test.ts › “--affected selects the projects the bump reaches”
turborepo#12635 affected:lockfile-delta-catalog fixed-in-item-747 packages/vx-lockfile/tests/yarn.test.ts › “a catalog bump ^6 → ^7 moves the workspace that names catalog: and what links it”<br>packages/vx-lockfile/tests/yarn.test.ts › “a bump inside the catalog range moves the workspace that names catalog:”<br>packages/vx-lockfile/tests/yarn.test.ts › “a named catalog (catalog:<name>) reaches the entries of its package”<br>packages/vx-lockfile/tests/yarn.test.ts › “a scoped package named by a catalog reaches its entries”<br>packages/vx-lockfile/tests/yarn.test.ts › “a bump inside the catalog range re-keys and selects the projects that reach it”<br>packages/vx-lockfile/tests/yarn.test.ts › “a catalog flip the lockfile does not record re-keys and selects every project”<br>packages/vx-lockfile/tests/pnpm.test.ts › “a catalog bump moves the importer that names catalog: and no other (turborepo#12635)”<br>packages/vx-lockfile/tests/bun.test.ts › “a catalog bump moves the workspace that names catalog: (turborepo#12635, D-141)” Writing the row found the bug: yarn.lock records a Yarn 4 catalog dependency as "catalog:", not its range, so yarn() reached no entry (a bump inside the range was a stale hit), and a catalog flip to a range the file already resolved left it byte-identical, a stale hit. yarn() now reaches every entry of the package, and claims .yarnrc.yml, folding it whole. pnpm and Bun catalogs were already right; the last two rows pin them.
turborepo#14151 affected:root-internal-dep-change n/a docs/caching.md step 9: core keys no root file; a lockfile plugin keys each project on its own closure and the root’s.
turborepo#12512 affected:upstream-deps-dropped covered packages/vx/tests/parity-turbo.test.ts › “--filter=app selects by package name; dependsOn still pulls its builds in”
turborepo#13790 affected:commandless-task-omitted n/a docs/cli.md § --affected: “It selects the CHANGED projects and their dependents.” Selection is per project, never per task.
turborepo#14149 affected:negated-global-glob-ignored covered packages/vx/tests/affected.test.ts › “honours a leading ! as an EXCLUDE, like resolveWorkspaceFiles”
turborepo#14130 affected:dot-slash-input-glob covered packages/vx/tests/affected.test.ts › “reads a spelling the way the KEY reads it, or --affected skips a stale project”
turborepo#12947, turborepo#12329, turborepo#12338 affected:root-relative-input covered packages/vx/tests/affected-workspace-files.test.ts › “the change re-keys the task AND selects it”
turborepo#7245 graph:deleted-package-stale covered packages/vx/tests/orchestrator-run.test.ts › “a project deleted after a warm run and a lock is named by the next run until a re-lock” written for this ledger (item 745)
turborepo#2517 graph:symlinked-package-dir covered packages/vx-migrate/tests/packages.test.ts › “a member directory that is a symlink to a package outside the glob is discovered” written for this ledger (item 745)
turborepo#3766 graph:negated-workspace-glob fixed-in-item-742 packages/vx-migrate/tests/packages.test.ts › “an extglob member pattern is refused by name, not widened (turborepo#3766)” Bun.Glob has no extglob, so every extglob form in a member glob is refused by name, with the ! rewrite for a whole-segment negation.
turborepo#8673 watch:deps-first-run-not-awaited n/a docs/cli.md § vx watch › Lifecycle: “Initial run. Same code path as vx run — same scope resolution, same task graph, same cache behaviour.”
turborepo#12433, turborepo#12505 watch:mixed-interruptible-stall n/a docs/cli.md § vx watch › Constraints: “Persistent tasks (exec.persistent) re-spawn each cycle.”
turborepo#9421, turborepo#9328 watch:interruptible-killed-not-restarted fixed-in-item-740 packages/vx/tests/watch-loop.test.ts › “the dev server stays up across cycles and is replaced when its locked config changes” The held server outlives its cycle: it stays up while watch idles and across later cycles.
turborepo#13115 watch:out-of-inputs-change-kills fixed-in-item-740 packages/vx/tests/watch-loop.test.ts › “the dev server stays up across cycles and is replaced when its locked config changes” On vx the same fault as the row above: the server stopped at the end of each cycle, so it was down whenever watch sat idle.
turborepo#12501, turborepo#8164 watch:upstream-build-not-rerun covered packages/vx/tests/watch-loop-members.test.ts › “a --filter scope watches its upstream dependencies too: a lib edit is one cycle that rebuilds both”
turborepo#12654 watch:upstream-rerun-on-downstream-change covered packages/vx/tests/watch-loop.test.ts › “the dev server stays up across cycles and is replaced when its locked config changes” A cycle keeps a server still up whose task is unchanged and re-runs only what it depends on: an edit restarts no server (docs/cli.md § vx watch › Constraints).
turborepo#12087, turborepo#10960 watch:outputs-retrigger-loop covered packages/vx/tests/watch-rules.test.ts › “drops a task’s own declared outputs, under either watcher, and nothing beside them”
turborepo#13402 watch:ignored-dir-burst-reruns covered packages/vx/tests/watch-loop-selfwrite.test.ts › “git-ignored, it never starts a cycle: the edit cycle and its follower, then quiet”
turborepo#8932 watch:subdir-root-spurious-reruns covered packages/vx/tests/git-subdir-workspace.test.ts › “git writing its own directory runs no cycle, and an input edit still does” written for this ledger (item 745)
turborepo#11118, turborepo#13925 watch:root-input-change-missed covered packages/vx/tests/watch-loop-members.test.ts › “under the root watcher, a root file no key can see is not a cycle; a declared one is”
turborepo#9463 watch:atomic-save-missed covered packages/vx/tests/watch-loop-edits.test.ts › “an atomic save by rename is one cycle with the new content, three saves in a row” written for this ledger (item 745)
turborepo#9531 watch:single-package-repo covered packages/vx/tests/watch-loop.test.ts › “runs, watches, and re-runs once on an edit” written for this ledger (item 745)
turborepo#10122 watch:persistent-failure-no-exit n/a docs/cli.md § vx watch › Exit codes: “Re-run cycles whose orchestrator returns { ok: false } do NOT exit the watch loop — a failed cycle just prints the framed FAILED block and waits for the next change.”
turborepo#8802, turborepo#10353 env:strict-mode-drops-inherited-vars covered packages/vx/tests/env.test.ts › “TMPDIR, TMP and TEMP reach the task unchanged, and what the task exports reaches its children” written for this ledger (item 745)
turborepo#9659 env:passthrough-wildcard-merge n/a packages/vx/tests/config-schema-refusals.test.ts › “an env name that no environment can hold is refused in every list” A wildcard in passThrough is refused at load (item 1090; schema.md § ExecEnv), and there is no workspace env layer to merge.
turborepo#11192 env:relative-path-resolved-per-task n/a Of the variables docs/cli.md § Environment variables vx reads lists, only VX_RUN_WORKSPACE holds a path, and vx sets it absolute; --cache-dir is resolved once, relative to cwd.
issue class verdict vx test note
nx#27965 stale-hit:key-before-upstream-runs covered packages/vx/tests/stale-hit-memo.test.ts › “a wiped output stops counting as a consumer input on the cache-miss path”
nx#32214, nx#33379, nx#29685 stale-hit:upstream-cascade covered packages/vx/tests/orchestrator.test.ts › “an edit two hops upstream misses the whole chain and reaches the top output” written for this ledger (item 745)
nx#36908, nx#36239 stale-hit:external-deps-upstream covered packages/vx-lockfile/tests/pnpm.test.ts › “a bump behind a link: re-keys the linking project too”
nx#22664, nx#29074 stale-hit:tool-version covered packages/vx-lockfile/tests/pnpm.test.ts › “a dependency bump re-keys only the projects that reach it”
nx#36902 stale-hit:undeclared-machine-state n/a CLAUDE.md principle 2: “Explicit over magical. Caching is opt-in; inputs.files is required; no inferred inputs”.
nx#33684, nx#35934 restore:non-relocatable-outputs n/a The key is path-independent by design (see nx#7692).
nx#7692 key-unstable:checkout-path covered packages/vx/tests/cache-dir-selection.test.ts › “the second checkout, at another and longer path, restores what the first saved” written for this ledger (item 745)
nx#36675 stale-hit:shared-cache-worktree covered packages/vx/tests/git-subdir-workspace.test.ts › “a worktree sharing the cache directory misses on its own edit and never replays main” written for this ledger (item 745)
nx#18289, nx#18866, nx#33781, nx#34528 stale-hit:file-hash-memo covered packages/vx/tests/stale-hit-memo.test.ts › “a content change that preserves mtime is not served from the file-hash memo”<br>packages/vx/tests/watch-loop-edits.test.ts › “a git checkout that rewrites twenty inputs is one cycle with the new content (L5)”
nx#23106 stale-hit:path-not-in-key covered packages/vx/tests/stale-hit-git.test.ts › “renaming an input misses and back again restores only the outputs of that name” written for this ledger (item 745)
nx#16270, nx#31574 stale-hit:gitignored-input covered packages/vx/tests/ignored-inputs.test.ts › “a literal naming a gitignored file is an input: missing, then created, then edited, each moves the key”
nx#19796 inputs:gitignore-unignore covered packages/vx/tests/orchestrator-run.test.ts › “gitignore: a directory re-included under an ignored parent is an input, its ignored siblings are not” written for this ledger (item 745)
nx#19392, nx#20216, nx#31067, nx#29824 stale-hit:dotenv n/a packages/vx/docs/modules/env.md § What this does NOT do: “Doesn’t read from .env files or anywhere except source.”
nx#21390 stale-hit:env-undeclared covered packages/vx/tests/orchestrator.test.ts › “undeclared env vars do not leak to the child”
nx#30170 stale-hit:runtime-input covered packages/vx/tests/runtime-inputs.test.ts › “runtime output change invalidates the cache (re-executes)”
nx#36629 stale-hit:config-subset n/a caching.md § What’s NOT in the key: “Workspace-root configs (tsconfig.base.json, etc.) are not auto-included — declare them via inputs.workspaceFiles”.
nx#34595 stale-hit:input-token-interpolation n/a schema.md inputs.workspaceFiles: “Workspace-root-relative globs — the Turbo $TURBO_ROOT$ / Nx {workspaceRoot} equivalent”.
nx#26880 stale-hit:glob-dialect n/a schema.md: “The wildcards are *, **, ? and a brace set {a,b}.” “This holds for every task glob … and for everything read from them (--affected, vx watch, the overlapping-output refusal).”
nx#36845 stale-hit:glob-literal-at n/a @ is no wildcard in a task glob: GLOB_WILDCARDS (src/util/paths.ts) is *?{}, and Bun.Glob has no extglob, so @ matches itself. No test pins it.
nx#34225, nx#31264 inputs:nested-project n/a CLAUDE.md principle 6: “Project boundaries are hard. Globs never cross into another project.” caching.md invalidation table: a change in a nested project’s dir is “NOT a trigger for the parent’s files globs”.
nx#11642 inputs:negation-token covered packages/vx/tests/workspace-files.test.ts › “supports ! negation”<br>packages/vx/tests/orchestrator.test.ts › “negation glob in inputs excludes matched files from the cache key”
nx#28047 inputs:negation-implicit n/a caching.md: core keys no package file; @vzn/vx-lockfile lists package.json as an input of every cached task.
nx#30980 inputs:negation-overridden n/a CLAUDE.md principle 2 (“no inferred inputs”) and Rejected: “Named inputs / globalInputs / globalEnv (TS configs compose)”.
nx#22277, nx#26915, nx#14217, nx#29101 key-overbroad:lockfile covered packages/vx-lockfile/tests/pnpm.test.ts › “a dependency bump re-keys only the projects that reach it”
nx#36951 key-unstable:node_modules-layout n/a caching.md step 9: a lockfile plugin folds the root lockfile and install settings (.npmrc, bunfig.toml, .yarnrc.yml), never node_modules.
nx#20929 key-unstable:platform-optional-deps n/a Same as the previous row, and caching.md § What’s NOT in the key: “Node / Bun / OS / build-tool versions — unless you declare them.”
nx#22248 key-unstable:stale-dep-graph covered packages/vx-lockfile/tests/pnpm.test.ts › “a warm run reads the memo instead of parsing”
nx#35234, nx#18198, nx#16153, nx#35855 key-unstable:run-context fixed-in-item-741 packages/vx/tests/exclude-dependencies-key.test.ts › “the dependant has one key with and without the flag, and it hits”<br>packages/vx/tests/exclude-dependencies-key.test.ts › “a change to the skipped dependency is a miss, not the old bytes”<br>packages/vx/tests/exclude-dependencies-key.test.ts › “what a run builds on a skipped, out-of-date dependency is not saved”<br>packages/vx/tests/taint-tracker.test.ts › “a seed is tainted with no failure upstream, and passes it on” --exclude-dependencies narrows the schedule, not the key: a skipped dependency is keyed without running, and what builds on it may hit but does not save.
nx#36939 key-unstable:config-mutation covered packages/vx/tests/orchestrator.test.ts › “runs a task and caches the result”<br>packages/vx/tests/orchestrator-run.test.ts › “forwardArgs do NOT pollute upstream cache keys (dep stays cached across user-args changes)”
nx#35297 key-unstable:key-order covered packages/vx/tests/config-eval.test.ts › “a faithful config crosses both paths with the same JSON, the bytes its key includes”<br>packages/vx/tests/plugin-pipeline.test.ts › “the fold is order-independent: two plugins key the same whichever is declared first”
nx#27880 key-unstable:file-metadata covered packages/vx/tests/git-oid.test.ts › “edit changes the key; reverting restores the ORIGINAL key before any commit”<br>packages/vx/tests/cache.test.ts › “does not change when only mtime changes (content identical)”
nx#26749 key-unstable:output-in-inputs covered packages/vx/tests/orchestrator.test.ts › “does not self-invalidate when only its declared outputs change”
nx#33076 key-collision:memo covered packages/vx/tests/orchestrator-run.test.ts › “sibling-package input isolation: editing one package does not bust an unrelated sibling”
nx#36968 stale-hit:config-eval-cache covered packages/vx/tests/config-staleness.test.ts › “a re-run in the same process does not serve a cache hit for a changed preset”
nx#35228 inputs:special-file covered packages/vx/tests/inputs.test.ts › “neither hangs the run nor enters the key or the artifact” written for this ledger (item 745)
nx#6370 inputs:deleted-file covered packages/vx/tests/inputs.test.ts › “deleted-but-tracked files are skipped (existsSync guard)”
nx#37110, nx#36898 restore:index-without-artifact covered packages/vx/tests/cache.test.ts › “get() returns null when DB row exists but on-disk artifact was deleted”
nx#36932 restore:partial-record covered packages/vx/tests/aborted-outcome.test.ts › “does not let its dependents cache what they built from its partial outputs”<br>packages/vx/tests/cache-hygiene.test.ts › “SIGTERM mid-task → no entries row, no live or tmp artifact”
nx#32620, nx#22166, nx#18494 restore:skip-on-stale-tracking covered packages/vx/tests/parity-turbo.test.ts › “a second run is a cache hit; deleted outputs come back from the cache; logs replay”<br>packages/vx/tests/orchestrator.test.ts › “restores a deleted output file on a cache hit”
nx#30429, nx#31191 remote:downloaded-not-restored covered packages/vx-migrate/tests/nx-cache.test.ts › “a miss uploads; with the local cache wiped the next run restores from the server”
nx#31568, nx#36401 restore:outside-workspace covered packages/vx/tests/project-loader.test.ts › “rejects .. in outputs.workspaceFiles (escapes the workspace root)”
nx#37061 restore:symlink-dir fixed-in-item-742 packages/vx/tests/restore-link-out.test.ts › “is refused by name, the link kept and nothing written through it” An output directory that links out of the project is a user error naming the link and its target; the link is kept, never replaced or written through.
nx#31085 restore:symlinks-dropped covered packages/vx/tests/output-shape.test.ts › “a symlink to a directory, or a dangling one, is cached and comes back as the link”
nx#32996 restore:dir-permissions covered packages/vx/tests/archive-security.test.ts › “directory records with 0644 or 0600 modes never set a directory mode; the file under them lands” written for this ledger (item 745)
nx#34013 restore:glob-and-dir-collision covered packages/vx/tests/artifact-roundtrip.test.ts › “overlapping output globs and directory literals save and restore the exact tree once” written for this ledger (item 745)
nx#35150 outputs:negation covered packages/vx/tests/negated-outputs.test.ts › “is left in place by a miss and kept out of the entry”<br>packages/vx/tests/negated-outputs.test.ts › “is left in place by a hit, which restores the rest”
nx#18075 outputs:glob-extension covered packages/vx/tests/artifact-roundtrip.test.ts › “an output glob with a brace extension set captures those extensions and restores them” written for this ledger (item 745)
nx#35817 restore:non-atomic covered packages/vx/tests/run-lock-e2e.test.ts › “the race of item 215 cannot start: cold outputs, warm cache, two runs, four rounds”
nx#35079 restore:tool-incremental-state covered packages/vx/tests/orchestrator.test.ts › “--force skips reads (re-executes) but still WRITES, refreshing the cache”<br>packages/vx/tests/orchestrator-run.test.ts › “cache-miss exec also cleans declared outputs before running”
nx#36113 outputs:overlap-shared-file covered packages/vx/tests/output-collision.test.ts › “refuses the same workspace output claimed by tasks in DIFFERENT projects”
nx#36949 restore:undeclared-side-effect n/a CLAUDE.md principle 2 (“Explicit over magical … the sandbox, exec.sandbox, is how a task proves what it touches”).
nx#35403 cache:artifacts-without-index covered packages/vx/tests/cache.test.ts › “is indexed from its bytes and hits, restoring its outputs” written for this ledger (item 745)
nx#36863, nx#35302 replay:truncated-output covered packages/vx/tests/runner.test.ts › “a grandchild that prints within the post-exit drain reaches the live stream and the result” written for this ledger (item 745)
nx#36688 replay:missing-log-fatal fixed-in-item-742 packages/vx/tests/vanished-artifact.test.ts › “probed in its own slot: runs there” An artifact gone between the probe and the restore is a miss (ArtifactVanishedError) and the task runs. The restore-tier rows (a demoted restore runs after its dependency) are template-titled.
nx#36928 evict:orphan-log n/a caching.md § Storage layout: “one entry is one file — eviction is a single unlink; no per-entry manifest, no separate logs/ tree”.
nx#35483 evict:orphan-artifact fixed-in-item-742 packages/vx/tests/cache-prune-policy.test.ts › “reaps row-less artifacts, whatever the index says”<br>packages/vx/tests/cache-clean-verb.test.ts › “a dry run deletes nothing and says what it would reap; the real one reaps it” vx cache clean sweeps artifacts with no index row.
nx#35329 evict:shared-unbounded covered packages/vx/tests/cache-clean-verb.test.ts › “evicts from a cache directory outside the workspace, named by --cache-dir” written for this ledger (item 745)
nx#34032 evict:concurrent-race fixed-in-item-742 packages/vx/tests/run-lock-e2e.test.ts › “vx cache clean waits for a run on the workspace before it evicts”<br>packages/vx/tests/vanished-artifact.test.ts › “probed in its own slot: runs there” A deleting vx cache clean takes the workspace’s run lock; another workspace’s retention on a shared --cache-dir turns the hit into a miss.
nx#28608, nx#28665, nx#28772, nx#28424 concurrency:index-db fixed-in-item-742 packages/vx/tests/cache-open-busy.test.ts › “a version row another opener is committing is read, not inserted twice” Two openers of a new cache: the write half re-reads the schema version under BEGIN IMMEDIATE.
nx#35901 cache:failed-result n/a caching.md § Cache write: “If the task exits non-zero, nothing is cached. This is deliberate”.
nx#32610 cache:name-special-case fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “persistence is Nx’s continuous, never the target name: a cached dev caches like gen (nx#32610)”
nx#29854 cli:skip-cache-scope covered packages/vx/tests/orchestrator.test.ts › “--force, --no-cache and --cache-policy=local:w re-execute the dependencies of the named task too” written for this ledger (item 745)
nx#37052, nx#36107 remote:store-error-fails-run covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a 500 on every request degrades to a miss — the task runs and the run is green”<br>packages/vx/tests/layered-cache.test.ts › “save() does not fail when the remote rejects”
nx#36036, nx#31134 remote:error-not-miss covered packages/vx/tests/layered-cache.test.ts › “get() suppresses remote errors and returns null”<br>packages/vx/tests/orchestrator-remote.test.ts › “a remote that 500s on every request never fails the run (optional cache degrades to miss)”
nx#30338 remote:corrupt-entry-sticky covered packages/vx-migrate/tests/remote-cache-degrade.test.ts › “a corrupt artifact degrades to a miss — never a half-restored output”<br>packages/vx/tests/layered-cache.test.ts › “get() degrades a corrupt remote artifact to a miss instead of throwing”<br>packages/vx/tests/vanished-artifact.test.ts › “is dropped and the task runs; the next run is a hit”
nx#36943, nx#30335 remote:large-upload covered packages/vx/tests/artifact-ceiling.test.ts › “is refused at save with one status line, the run green, nothing cached”<br>packages/vx/tests/artifact-ceiling.test.ts › “an ingest enforces it too: remote bytes past it never land” Written for this ledger (item 800): the ceiling is RunOptions.artifactCeiling, a seam only a test sets, and a save refuses a tar past it before it compresses a byte (one stat per output), where the scan used to pay the whole compress and a decode (6 to 14 s on the 2.2 GB probe) and call the outputs corrupt.
nx#33092, nx#30018 remote:protocol-headers fixed-in-item-736 packages/vx-migrate/tests/nx-cache.test.ts › “put → get round trip; a miss is 404 → null; a second put of the same hash is the spec’s 409 and fine”<br>packages/vx-migrate/tests/turbo-cache.test.ts › “put → has / hasMany / get round trip with the spec’s headers and query”
nx#33335, nx#31535 remote:read-only-ignored covered packages/vx/tests/layered-cache.test.ts › “save() with remote writes off uploads nothing: local entry, no remote PUT”<br>packages/vx/tests/cache.test.ts › “local:rw,remote:r → remote read-only (local stays rw)”
nx#35556 remote:store-race-local-write covered packages/vx/tests/layered-cache.test.ts › “save() resolves before a slow remote PUT completes; drainUploads() completes it”
nx#30733 remote:restore-enoent covered packages/vx/tests/artifact-roundtrip.test.ts › “a cache hit restores the produced tree byte- and mode-identically”<br>packages/vx-migrate/tests/nx-cache.test.ts › “a miss uploads; with the local cache wiped the next run restores from the server”
nx#36640 remote:hang-inherited-stdio n/a caching.md § Remote uploads: “the remote PUT is a fire-and-forget background upload … drained before cache.close(), so a short run still ships every artifact before the process exits”.
nx#32779 graph:missing-dep-silent fixed-in-item-737 packages/vx/tests/task-graph.test.ts › “refuses ^biuld when no project in the workspace declares biuld”
nx#36498 graph:dep-name-glob-chars covered packages/vx/tests/task-graph.test.ts › “names holding brackets and slashes are literal, exact or inside a pattern” written for this ledger (item 745)
nx#16931 graph:dep-name-ambiguity n/a vx/docs/schema.md § dependsOn: “'name' — Same-project task name” and “'pkg#name' — The name task in a specific other package”.
nx#33716, nx#29735, nx#27679 graph:false-cycle covered packages/vx/tests/task-graph.test.ts › “dedupes diamond dependency: shared upstream node is created once”
nx#28788 graph:cycle-stack-overflow fixed-in-item-737 packages/vx/tests/task-graph.test.ts › “a 50,000-deep chain plans”<br>packages/vx/tests/task-graph.test.ts › “a 50,000-deep ring is refused as that cycle”
nx#33974 graph:lockfile-edges-cycle n/a vx/docs/schema.md § dependsOn: “'^name' — nearest-holder frontier. Walk the package dep graph from this project’s direct deps”. An edge is a package.json workspace dependency (cli.md § Filter DSL), never a lockfile entry.
nx#28599 graph:dep-order-parallel covered packages/vx/tests/scheduler.test.ts › “runs tasks in dependency order”
nx#26929 graph:override-drops-deps n/a vx/docs/comparison.md: “Target defaults / inheritance” is “rejected by design — presets are TS imports”.
nx#36489 graph:defaults-merge n/a Same as nx#26929: target defaults are rejected by design (vx/docs/comparison.md), and nx() reads Nx’s resolved graph.
nx#14234 graph:missing-target-run-many covered packages/vx/tests/task-selection.test.ts › “a bogus BARE task fails the run even when another task resolves”
nx#16147, nx#18437, nx#11984 graph:params-forward n/a vx/docs/cli.md § Argument forwarding: “They scope to user-requested tasks only; dependsOn-pulled deps don’t see them (so upstream cache identity stays clean).”
nx#31496 continuous:readiness covered packages/vx/tests/persistent.test.ts › “downstream task waits for persistent upstream to become ready”
nx#31494, nx#34117 parallel:limit-continuous covered packages/vx/tests/persistent.test.ts › “at concurrency 1 the dependents of a ready persistent task run one at a time” written for this ledger (item 745)
nx#27986 continuous:killed-when-dependent-starts covered packages/vx/tests/persistent.test.ts › “a ready persistent upstream is alive while its dependent runs” written for this ledger (item 745)
nx#33460, nx#32438 signal:orphan-continuous covered packages/vx/tests/signal-handling.test.ts › “the child of a persistent task that traps TERM, INT and HUP is dead after SIGINT or SIGTERM to vx” written for this ledger (item 745)
nx#36682 signal:terminal-hangup covered packages/vx/tests/task-tree-kill.test.ts › “SIGHUP to vx reaps the grandchild and exits 129”
nx#11782 signal:orphan-child-kill covered packages/vx/tests/task-tree-kill.test.ts › “SIGTERM to vx reaps the grandchild and exits 143”<br>packages/vx/tests/task-tree-kill.test.ts › “a timeout reaps a grandchild that ignores SIGTERM”<br>packages/vx/tests/runner.test.ts › “a timed-out shell that dies on the SIGTERM: settle() SIGKILLs the grandchild that ignored it” Item 740 fixed the timeout sibling: a timed-out shell’s exit cleared the SIGKILL, so a grandchild ignoring SIGTERM outlived vx.
nx#23585 signal:graceful-shutdown fixed-in-item-740 packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a one-shot task as SIGINT”<br>packages/vx/tests/signal-handling.test.ts › “SIGINT to vx reaches a ready persistent task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT during the initial run reaches its task as SIGINT”<br>packages/vx/tests/watch-signals.test.ts › “SIGINT while idle reaches the dev server it holds as SIGINT”<br>packages/vx/tests/signal-handling.test.ts › “SIGTERM to vx reaches a one-shot task as SIGTERM” vx forwards the signal it received, so a SIGINT-only cleanup runs.
nx#27917 signal:kill-during-start n/a vx/docs/design/roadmap-1.0.md Milestone 2, row 2.4: “Record the out-of-scope set as final: daemon, JS-function tasks, generators, TUI, …”.
nx#36473 signal:stale-marker-after-kill fixed-in-item-740 packages/vx/tests/run-lock.test.ts › “a lock naming this process’s own pid is stale: a restarted container’s vx wears it”<br>packages/vx/tests/run-lock-recycled.unsafe.test.ts › “a lock whose pid another process now wears is stale: the start time differs” A run lock naming our own pid, or on Linux a pid another process now wears, is stale.
nx#32750 signal:hang-no-tty covered packages/vx/tests/ci-output.test.ts › “colour and no other escape or carriage return, on a miss, a hit, a failure, and the readers”
nx#36579 signal:hang-foreign-pty n/a vx/docs/design/roadmap-1.0.md Milestone 2, row 2.4 lists TUI in the out-of-scope set.
nx#8286 signal:hang-at-exit fixed-in-item-740 packages/vx/tests/task-tree-kill.test.ts › “a persistent dependency’s server that ignores SIGTERM does not hang vx’s exit”<br>packages/vx/tests/task-tree-kill.test.ts › “a grandchild’s SIGTERM cleanup gets the grace after its shell has exited” Both teardowns SIGKILL every task group with a member left at the grace, not only the shell.
nx#29204 exit:signal-death-success covered packages/vx/tests/signal-death.test.ts › “a SIGKILL the runner saw is named with the OOM killer and a kill”
nx#28477, nx#20285 run-commands:parallel-exit fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “commands run in parallel: a failing check fails the task while the server beside it is up, and TERMs it (nx#28477)”
nx#31307, nx#36520 output:pty-swallow covered packages/vx/tests/output-flow.test.ts › “failure → full frame with the buffered output”
nx#26553 affected:bad-base-exit covered packages/vx/tests/affected.test.ts › “throws UserError when the ref does not resolve”
nx#14202 exit:exec-nonzero n/a vx/src/util/verbs.ts CORE_VERBS has no exec.
nx#35169 run-commands:child-restart-exit n/a vx/docs/execution.md § One command per task: “exec.command is a single shell command — there’s no multi-step sequence.”
nx#21779 run-commands:sequential-hang covered packages/vx-migrate/tests/nx-command.test.ts › “serial: one command’s exit or cd stays in its own shell, and a failure stops the rest”
nx#31345 run-commands:empty-list fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “commands: [] is a no-op that succeeds (nx#31345)”
nx#12165 run-commands:args-forward fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “arguments after vx run … -- reach every command, and an executor target’s options (nx#12165)”<br>packages/vx-migrate/tests/nx-command.test.ts › “forwarded arguments reach EVERY command, and none when forwardAllArgs is off (nx#12165)”
nx#36652 run:exec-cwd n/a vx/src/util/verbs.ts CORE_VERBS has no exec.
nx#32579 run:package-manager-detect n/a vx-migrate/README.md: “nx:run-script is the package’s script body with its pre<name> / post<name> hooks folded in (or yarn run <name> when the body calls yarn’s run builtin; …)”.
nx#35302, nx#36863 output:lost-on-exit fixed-in-item-740 packages/vx/tests/runner.test.ts › “output a backgrounded child writes after the drain bound is cut, and the frame says so” The post-exit drain bound stays; when it cuts output, the frame says so.
nx#27968 output:truncated-pipe covered packages/vx/tests/bin-stdout.test.ts › “a JSON answer past the pipe buffer parses whole”
nx#31237 output:truncated-large covered packages/vx/tests/capture-cap.test.ts › “a hit replays the bounded text with the line, never the whole output”
nx#13540 output:partial-line n/a vx/docs/execution.md § Output capture and rendering: “Stdin is never the terminal”. A one-shot task “gets 'ignore'”; a persistent task “gets a pipe vx holds and never writes”.
nx#5472 output:stderr-lost covered packages/vx/tests/output-flow.test.ts › “failure → full frame with the buffered output”
nx#35292, nx#34387 color:force-color-override fixed-in-item-737 packages/vx/tests/ci-output.test.ts › “FORCE_COLOR=0 and =false leave the piped run plain, and reach the task as set”
nx#23259 color:forced-without-tty n/a packages/vx/tests/terminal.unsafe.test.ts › “vx on a terminal sets FORCE_COLOR=1 for a task, and NO_COLOR keeps it unset” The owner chose Nx’s behaviour (2026-10-03, E-103): vx forces colour on a task and strips it where it prints plain. A task writing its output to a file sets FORCE_COLOR: '0'.
nx#9673, nx#8051, nx#10918 color:lost-in-nested n/a packages/vx/tests/recursive-run.test.ts › “is refused in the task’s own workspace, naming the task” A nested vx run in the task’s own workspace is refused. cli.md § Output format › Colors: a task sees FORCE_COLOR=1 unless it already sees FORCE_COLOR or NO_COLOR.
nx#15116, nx#14891, nx#22259, nx#34742, nx#29101 affected:lockfile-all covered packages/vx-lockfile/tests/pnpm.test.ts › “--affected selects the projects the bump reaches”
nx#36929 affected:lockfile-transitive covered packages/vx-lockfile/tests/pnpm.test.ts › “a transitive bump moves the importers that reach it and no other”
nx#35524 affected:lockfile-catalog n/a A lockfile plugin keys each project on its own closure, but a catalog edit re-keys and selects every project: the catalog lives in a file the plugin folds whole (pnpm-workspace.yaml, .yarnrc.yml; modules/fingerprint.md § Claiming a file), and bun() folds bun.lock’s catalogs into every project.
nx#35173 affected:lockfile-resolutions covered packages/vx-lockfile/tests/yarn.test.ts › “a transitive bump moves the workspaces that reach it and no other”
nx#36415 affected:root-devdep-global fixed-in-item-733 packages/vx-lockfile/tests/pnpm.test.ts › “a root devDependency bump re-keys and selects every project: the root .bin is on every PATH”
nx#18112, nx#20691 affected:deleted-project covered packages/vx/tests/affected.test.ts › “a deleted project directory selects no remaining project” written for this ledger (item 745)
nx#29699 affected:deleted-file-all covered packages/vx/tests/affected.test.ts › “selects the project that owned a deleted file”
nx#21763 affected:root-scoped-input covered packages/vx/tests/affected.test.ts › “a glob a plugin gave a config-less package selects it; a sibling without one is not selected”
nx#27182 affected:cross-root-input covered packages/vx/tests/affected-workspace-files.test.ts › “the change re-keys the task AND selects it”
nx#32974 affected:interpolated-input n/a vx/docs/parity.md: “namedInputs, targetDefaults, {projectRoot} tokens, .env auto-loading, tags” are “≠ rejected: TypeScript configs compose by import”.
nx#33330 affected:explicit-base-ignored covered packages/vx/tests/affected-base-notes.test.ts › “an explicit base never asks git for origin/HEAD or main, and no git error is printed” written for this ledger (item 745)
nx#11840, nx#12203, nx#29051 affected:missing-base-ref covered packages/vx/tests/affected-base-notes.test.ts › “no origin/HEAD and no parent commit: no base at all, exit 1”
nx#16975 affected:large-diff-buffer covered packages/vx/tests/affected.test.ts › “six thousand changed files, over a megabyte of paths, select their project and no other” written for this ledger (item 745)
nx#21319 affected:files-list n/a vx/docs/cli.md documents no --files.
nx#7177, nx#6370, nx#15819 affected:deleted-file-enoent covered packages/vx/tests/inputs.test.ts › “deleted-but-tracked files are skipped (existsSync guard)”<br>packages/vx/tests/affected.test.ts › “selects the project on a working-tree delete (uncommitted)”
nx#36576, nx#21991 affected:hang n/a vx/docs/design/roadmap-1.0.md Milestone 2, row 2.4: “Record the out-of-scope set as final: daemon, JS-function tasks, generators, TUI, …”.
nx#15625 discovery:dir-name-pattern covered packages/vx-migrate/tests/packages.test.ts › “a directory named __generated__ or _generated is a project like any other” written for this ledger (item 745)
nx#19981 discovery:workspace-globs-negation covered packages/vx-migrate/tests/packages.test.ts › “globs that are only negations list no project and do not throw” written for this ledger (item 745)
nx#36290 discovery:root-project-deps n/a written for this ledger (item 745); core reads no manifest edge since the language-agnostic core’s PR 3: edges are what the lockfile plugin reads the manager installed, the root importer’s as any other (packages/vx-lockfile/tests/discover-parity.test.ts, root → lib, in a loop titled by manager)
nx#27368, nx#34626 discovery:new-project-invisible covered packages/vx/tests/watch-loop-members.test.ts › “a package added under a running watch is a cycle that runs it, and its edits are cycles from then on”
nx#28212 env:path-bin covered packages/vx/tests/tool-not-on-path.test.ts › “the same tool at the root bin runs green with no line”
nx#34955 env:dotenv-cross-file n/a vx/docs/comparison.md § Gap audit: “.env files loaded into the task env” — “Tasks read their own .env (Vite, Next do); the cache side is .env* plus each gitignored *.local one by name (.env.production.local), as a glob skips it. A config-stage plugin can inject. Not core; a docs footnote.”
nx#19437 env:dotenv-expand-overwritten n/a Same as nx#34955.
nx#23221 env:dotenv-config-precedence n/a Same as nx#34955.
nx#17128 env:dotenv-per-project n/a Same as nx#34955.
nx#23581 env:envfile-per-task fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “a run-commands envFile is loaded under them (nx#23581)”<br>packages/vx-migrate/tests/nx-command.test.ts › “envFile is handed on as declared, {projectRoot} expanded (nx#23581)”
nx#20465 env:task-env-option fixed-in-item-736 packages/vx-migrate/tests/nx.test.ts › “a run-commands env reaches the command and the key (nx#20465)”
nx#19850 env:dotenv-cwd n/a Same as nx#34955.
nx#36446 watch:project-glob covered packages/vx/tests/watch-loop-members.test.ts › “a --filter glob runs and watches exactly the projects it names” written for this ledger (item 745)
nx#30663 watch:env-to-command n/a vx/docs/cli.md: vx watch [OPTIONS] TASK [-- forwarded-args...]: “Run the named task, then re-run it on every filesystem change in the projects in scope.”
nx#22914, nx#14038 watch:self-trigger-loop covered packages/vx/tests/watch-loop-uncached.test.ts › “an UNCACHED task that writes into its project costs exactly one extra execution per edit, then quiet”
Turborepo, Nx and other product names are trademarks of their owners. vx is not affiliated with or endorsed by them.