@vzn/vx 0.0.636 → 0.0.638

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.
Files changed (151) hide show
  1. package/README.md +39 -11
  2. package/docs/caching.md +246 -213
  3. package/docs/cli.md +791 -705
  4. package/docs/execution.md +68 -76
  5. package/docs/features.md +47 -42
  6. package/docs/patterns.md +26 -25
  7. package/docs/schema.md +392 -205
  8. package/docs/security.md +76 -39
  9. package/launcher.sh +43 -0
  10. package/package.json +5 -5
  11. package/schemas/cache.json +41 -19
  12. package/schemas/info.json +23 -11
  13. package/schemas/last.json +48 -2
  14. package/schemas/lock.json +1 -1
  15. package/schemas/plan.json +4 -4
  16. package/schemas/show.json +5 -3
  17. package/schemas/why.json +15 -1
  18. package/skills/vx/SKILL.md +28 -13
  19. package/src/bin.ts +30 -9
  20. package/src/cache/archive.ts +11 -0
  21. package/src/cache/cache.ts +124 -53
  22. package/src/cache/chained-cache.ts +4 -0
  23. package/src/cache/git-inputs.ts +277 -63
  24. package/src/cache/index.ts +15 -1
  25. package/src/cache/inputs.ts +102 -36
  26. package/src/cache/key-fold.ts +8 -7
  27. package/src/cache/layer.ts +15 -18
  28. package/src/cache/layered-cache.ts +20 -102
  29. package/src/cache/plugin-cache.ts +248 -0
  30. package/src/cache/policy.ts +32 -27
  31. package/src/cache/run-history.ts +104 -14
  32. package/src/cache/run-store.ts +77 -0
  33. package/src/cache/schema.ts +58 -31
  34. package/src/cache/scoped-cache.ts +237 -0
  35. package/src/cli/cache.ts +173 -34
  36. package/src/cli/completions.ts +11 -7
  37. package/src/cli/core-alias.ts +1 -1
  38. package/src/cli/foreign-flags.ts +13 -12
  39. package/src/cli/help.ts +110 -70
  40. package/src/cli/index.ts +67 -24
  41. package/src/cli/info.ts +43 -27
  42. package/src/cli/init.ts +115 -407
  43. package/src/cli/last.ts +157 -9
  44. package/src/cli/lock.ts +356 -122
  45. package/src/cli/plan-format.ts +7 -5
  46. package/src/cli/plugin-commands.ts +81 -14
  47. package/src/cli/plugin-templates.ts +11 -11
  48. package/src/cli/run.ts +116 -160
  49. package/src/cli/select.ts +50 -47
  50. package/src/cli/show.ts +83 -59
  51. package/src/cli/task-verb.ts +6 -13
  52. package/src/cli/upgrade.ts +415 -149
  53. package/src/cli/watch-cycle.ts +9 -2
  54. package/src/cli/watch-filter.ts +39 -61
  55. package/src/cli/watch-fs.ts +29 -16
  56. package/src/cli/watch-judge.ts +18 -4
  57. package/src/cli/watch-set.ts +16 -42
  58. package/src/cli/watch.ts +227 -230
  59. package/src/cli/why.ts +38 -18
  60. package/src/cli/workspace-config.ts +33 -70
  61. package/src/config.ts +169 -70
  62. package/src/exec/env.ts +1 -31
  63. package/src/exec/executor.ts +1 -5
  64. package/src/exec/kill-tree.ts +2 -1
  65. package/src/exec/sandbox-runtime.ts +12 -1
  66. package/src/exec/sandbox-violations.ts +9 -1
  67. package/src/graph/dependency-spec.ts +1 -1
  68. package/src/graph/index.ts +1 -0
  69. package/src/graph/priorities.ts +1 -1
  70. package/src/graph/scheduler.ts +27 -7
  71. package/src/graph/task-graph.ts +76 -24
  72. package/src/handoff.ts +169 -0
  73. package/src/index.ts +35 -58
  74. package/src/orchestrator/affected-tasks.ts +15 -8
  75. package/src/orchestrator/command-windows.ts +44 -0
  76. package/src/orchestrator/deferred-outputs.ts +12 -10
  77. package/src/orchestrator/doctor.ts +98 -110
  78. package/src/orchestrator/download-policy.ts +3 -3
  79. package/src/orchestrator/events.ts +19 -3
  80. package/src/orchestrator/excluded-keys.ts +0 -2
  81. package/src/orchestrator/execute-task.ts +147 -69
  82. package/src/orchestrator/failure-mode.ts +19 -10
  83. package/src/orchestrator/fingerprint-watch.ts +18 -15
  84. package/src/orchestrator/forecast.ts +10 -2
  85. package/src/orchestrator/framed-output.ts +9 -5
  86. package/src/orchestrator/graph-stage.ts +5 -5
  87. package/src/orchestrator/history.ts +126 -30
  88. package/src/orchestrator/hit-restore.ts +15 -3
  89. package/src/orchestrator/index.ts +20 -5
  90. package/src/orchestrator/local-shortcircuit.ts +2 -1
  91. package/src/orchestrator/lockfile-claim.ts +79 -20
  92. package/src/orchestrator/logger.ts +80 -41
  93. package/src/orchestrator/metrics.ts +78 -9
  94. package/src/orchestrator/miss-save.ts +3 -0
  95. package/src/orchestrator/options.ts +42 -29
  96. package/src/orchestrator/output-host.ts +72 -0
  97. package/src/orchestrator/plan.ts +6 -8
  98. package/src/orchestrator/plugin-host.ts +100 -66
  99. package/src/orchestrator/plugin.ts +173 -67
  100. package/src/orchestrator/prepare.ts +163 -78
  101. package/src/orchestrator/projects.ts +105 -99
  102. package/src/orchestrator/remote-prefetch.ts +11 -6
  103. package/src/orchestrator/run-context.ts +25 -6
  104. package/src/orchestrator/run-failures.ts +17 -8
  105. package/src/orchestrator/run-lock.ts +1 -1
  106. package/src/orchestrator/run-records.ts +1 -1
  107. package/src/orchestrator/run-report.ts +9 -9
  108. package/src/orchestrator/run-settings.ts +48 -0
  109. package/src/orchestrator/run.ts +244 -119
  110. package/src/orchestrator/sandbox-fix.ts +39 -20
  111. package/src/orchestrator/sandbox-request.ts +84 -13
  112. package/src/orchestrator/signals.ts +1 -1
  113. package/src/orchestrator/stable-keys.ts +13 -11
  114. package/src/orchestrator/status-line.ts +49 -7
  115. package/src/orchestrator/summary.ts +115 -106
  116. package/src/orchestrator/task-hash.ts +12 -83
  117. package/src/orchestrator/telemetry.ts +4 -4
  118. package/src/settings.ts +428 -0
  119. package/src/{orchestrator → util}/colors.ts +5 -0
  120. package/src/util/config-frame.ts +31 -2
  121. package/src/util/errors.ts +33 -1
  122. package/src/util/essential-env.ts +31 -0
  123. package/src/util/hide-env.ts +107 -0
  124. package/src/util/index.ts +16 -3
  125. package/src/util/paths.ts +10 -0
  126. package/src/util/refusal-notice.ts +111 -0
  127. package/src/util/report.ts +31 -0
  128. package/src/util/settle.ts +49 -30
  129. package/src/util/size.ts +23 -4
  130. package/src/util/timing.ts +3 -2
  131. package/src/util/ui.ts +186 -0
  132. package/src/util/ulid.ts +1 -1
  133. package/src/util/verbs.ts +0 -15
  134. package/src/workspace/affected.ts +84 -232
  135. package/src/workspace/config-eval.ts +15 -20
  136. package/src/workspace/config-imports.ts +78 -3
  137. package/src/workspace/config-schema.ts +209 -268
  138. package/src/workspace/dependency-rules.ts +65 -0
  139. package/src/workspace/filter.ts +2 -2
  140. package/src/workspace/fingerprint.ts +11 -121
  141. package/src/workspace/index.ts +20 -27
  142. package/src/workspace/load-reads.ts +4 -4
  143. package/src/workspace/lockfile.ts +96 -140
  144. package/src/workspace/migration.ts +307 -215
  145. package/src/workspace/package-graph.ts +30 -216
  146. package/src/workspace/project-loader.ts +80 -285
  147. package/src/workspace/repo-id.ts +2 -1
  148. package/src/workspace/workspace.ts +363 -831
  149. package/src/cache/config-evals.ts +0 -130
  150. package/src/workspace/config-cache.ts +0 -661
  151. package/src/workspace/migrate-scripts.ts +0 -1121
