@vzn/vx 0.0.587 → 0.0.588

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.587",
3
+ "version": "0.0.588",
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.587",
25
- "@vzn/vx-linux-arm64": "0.0.587",
26
- "@vzn/vx-darwin-x64": "0.0.587",
27
- "@vzn/vx-darwin-arm64": "0.0.587"
24
+ "@vzn/vx-linux-x64": "0.0.588",
25
+ "@vzn/vx-linux-arm64": "0.0.588",
26
+ "@vzn/vx-darwin-x64": "0.0.588",
27
+ "@vzn/vx-darwin-arm64": "0.0.588"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
package/src/cli/run.ts CHANGED
@@ -7,11 +7,9 @@ import { defaultAffectedBase, findWorkspaceRoot } from '../workspace/index.js'
7
7
  import {
8
8
  planRun,
9
9
  formatRunReportMarkdown,
10
- outcomeLabel,
11
10
  projectOutcome,
12
11
  run as runOrchestrator,
13
12
  shellQuote,
14
- type OutcomeView,
15
13
  type RunOptions,
16
14
  type RunResult,
17
15
  } from '../orchestrator/index.js'
@@ -567,6 +565,7 @@ export async function resolveRunOptions(
567
565
  flow: detectFlow(parsed),
568
566
  ...(parsed.frozen ? { frozen: true } : {}),
569
567
  ...(parsed.outputLogs !== undefined ? { outputLogs: parsed.outputLogs } : {}),
568
+ ...(parsed.verbosity > 0 ? { summaryTable: true } : {}),
570
569
  ...(parsed.download !== undefined ? { download: parsed.download } : {}),
571
570
  ...(parsed.continueMode !== undefined ? { continueMode: parsed.continueMode } : {}),
572
571
  forwardArgs: parsed.forwardArgs,
@@ -707,7 +706,6 @@ export async function runCmd(args: readonly string[]): Promise<number> {
707
706
  return 1
708
707
  }
709
708
  const result: RunResult = { ok: summary.ok, outcomes: summary.outcomes.map(projectOutcome) }
710
- if (parsed.verbosity > 0) printSummary(result)
711
709
  // Report generation is post-run, gated on the flags — zero cost when
712
710
  // both are absent. Rendered once, however many sinks asked for it.
713
711
  if (parsed.report === 'markdown' || parsed.reportFile !== undefined) {
@@ -742,35 +740,3 @@ export async function runCmd(args: readonly string[]): Promise<number> {
742
740
  }
743
741
  return result.ok ? 0 : 1
744
742
  }
745
-
746
- function printSummary(summary: RunResult): void {
747
- const rows = summary.outcomes.map((o) => formatRow(o))
748
- if (rows.length === 0) return
749
- const widths = {
750
- task: Math.max(4, ...rows.map((r) => r.task.length)),
751
- status: Math.max(6, ...rows.map((r) => r.status.length)),
752
- duration: Math.max(8, ...rows.map((r) => r.duration.length)),
753
- }
754
- const header =
755
- 'TASK'.padEnd(widths.task) +
756
- ' ' +
757
- 'STATUS'.padEnd(widths.status) +
758
- ' ' +
759
- 'DURATION'.padStart(widths.duration)
760
- process.stdout.write(`\n${header}\n`)
761
- process.stdout.write('-'.repeat(header.length) + '\n')
762
- for (const r of rows) {
763
- process.stdout.write(
764
- r.task.padEnd(widths.task) +
765
- ' ' +
766
- r.status.padEnd(widths.status) +
767
- ' ' +
768
- r.duration.padStart(widths.duration) +
769
- '\n',
770
- )
771
- }
772
- }
773
-
774
- function formatRow(o: OutcomeView): { task: string; status: string; duration: string } {
775
- return { task: o.taskId, status: outcomeLabel(o), duration: `${o.durationMs}ms` }
776
- }
@@ -38,7 +38,6 @@ export {
38
38
  projectNode,
39
39
  projectOutcome,
40
40
  outcomeWord,
41
- outcomeLabel,
42
41
  } from './events.js'
43
42
  export type {
44
43
  EventBus,
@@ -207,6 +207,11 @@ export interface RunOptions {
207
207
  * is replaced only when the next cycle starts.
208
208
  */
209
209
  holdPersistent?: boolean
210
+ /**
211
+ * Print the per-task table (`--verbosity 1`) just above the footer: the
212
+ * footer is the run's last word, so the caller cannot print it after.
213
+ */
214
+ summaryTable?: boolean
210
215
  /**
211
216
  * vx's stdin is a terminal: each `exec.interactive` task is handed it,
212
217
  * alone (placement.ts `terminalHolders`). The CLI sets it from
@@ -92,7 +92,7 @@ import { assembleRunRecords } from './run-records.js'
92
92
  import { hasEnded, selectKeepAlive, shutdownPersistent } from './persistent.js'
93
93
  import { writeRunProfile, writeRunSummary } from './run-artifacts.js'
94
94
  import { createSaveLane } from './save-lane.js'
95
- import { formatRunSummary } from './summary.js'
95
+ import { formatOutcomeTable, formatRunSummary } from './summary.js'
96
96
  import { detectFlaky, type FlakyCandidate, type FlakyFinding } from './failure-mode.js'
97
97
  import { createMissExplainer } from './miss-reason.js'
98
98
  import type { RunOptions, RunSummary } from './options.js'
@@ -1328,6 +1328,7 @@ async function runOnBus(
1328
1328
  // sandbox reset included, so any warning they raise lands above it. A
1329
1329
  // task's own facts (flaky, blocked) ride its row. Only a kept server's
1330
1330
  // own output follows.
1331
+ if (options.summaryTable === true) for (const line of formatOutcomeTable(list)) log.status(line)
1331
1332
  for (const line of formatRunSummary(list, totalMs, colors, runContext)) log.status(line)
1332
1333
 
1333
1334
  // Edge case the summary already reported: the user requested a
@@ -6,6 +6,7 @@
6
6
  import type { TaskOutcome } from '../graph/index.js'
7
7
  import { paint, type ColorSupport } from './colors.js'
8
8
  import { tallyOutcomes } from './tally.js'
9
+ import { outcomeLabel, projectOutcome } from './events.js'
9
10
  import { isGroupTask } from '../graph/index.js'
10
11
  import { formatElapsed } from '../util/index.js'
11
12
 
@@ -314,6 +315,34 @@ function resultLine(
314
315
  return parts.join(` ${paint('', '\u00b7', colors, { dim: true })} `)
315
316
  }
316
317
 
318
+ /**
319
+ * The `--verbosity 1` per-task table (`RunOptions.summaryTable`). Groups are
320
+ * left out as the footer and `--report` leave them: a group ran no command.
321
+ */
322
+ export function formatOutcomeTable(outcomes: readonly TaskOutcome[]): string[] {
323
+ const rows = outcomes
324
+ .filter((o) => !isGroupTask(o.node))
325
+ .map((o) => {
326
+ const v = projectOutcome(o)
327
+ return { task: v.taskId, status: outcomeLabel(v), duration: `${v.durationMs}ms` }
328
+ })
329
+ if (rows.length === 0) return []
330
+ const widths = {
331
+ task: Math.max(4, ...rows.map((r) => r.task.length)),
332
+ status: Math.max(6, ...rows.map((r) => r.status.length)),
333
+ duration: Math.max(8, ...rows.map((r) => r.duration.length)),
334
+ }
335
+ const line = (task: string, status: string, duration: string) =>
336
+ `${task.padEnd(widths.task)} ${status.padEnd(widths.status)} ${duration.padStart(widths.duration)}`
337
+ const header = line('TASK', 'STATUS', 'DURATION')
338
+ return [
339
+ '',
340
+ header,
341
+ '-'.repeat(header.length),
342
+ ...rows.map((r) => line(r.task, r.status, r.duration)),
343
+ ]
344
+ }
345
+
317
346
  // Local byte formatter — the orchestrator can't import cli/format.ts
318
347
  // (module boundary), and the footer only needs one compact form.
319
348
  export function formatRunSummary(