@vzn/vx 0.0.646 → 0.0.649
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -22
- package/launcher.cjs +9 -2
- package/launcher.sh +2 -2
- package/package.json +5 -5
- package/schemas/cache.json +5 -5
- package/schemas/error.json +1 -1
- package/schemas/info.json +16 -2
- package/schemas/last.json +112 -5
- package/schemas/plan.json +28 -2
- package/schemas/show.json +10 -1
- package/skills/vx/SKILL.md +18 -2
- package/src/bin.ts +53 -12
- package/src/cache/archive.ts +324 -23
- package/src/cache/cache.ts +268 -53
- package/src/cache/git-inputs.ts +219 -87
- package/src/cache/index.ts +3 -2
- package/src/cache/inputs.ts +460 -78
- package/src/cache/key-fold.ts +15 -6
- package/src/cache/layer.ts +49 -9
- package/src/cache/layered-cache.ts +123 -58
- package/src/cache/linked-inputs.ts +1 -1
- package/src/cache/output-index.ts +19 -3
- package/src/cache/plugin-cache.ts +49 -23
- package/src/cache/remote-hits.ts +72 -0
- package/src/cache/remote-lane.ts +90 -14
- package/src/cache/run-history.ts +70 -23
- package/src/cache/run-store.ts +11 -10
- package/src/cache/schema.ts +25 -6
- package/src/cache/tar-stream.ts +5 -0
- package/src/cache/umask.ts +1 -2
- package/src/cli/cache.ts +58 -27
- package/src/cli/completions.ts +12 -5
- package/src/cli/docs.ts +42 -16
- package/src/cli/help.ts +58 -19
- package/src/cli/index.ts +79 -33
- package/src/cli/info.ts +12 -6
- package/src/cli/init.ts +186 -31
- package/src/cli/last.ts +439 -45
- package/src/cli/lock.ts +197 -52
- package/src/cli/plan-format.ts +91 -49
- package/src/cli/plugin-commands.ts +70 -14
- package/src/cli/plugin-templates.ts +13 -13
- package/src/cli/registry.ts +209 -0
- package/src/cli/run.ts +109 -34
- package/src/cli/select.ts +143 -46
- package/src/cli/show.ts +59 -16
- package/src/cli/task-verb.ts +16 -6
- package/src/cli/upgrade.ts +151 -49
- package/src/cli/watch-cycle.ts +10 -5
- package/src/cli/watch-filter.ts +71 -3
- package/src/cli/watch-fs.ts +22 -6
- package/src/cli/watch-judge.ts +48 -6
- package/src/cli/watch.ts +163 -42
- package/src/cli/why.ts +211 -73
- package/src/cli/workspace-config.ts +54 -15
- package/src/config.ts +13 -1
- package/src/exec/env.ts +7 -2
- package/src/exec/executor.ts +154 -10
- package/src/exec/index.ts +6 -2
- package/src/exec/kill-tree.ts +15 -0
- package/src/exec/local-executor.ts +1 -1
- package/src/exec/proc-sample.ts +3 -1
- package/src/exec/runner.ts +253 -54
- package/src/exec/sandbox-binds.ts +7 -3
- package/src/exec/sandbox-paths.ts +1 -1
- package/src/exec/sandbox-runtime.ts +211 -24
- package/src/exec/sandbox-violations.ts +52 -20
- package/src/graph/critical-path.ts +79 -0
- package/src/graph/default-build.ts +19 -0
- package/src/graph/definition.ts +38 -0
- package/src/graph/folds.ts +38 -5
- package/src/graph/index.ts +4 -1
- package/src/graph/priorities.ts +74 -8
- package/src/graph/scheduler.ts +270 -60
- package/src/graph/task-graph.ts +228 -35
- package/src/handoff.ts +97 -9
- package/src/history/failure-mode.ts +6 -3
- package/src/history/history.ts +167 -61
- package/src/history/index.ts +2 -0
- package/src/history/metrics.ts +90 -30
- package/src/index.ts +30 -13
- package/src/orchestrator/admission.ts +10 -6
- package/src/orchestrator/affected-tasks.ts +11 -6
- package/src/orchestrator/deferred-outputs.ts +2 -0
- package/src/orchestrator/doctor.ts +134 -42
- package/src/orchestrator/execute-args.ts +4 -1
- package/src/orchestrator/execute-task.ts +130 -38
- package/src/orchestrator/fingerprint-watch.ts +1 -1
- package/src/orchestrator/graph-memo.ts +140 -0
- package/src/orchestrator/graph-stage.ts +18 -1
- package/src/orchestrator/held-servers.ts +1 -1
- package/src/orchestrator/hit-restore.ts +217 -119
- package/src/orchestrator/index.ts +4 -3
- package/src/orchestrator/local-floor.ts +119 -25
- package/src/orchestrator/local-shortcircuit.ts +28 -4
- package/src/orchestrator/lockfile-claim.ts +96 -16
- package/src/orchestrator/miss-save.ts +42 -8
- package/src/orchestrator/options.ts +8 -6
- package/src/orchestrator/output-host.ts +43 -14
- package/src/orchestrator/output-log.ts +90 -10
- package/src/orchestrator/persistent-task.ts +84 -29
- package/src/orchestrator/persistent.ts +16 -4
- package/src/orchestrator/placement.ts +185 -17
- package/src/orchestrator/plan.ts +64 -7
- package/src/orchestrator/plugin-host.ts +214 -42
- package/src/orchestrator/plugin.ts +113 -37
- package/src/orchestrator/prepare.ts +168 -30
- package/src/orchestrator/projects.ts +65 -40
- package/src/orchestrator/remote-prefetch.ts +119 -25
- package/src/orchestrator/run-artifacts.ts +95 -32
- package/src/orchestrator/run-context.ts +39 -41
- package/src/orchestrator/run-failures.ts +65 -23
- package/src/orchestrator/run-id.ts +6 -3
- package/src/orchestrator/run-keys.ts +149 -13
- package/src/orchestrator/run-live.ts +294 -0
- package/src/orchestrator/run-lock.ts +13 -7
- package/src/orchestrator/run-records.ts +35 -29
- package/src/orchestrator/run-report.ts +3 -3
- package/src/orchestrator/run-steps.ts +58 -22
- package/src/orchestrator/run-stop.ts +22 -5
- package/src/orchestrator/run.ts +331 -88
- package/src/orchestrator/sandbox-fix.ts +7 -5
- package/src/orchestrator/sandbox-request.ts +70 -20
- package/src/orchestrator/shell-verdict.ts +5 -5
- package/src/orchestrator/signals.ts +26 -1
- package/src/orchestrator/stable-keys.ts +92 -8
- package/src/orchestrator/steps.ts +2 -2
- package/src/orchestrator/task-artifacts.ts +90 -26
- package/src/orchestrator/task-hash.ts +78 -13
- package/src/orchestrator/task-log-buffer.ts +72 -36
- package/src/orchestrator/task-process.ts +7 -1
- package/src/orchestrator/telemetry-host.ts +22 -2
- package/src/orchestrator/telemetry.ts +53 -21
- package/src/orchestrator/upstream.ts +15 -0
- package/src/report/events.ts +32 -13
- package/src/report/forecast.ts +31 -9
- package/src/report/framed-output.ts +141 -50
- package/src/report/index.ts +1 -0
- package/src/report/logger.ts +170 -179
- package/src/report/path-links.ts +12 -4
- package/src/report/plain-output.ts +13 -5
- package/src/report/status-line.ts +81 -53
- package/src/report/summary.ts +114 -32
- package/src/report/terminal-signals.ts +13 -2
- package/src/settings.ts +7 -6
- package/src/util/bun-version.ts +4 -1
- package/src/util/colors.ts +4 -2
- package/src/util/config-frame.ts +41 -4
- package/src/{graph → util}/dependency-spec.ts +22 -13
- package/src/util/edit-distance.ts +13 -1
- package/src/util/env-flag.ts +9 -0
- package/src/util/errors.ts +59 -3
- package/src/util/essential-env.ts +57 -0
- package/src/util/git-ignored.ts +1 -1
- package/src/util/hash.ts +35 -0
- package/src/util/hide-env.ts +45 -5
- package/src/util/index.ts +21 -5
- package/src/util/num.ts +8 -0
- package/src/util/paths.ts +91 -21
- package/src/util/report.ts +6 -1
- package/src/util/secret-mask.ts +62 -1
- package/src/util/secrets.ts +7 -2
- package/src/util/size.ts +11 -3
- package/src/util/tail.ts +6 -1
- package/src/util/timing.ts +13 -1
- package/src/util/ui.ts +61 -3
- package/src/util/which.ts +1 -1
- package/src/util/write-file.ts +67 -0
- package/src/workspace/affected.ts +710 -107
- package/src/workspace/bracket-literal.ts +84 -0
- package/src/workspace/canonical-dir.ts +37 -0
- package/src/workspace/config-bytecode.ts +17 -11
- package/src/workspace/config-eval.ts +29 -8
- package/src/workspace/config-imports.ts +199 -58
- package/src/workspace/config-schema.ts +242 -39
- package/src/workspace/filter.ts +37 -8
- package/src/workspace/index.ts +11 -1
- package/src/workspace/json-data.ts +3 -4
- package/src/workspace/lockfile.ts +57 -8
- package/src/workspace/migration.ts +69 -18
- package/src/workspace/package-graph.ts +5 -4
- package/src/workspace/project-loader.ts +226 -37
- package/src/workspace/repo-id.ts +1 -1
- package/src/workspace/workspace.ts +176 -33
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// The report every plugin's teardown reads, and the run's own bytes kept
|
|
2
|
-
// in a remote that takes its writes (
|
|
2
|
+
// in a remote that takes its writes (2026-10-15): a failed task's
|
|
3
3
|
// log and the files its outputs left (`cache.upload.failures`), and the
|
|
4
|
-
// log of a task that saved no entry, on every run (
|
|
4
|
+
// log of a task that saved no entry, on every run (2026-10-16: "Always
|
|
5
5
|
// keep"). Each task's bytes leave when it ends, off its path, like its
|
|
6
|
-
// entry's upload (
|
|
6
|
+
// entry's upload (2026-10-16); the run only waits for them where it
|
|
7
7
|
// waits for every upload, and the footer counts them as the task's remote
|
|
8
8
|
// traffic.
|
|
9
9
|
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
//
|
|
2
|
-
// 2026-10-16)
|
|
3
|
-
//
|
|
1
|
+
// What a run said that its rows do not hold, for `vx last`: the steps it
|
|
2
|
+
// did not wait on (`vx:prefetch`, M 2026-10-16), which never show in a
|
|
3
|
+
// run's output, and its warnings, which scroll past on a terminal and are
|
|
4
|
+
// gone (an agent reading the run afterwards saw only the footer's count,
|
|
5
|
+
// 2026-10-28). One file per run that had any, `<cacheDir>/steps/<runId>.json`
|
|
6
|
+
// and `<cacheDir>/warnings/<runId>.json`, the newest 50 of each kept, as
|
|
4
7
|
// run-failures.ts keeps failed output: files, not cache.db, so the index
|
|
5
8
|
// layout stays as it was. A run with none writes nothing.
|
|
6
9
|
|
|
7
|
-
import { mkdirSync,
|
|
10
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
|
|
8
11
|
import path from 'node:path'
|
|
9
12
|
import { isFsRefusal } from '../util/index.js'
|
|
13
|
+
import { trimKept } from './run-failures.js'
|
|
10
14
|
|
|
11
|
-
/** Runs whose
|
|
15
|
+
/** Runs whose steps (or warnings) are kept; run ids are UUIDv7, so names sort by age. */
|
|
12
16
|
const KEPT = 50
|
|
13
17
|
|
|
14
18
|
/** One of vx's own steps that ran beside the tasks. */
|
|
@@ -18,40 +22,72 @@ export interface RunStep {
|
|
|
18
22
|
ok: boolean
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
type Kept = 'steps' | 'warnings'
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
export function writeRunSteps(
|
|
27
|
+
function keep(
|
|
25
28
|
cacheDir: string,
|
|
29
|
+
kind: Kept,
|
|
26
30
|
runId: string,
|
|
27
|
-
|
|
31
|
+
value: readonly unknown[],
|
|
28
32
|
warn: (message: string) => void,
|
|
29
33
|
): void {
|
|
30
|
-
if (
|
|
34
|
+
if (value.length === 0) return
|
|
31
35
|
try {
|
|
32
|
-
const dir =
|
|
36
|
+
const dir = path.join(cacheDir, kind)
|
|
33
37
|
mkdirSync(dir, { recursive: true })
|
|
34
38
|
const file = path.join(dir, `${runId}.json`)
|
|
35
39
|
const tmp = `${file}.${process.pid}.tmp`
|
|
36
|
-
writeFileSync(tmp, JSON.stringify(
|
|
40
|
+
writeFileSync(tmp, JSON.stringify(value))
|
|
37
41
|
renameSync(tmp, file)
|
|
38
|
-
|
|
39
|
-
.filter((n) => n.endsWith('.json'))
|
|
40
|
-
.sort()
|
|
41
|
-
for (const n of names.slice(0, -KEPT)) rmSync(path.join(dir, n), { force: true })
|
|
42
|
+
trimKept(dir, KEPT)
|
|
42
43
|
} catch (err) {
|
|
43
44
|
if (!isFsRefusal(err)) throw err
|
|
44
|
-
warn(
|
|
45
|
+
warn(
|
|
46
|
+
`[vx] ${kind === 'steps' ? 'background steps' : 'warnings'} not kept: ${err.message} — the verdict above stands`,
|
|
47
|
+
)
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
export function runSteps(cacheDir: string, runId: string): RunStep[] {
|
|
51
|
+
function kept<T>(cacheDir: string, kind: Kept, runId: string): T[] {
|
|
50
52
|
try {
|
|
51
|
-
return JSON.parse(
|
|
52
|
-
readFileSync(path.join(dirOf(cacheDir), `${runId}.json`), 'utf8'),
|
|
53
|
-
) as RunStep[]
|
|
53
|
+
return JSON.parse(readFileSync(path.join(cacheDir, kind, `${runId}.json`), 'utf8')) as T[]
|
|
54
54
|
} catch {
|
|
55
55
|
return []
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
/** Keep `steps` for `runId`; a refused write costs only them. */
|
|
60
|
+
export function writeRunSteps(
|
|
61
|
+
cacheDir: string,
|
|
62
|
+
runId: string,
|
|
63
|
+
steps: readonly RunStep[],
|
|
64
|
+
warn: (message: string) => void,
|
|
65
|
+
): void {
|
|
66
|
+
keep(cacheDir, 'steps', runId, steps, warn)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The background steps `runId` kept; none when it had none or they are gone. */
|
|
70
|
+
export function runSteps(cacheDir: string, runId: string): RunStep[] {
|
|
71
|
+
return kept<RunStep>(cacheDir, 'steps', runId)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Keep the run's warnings as plain text, colour stripped; a refused write costs only them. */
|
|
75
|
+
export function writeRunWarnings(
|
|
76
|
+
cacheDir: string,
|
|
77
|
+
runId: string,
|
|
78
|
+
warnings: readonly string[],
|
|
79
|
+
warn: (message: string) => void,
|
|
80
|
+
): void {
|
|
81
|
+
keep(
|
|
82
|
+
cacheDir,
|
|
83
|
+
'warnings',
|
|
84
|
+
runId,
|
|
85
|
+
warnings.map((w) => Bun.stripANSI(w)),
|
|
86
|
+
warn,
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The warnings `runId` said; none when it said none or they are gone. */
|
|
91
|
+
export function runWarnings(cacheDir: string, runId: string): string[] {
|
|
92
|
+
return kept<string>(cacheDir, 'warnings', runId)
|
|
93
|
+
}
|
|
@@ -25,6 +25,14 @@ import {
|
|
|
25
25
|
|
|
26
26
|
type Child = ReturnType<typeof Bun.spawn>
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The abort reason that stops a run's own work and spares the servers it
|
|
30
|
+
* was handed (`RunOptions.keep`), which it hands back. `vx watch` stops a
|
|
31
|
+
* cycle waiting on a server that never becomes ready (WD-15); any other
|
|
32
|
+
* stop took the unchanged servers down with it, and they restarted.
|
|
33
|
+
*/
|
|
34
|
+
export const CYCLE_INTERRUPT = 'vx:cycle-interrupt'
|
|
35
|
+
|
|
28
36
|
export interface RunStop {
|
|
29
37
|
readonly signal: AbortSignal
|
|
30
38
|
readonly liveChildren: Set<Child>
|
|
@@ -33,8 +41,10 @@ export interface RunStop {
|
|
|
33
41
|
* The process signal that stopped the run. A run a process signal
|
|
34
42
|
* stopped records no history: until item 849 the handler exited before
|
|
35
43
|
* any outcome landed, and a Ctrl-C'd run then read in `vx last` as
|
|
36
|
-
* FAILED with 0 tasks (item 854).
|
|
37
|
-
*
|
|
44
|
+
* FAILED with 0 tasks (item 854). So does an embedder's abort whose
|
|
45
|
+
* reason names one (`'SIGINT'`, `'SIGTERM'`, `'SIGHUP'`): the signal the
|
|
46
|
+
* embedder received, as the watch loop relays a Ctrl-C to its cycle. Any
|
|
47
|
+
* other abort is the embedder's own call and keeps its record.
|
|
38
48
|
*/
|
|
39
49
|
readonly stoppedBy: StopSignal | undefined
|
|
40
50
|
/**
|
|
@@ -71,6 +81,8 @@ export function runStop(args: {
|
|
|
71
81
|
teardowns: number
|
|
72
82
|
/** Called first when the run is stopped. */
|
|
73
83
|
onStop: () => void
|
|
84
|
+
/** A server the run was handed: a `CYCLE_INTERRUPT` leaves it running. */
|
|
85
|
+
handed: (child: Child) => boolean
|
|
74
86
|
}): RunStop {
|
|
75
87
|
const { log, external } = args
|
|
76
88
|
const liveChildren = new Set<Child>()
|
|
@@ -90,10 +102,14 @@ export function runStop(args: {
|
|
|
90
102
|
}
|
|
91
103
|
})()
|
|
92
104
|
const controller = new AbortController()
|
|
93
|
-
|
|
105
|
+
let stoppedBy: StopSignal | undefined
|
|
106
|
+
const forwardAbort = (): void => {
|
|
107
|
+
const reason: unknown = external?.reason
|
|
108
|
+
if (reason === 'SIGINT' || reason === 'SIGTERM' || reason === 'SIGHUP') stoppedBy = reason
|
|
109
|
+
controller.abort(reason)
|
|
110
|
+
}
|
|
94
111
|
if (external?.aborted === true) forwardAbort()
|
|
95
112
|
else external?.addEventListener('abort', forwardAbort, { once: true })
|
|
96
|
-
let stoppedBy: StopSignal | undefined
|
|
97
113
|
let left = (): void => {}
|
|
98
114
|
const runLeft = new Promise<void>((resolve) => {
|
|
99
115
|
left = resolve
|
|
@@ -120,8 +136,9 @@ export function runStop(args: {
|
|
|
120
136
|
const onAbort = (): void => {
|
|
121
137
|
args.onStop()
|
|
122
138
|
endedBeforeStop = new Set([...persistentRegistry.values()].filter(hasEnded))
|
|
139
|
+
const spare = controller.signal.reason === CYCLE_INTERRUPT ? args.handed : () => false
|
|
123
140
|
aborting = terminateChildren(
|
|
124
|
-
() => [...liveChildren, ...persistentRegistry.values()],
|
|
141
|
+
() => [...liveChildren, ...persistentRegistry.values()].filter((c) => !spare(c)),
|
|
125
142
|
forwardedSignal(controller.signal.reason),
|
|
126
143
|
)
|
|
127
144
|
}
|