@vzn/vx 0.0.428 → 0.0.430
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.430",
|
|
4
4
|
"description": "The fastest task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"node": ">=18"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
25
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
26
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
27
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
24
|
+
"@vzn/vx-linux-x64": "0.0.430",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.430",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.430",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.430"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cli/init.ts
CHANGED
|
@@ -374,6 +374,9 @@ function namelessNotes(root: string, dirs: readonly string[]): string[] {
|
|
|
374
374
|
})
|
|
375
375
|
.map((dir) => path.relative(root, dir).split(path.sep).join('/'))
|
|
376
376
|
.sort()
|
|
377
|
+
// The root's own manifest is the empty relative path: a nameless
|
|
378
|
+
// single-package repo read `not mapped: — its package.json…` (M-54).
|
|
379
|
+
.map((rel) => (rel === '' ? 'the root' : rel))
|
|
377
380
|
if (withScripts.length === 0) return []
|
|
378
381
|
const shown =
|
|
379
382
|
withScripts.slice(0, 3).join(', ') +
|
package/src/exec/executor.ts
CHANGED
|
@@ -278,9 +278,15 @@ export function selectExecutor(
|
|
|
278
278
|
for (const executor of executors) {
|
|
279
279
|
if (task.pinnedLocal && executor.remote === true) continue
|
|
280
280
|
if (executor.accepts === undefined) return executor
|
|
281
|
-
let taken:
|
|
281
|
+
let taken: unknown
|
|
282
282
|
try {
|
|
283
283
|
taken = executor.accepts(task)
|
|
284
|
+
// An `async accepts` answers a Promise: truthy, so the executor took
|
|
285
|
+
// every task, and a rejection went unheard (the shape of H-16's admit).
|
|
286
|
+
if (taken instanceof Promise) {
|
|
287
|
+
taken.catch(() => {})
|
|
288
|
+
throw new Error('returned a Promise; accepts is synchronous')
|
|
289
|
+
}
|
|
284
290
|
} catch (err) {
|
|
285
291
|
const m = err instanceof Error ? err.message : String(err)
|
|
286
292
|
throw new UserError(`${label(executor)} failed in accepts for ${task.taskId}: ${m}`)
|
package/src/orchestrator/run.ts
CHANGED
|
@@ -500,13 +500,20 @@ async function runOnBus(
|
|
|
500
500
|
// it surfaced as a bare stack, or mid-run from the completion path
|
|
501
501
|
// (item 1022).
|
|
502
502
|
const tellDemand = (executor: TaskExecutor, remaining: ReadonlySet<string>): void => {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
} catch (err) {
|
|
506
|
-
demandOf.delete(executor)
|
|
503
|
+
const failed = (err: unknown): void => {
|
|
504
|
+
if (!demandOf.delete(executor)) return
|
|
507
505
|
const m = err instanceof Error ? err.message : String(err)
|
|
508
506
|
log.status(`[vx] ${executorLabel(executor)} failed in demand: ${m}; not asked again this run`)
|
|
509
507
|
}
|
|
508
|
+
try {
|
|
509
|
+
// An `async demand` that rejects did so where no one listened: an
|
|
510
|
+
// unhandled rejection, a stack, the run killed. Its rejection is a
|
|
511
|
+
// throw like any other.
|
|
512
|
+
const ret: unknown = executor.demand!(remaining)
|
|
513
|
+
if (ret instanceof Promise) ret.catch(failed)
|
|
514
|
+
} catch (err) {
|
|
515
|
+
failed(err)
|
|
516
|
+
}
|
|
510
517
|
}
|
|
511
518
|
for (const [executor, remaining] of demandOf) tellDemand(executor, remaining)
|
|
512
519
|
const narrowDemand =
|
|
@@ -388,9 +388,11 @@ export function createTelemetrySource(args: {
|
|
|
388
388
|
// Never silently. The standing rule is that a never-fail path must still
|
|
389
389
|
// WARN — telemetry that vanishes without a word is indistinguishable from
|
|
390
390
|
// telemetry nobody configured.
|
|
391
|
-
// Every hook call site skips a disabled sink first
|
|
392
|
-
//
|
|
391
|
+
// Every hook call site skips a disabled sink first (item 654), but an
|
|
392
|
+
// async hook's rejections land later, several records' worth of them
|
|
393
|
+
// after the first: those are said once too.
|
|
393
394
|
const disable = (sink: TelemetrySink, hook: string, err: unknown): void => {
|
|
395
|
+
if (disabled.has(sink)) return
|
|
394
396
|
disabled.add(sink)
|
|
395
397
|
warn?.(
|
|
396
398
|
`[vx] telemetry sink '${label(sink)}' threw in ${hook}; disabled for this run: ${err instanceof Error ? err.message : String(err)}`,
|
|
@@ -406,7 +408,10 @@ export function createTelemetrySource(args: {
|
|
|
406
408
|
const kinds = sink.wants ?? DEFAULT_KINDS
|
|
407
409
|
if (!kinds.includes(record.kind)) continue
|
|
408
410
|
try {
|
|
409
|
-
|
|
411
|
+
// Typed `void`, yet an `async onRecord` rejects where no one
|
|
412
|
+
// listened: an unhandled rejection killed the run (C-101).
|
|
413
|
+
const ret: unknown = sink.onRecord(record)
|
|
414
|
+
if (ret instanceof Promise) ret.catch((err) => disable(sink, 'onRecord', err))
|
|
410
415
|
} catch (err) {
|
|
411
416
|
disable(sink, 'onRecord', err)
|
|
412
417
|
}
|
|
@@ -483,7 +488,8 @@ export function createTelemetrySource(args: {
|
|
|
483
488
|
for (const sink of sinks) {
|
|
484
489
|
if (disabled.has(sink) || sink.onRunSummary === undefined) continue
|
|
485
490
|
try {
|
|
486
|
-
sink.onRunSummary(summary)
|
|
491
|
+
const ret: unknown = sink.onRunSummary(summary)
|
|
492
|
+
if (ret instanceof Promise) ret.catch((err) => disable(sink, 'onRunSummary', err))
|
|
487
493
|
} catch (err) {
|
|
488
494
|
disable(sink, 'onRunSummary', err)
|
|
489
495
|
}
|
|
@@ -504,7 +504,10 @@ export async function loadProjectConfigs(
|
|
|
504
504
|
? []
|
|
505
505
|
: [
|
|
506
506
|
...restoreBuiltins(builtins, overlapping),
|
|
507
|
-
|
|
507
|
+
// Overlapping, the env is checked once at the round's end, as most
|
|
508
|
+
// built-ins are: reading all of it after every load was 15–25 µs a
|
|
509
|
+
// config (149 variables, compiled, 2026-10-03).
|
|
510
|
+
...(overlapping ? [] : restoreEnv(env)),
|
|
508
511
|
...restoreCwd(cwd),
|
|
509
512
|
// Alone in the round: nothing else reads the umask now. Beside
|
|
510
513
|
// other loads the round reads it once they are done (see
|
|
@@ -591,7 +594,7 @@ export async function loadProjectConfigs(
|
|
|
591
594
|
...restoreUmask(umask),
|
|
592
595
|
]
|
|
593
596
|
: []
|
|
594
|
-
// Overlapping loads check most built-ins only here, so a change one
|
|
597
|
+
// Overlapping loads check most built-ins and the env only here, so a change one
|
|
595
598
|
// config made may have broken another's load: it is refused first, and
|
|
596
599
|
// nothing the round evaluated is stored.
|
|
597
600
|
const changedInRound =
|