package/src/cli/info.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  // `vx info` — workspace doctor printout. One screen of environment +
2
2
  // workspace + cache facts for bug reports and quick sanity checks.
3
3
  // The facts come
4
- // from the orchestrator's `collectInfo` (doctor.ts), which `vx mcp` reads
5
- // too; this file parses the flags and renders the rows.
4
+ // from the orchestrator's `collectInfo` (doctor.ts); this file parses the flags and renders the rows.
6
5
 
7
6
  import os from 'node:os'
8
7
  import { collectInfo, type FlakyTask, type InfoFacts } from '../orchestrator/index.js'
9
8
  import { flagHint, formatValue, refuse, refusedWord, seeHelp } from './help.js'
10
9
  import { namedCacheDir, parseCacheDirFlag, warnToStderr } from './workspace-config.js'
11
10
  import { formatBytes } from './format.js'
12
- import { MIN_BUN } from '../util/index.js'
11
+ import { detectColors, MIN_BUN, ui, type ColorSupport } from '../util/index.js'
12
+ import { envName } from '../settings.js'
13
13
 
14
14
  interface InfoArgs {
15
15
  format: 'pretty' | 'json'
@@ -46,7 +46,7 @@ export function parseInfoArgs(args: readonly string[]): InfoArgs {
46
46
  export async function infoCmd(args: readonly string[]): Promise<number> {
47
47
  const parsed = parseInfoArgs(args)
48
48
  if (parsed.error) return refuse('info', args, parsed.error, 'VX_E_USAGE')
49
- // `collectInfo` takes a resolved directory from `vx mcp` too, where one
49
+ // `collectInfo` takes a resolved directory, where one
50
50
  // not made yet is a workspace that never ran; the flag is the user's,
51
51
  // and a directory it names that is not there is a typo (item 900).
52
52
  if (parsed.cacheDir !== undefined) namedCacheDir(parsed.cacheDir)
@@ -55,14 +55,19 @@ export async function infoCmd(args: readonly string[]): Promise<number> {
55
55
  warn: warnToStderr,
56
56
  })
57
57
  process.stdout.write(
58
- parsed.format === 'json' ? `${JSON.stringify(facts, null, 2)}\n` : `${renderInfo(facts)}\n`,
58
+ parsed.format === 'json'
59
+ ? `${JSON.stringify(facts)}\n`
60
+ : `${renderInfo(facts, detectColors(process.stdout))}\n`,
59
61
  )
60
62
  return 0
61
63
  }
62
64
 
63
- export function renderInfo(f: InfoFacts): string {
65
+ export function renderInfo(f: InfoFacts, colors: ColorSupport = { enabled: false }): string {
64
66
  const rows: [string, string][] = [
65
- ['vx', f.vx],
67
+ [
68
+ 'vx',
69
+ `${f.vx} (${tildePath(f.vxPath)}${f.handedOffFrom === null ? '' : `, handed off from ${tildePath(f.handedOffFrom)}`})`,
70
+ ],
66
71
  // The prose stays in the rendered row; `f.bun` itself is the bare
67
72
  // version a script reads (doctor.ts says why).
68
73
  [
@@ -75,24 +80,25 @@ export function renderInfo(f: InfoFacts): string {
75
80
  ['git status cache', renderGitStatusCache(f.gitStatusCache)],
76
81
  ['workspace root', tildePath(f.workspaceRoot)],
77
82
  ['projects', describeProjects(f)],
78
- // Only when a config did not load: the count above says "zero" for
79
- // it, and this row says which and why.
80
- ...(f.configErrors.length > 0
81
- ? ([['config errors', f.configErrors.map((e) => `${e.path}: ${e.message}`).join('; ')]] as [
82
- string,
83
- string,
84
- ][])
85
- : []),
86
83
  ['plugins', describePlugins(f.plugins)],
87
84
  ['workers', describeWorkers(f.workers)],
88
85
  ['memory', describeMemory(f.memory)],
89
- ['cache dir', tildePath(f.cacheDir)],
86
+ [
87
+ 'cache dir',
88
+ `${tildePath(f.cacheDir)} (${formatBytes(f.cacheDirBytes)}, ${f.cacheStore === null ? 'the entries and ' : ''}this workspace's run history)`,
89
+ ],
90
90
  [
91
91
  'cache store',
92
- f.cacheStore === null ? 'none: the cache dir holds the entries' : tildePath(f.cacheStore),
92
+ f.cacheStore === null
93
+ ? 'none: the cache dir holds the entries'
94
+ : `${tildePath(f.cacheStore)} (${formatBytes(f.cacheStoreBytes ?? 0)}, shared by this repo's checkouts)`,
93
95
  ],
94
96
  ['cache versions', `keys ${f.cacheVersion} · index schema ${f.schemaVersion}`],
95
97
  ['cache entries', describeEntries(f)],
98
+ // Only the settings a variable or the workspace changed.
99
+ ...(Object.values(f.settings).some((s) => s.source !== 'default')
100
+ ? ([['settings', describeSettings(f.settings)]] as [string, string][])
101
+ : []),
96
102
  ...(f.cacheRetention !== null
97
103
  ? ([['cache retention', describeRetention(f.cacheRetention)]] as [string, string][])
98
104
  : []),
@@ -101,7 +107,7 @@ export function renderInfo(f: InfoFacts): string {
101
107
  ? ([
102
108
  [
103
109
  'orphans',
104
- `${f.orphans.artifacts} artifact${f.orphans.artifacts === 1 ? '' : 's'} (${formatBytes(f.orphans.bytes)}) the index does not know — \`vx cache prune\` reaps them`,
110
+ `${f.orphans.artifacts} artifact${f.orphans.artifacts === 1 ? '' : 's'} (${formatBytes(f.orphans.bytes)}) the index does not know — \`vx cache clean\` reaps them`,
105
111
  ],
106
112
  ] as [string, string][])
107
113
  : []),
@@ -116,10 +122,9 @@ export function renderInfo(f: InfoFacts): string {
116
122
  ],
117
123
  ['flaky tasks', describeFlakyTasks(f.flakyTasks)],
118
124
  ['sandbox', describeSandbox(f.sandbox)],
119
- ['vx-lock.json', f.lockfile ? 'yes' : 'no'],
125
+ ['projects lock', f.lockfile ? 'yes' : 'no'],
120
126
  ]
121
- const labelW = Math.max(...rows.map(([label]) => label.length))
122
- return rows.map(([label, value]) => `${`${label}:`.padEnd(labelW + 1)} ${value}`).join('\n')
127
+ return ui.report('vx info', rows).lines(colors).join('\n')
123
128
  }
124
129
 
125
130
  /** `812 (1.2 GB)`, or against `cacheRetention.maxSize`: `812 (1.2 GB of 10 GB, 12%)`. */
@@ -132,6 +137,20 @@ function describeEntries(f: InfoFacts): string {
132
137
  return `${f.cacheEntries} (${size})`
133
138
  }
134
139
 
140
+ /**
141
+ * The settings not at their default, with where each came from:
142
+ * `run.timeout 30m (VX_RUN_TIMEOUT), cache.policy local:rw (.vx/workspace)`.
143
+ */
144
+ function describeSettings(settings: InfoFacts['settings']): string {
145
+ return Object.entries(settings)
146
+ .filter(([, s]) => s.source !== 'default')
147
+ .map(
148
+ ([path, s]) =>
149
+ `${path} ${String(s.value)} (${s.source === 'env' ? envName(path) : '.vx/workspace'})`,
150
+ )
151
+ .join(', ')
152
+ }
153
+
135
154
  /** What a run's end evicts: `entries unused for 30d, and the oldest entries past 10G`. */
136
155
  function describeRetention(r: NonNullable<InfoFacts['cacheRetention']>): string {
137
156
  const parts = [
@@ -163,10 +182,10 @@ function describeSandbox(s: InfoFacts['sandbox']): string {
163
182
  return `unavailable — ${s.reason}; ${declared}${s.declared > 0 ? ' and will fail' : ''}`
164
183
  }
165
184
 
166
- /** `4 — the CPU count`, `2 — cgroup CPU quota 2 of 8 cores`, `8 — vx.workspace.ts (4 cores)`. */
185
+ /** `4 — the CPU count`, `2 — cgroup CPU quota 2 of 8 cores`, `8 — .vx/workspace.ts (4 cores)`. */
167
186
  export function describeWorkers(w: InfoFacts['workers']): string {
168
187
  const quota = w.cpuQuota === null ? '' : `, cgroup CPU quota ${trimCores(w.cpuQuota)}`
169
- if (w.source === 'workspace') return `${w.count} — vx.workspace.ts (${w.cores} cores${quota})`
188
+ if (w.source === 'workspace') return `${w.count} — .vx/workspace.ts (${w.cores} cores${quota})`
170
189
  if (w.source === 'cgroup')
171
190
  return `${w.count} — cgroup CPU quota ${trimCores(w.cpuQuota ?? w.count)} of ${w.cores} cores`
172
191
  return `${w.count} — the CPU count${quota}`
@@ -186,10 +205,7 @@ function trimCores(n: number): string {
186
205
 
187
206
  /** `2 — app#test (3 of 7 runs failed on unchanged inputs); api#e2e (1 of 4)`, or `none`. */
188
207
  function describeProjects(f: InfoFacts): string {
189
- const tasks = `${f.tasks} task${f.tasks === 1 ? '' : 's'}`
190
- const n = f.configErrors.length
191
- if (n === 0) return `${f.projects} (${tasks})`
192
- return `${f.projects} (${tasks} · ${n} config${n === 1 ? '' : 's'} did not load)`
208
+ return `${f.projects} (${f.tasks} task${f.tasks === 1 ? '' : 's'})`
193
209
  }
194
210
 
195
211
  function describeFlakyTasks(tasks: readonly FlakyTask[]): string {