@vzn/vx 0.0.649 → 0.0.651
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 +5 -20
- package/package.json +5 -5
- package/schemas/last.json +15 -0
- package/src/bin.ts +9 -31
- package/src/cache/cache.ts +225 -51
- package/src/cache/file-hashes.ts +3 -0
- package/src/cache/fold-memo.ts +8 -1
- package/src/cache/git-inputs.ts +188 -39
- package/src/cache/index.ts +12 -0
- package/src/cache/inputs.ts +3 -0
- package/src/cache/layer.ts +11 -0
- package/src/cache/layered-cache.ts +4 -0
- package/src/cache/linked-inputs.ts +3 -0
- package/src/cache/lockfile-memo.ts +120 -0
- package/src/cache/output-index.ts +5 -2
- package/src/cache/remote-hits.ts +9 -1
- package/src/cache/remote-lane.ts +2 -1
- package/src/cache/run-history.ts +11 -1
- package/src/cache/run-notes.ts +123 -0
- package/src/cache/schema.ts +54 -1
- package/src/cli/cache.ts +26 -16
- package/src/cli/completions.ts +4 -2
- package/src/cli/docs.ts +10 -11
- package/src/cli/help.ts +12 -23
- package/src/cli/index.ts +4 -9
- package/src/cli/info.ts +15 -7
- package/src/cli/init.ts +23 -15
- package/src/cli/last.ts +224 -223
- package/src/cli/lock.ts +55 -5
- package/src/cli/plan-format.ts +100 -118
- package/src/cli/plugin-commands.ts +10 -3
- package/src/cli/plugin-templates.ts +2 -2
- package/src/cli/run.ts +46 -27
- package/src/cli/select.ts +43 -5
- package/src/cli/show.ts +38 -42
- package/src/cli/task-verb.ts +22 -0
- package/src/cli/upgrade.ts +3 -1
- package/src/cli/watch-fs.ts +6 -1
- package/src/cli/watch-judge.ts +2 -1
- package/src/cli/watch.ts +83 -44
- package/src/cli/why.ts +126 -92
- package/src/cli/workspace-config.ts +2 -1
- package/src/exec/executor.ts +2 -1
- package/src/exec/kill-tree.ts +58 -5
- package/src/exec/local-executor.ts +1 -1
- package/src/exec/pipes.ts +152 -0
- package/src/exec/runner.ts +199 -182
- package/src/exec/sandbox-binds.ts +1 -1
- package/src/exec/sandbox-runtime.ts +11 -2
- package/src/exec/spawn-off.ts +154 -0
- package/src/exec/warm-shell.ts +146 -0
- package/src/graph/critical-path.ts +40 -28
- package/src/graph/priorities.ts +98 -44
- package/src/graph/scheduler.ts +12 -2
- package/src/graph/task-graph.ts +27 -1
- package/src/handoff.ts +10 -7
- package/src/history/history.ts +39 -2
- package/src/history/index.ts +3 -0
- package/src/history/metrics.ts +9 -1
- package/src/index.ts +12 -3
- package/src/orchestrator/doctor.ts +3 -3
- package/src/orchestrator/execute-task.ts +16 -2
- package/src/orchestrator/graph-memo.ts +50 -1
- package/src/orchestrator/graph-stage.ts +6 -0
- package/src/orchestrator/hit-restore.ts +3 -0
- package/src/orchestrator/index.ts +3 -1
- package/src/orchestrator/live-usage.ts +98 -0
- package/src/orchestrator/locked-digests.ts +63 -0
- package/src/orchestrator/lockfile-claim.ts +176 -102
- package/src/orchestrator/miss-save.ts +31 -3
- package/src/orchestrator/persistent-task.ts +3 -1
- package/src/orchestrator/plan.ts +5 -1
- package/src/orchestrator/plugin-host.ts +61 -0
- package/src/orchestrator/plugin.ts +49 -4
- package/src/orchestrator/prepare.ts +18 -2
- package/src/orchestrator/projects.ts +4 -1
- package/src/orchestrator/run-context.ts +29 -10
- package/src/orchestrator/run-failures.ts +35 -114
- package/src/orchestrator/run-records.ts +10 -0
- package/src/orchestrator/run.ts +89 -26
- package/src/orchestrator/sandbox-request.ts +2 -2
- package/src/orchestrator/signals.ts +8 -5
- package/src/orchestrator/steps.ts +2 -2
- package/src/orchestrator/task-hash.ts +17 -3
- package/src/report/forecast.ts +12 -33
- package/src/report/framed-output.ts +388 -161
- package/src/report/index.ts +8 -2
- package/src/report/logger.ts +100 -36
- package/src/report/status-line.ts +81 -365
- package/src/report/summary.ts +104 -131
- package/src/ui/ansi.ts +48 -0
- package/src/ui/components.ts +506 -0
- package/src/ui/index.ts +79 -0
- package/src/ui/kit.ts +37 -0
- package/src/ui/live-region.ts +363 -0
- package/src/{util/refusal-notice.ts → ui/refusal.ts} +7 -5
- package/src/ui/terminal.ts +51 -0
- package/src/ui/theme.ts +224 -0
- package/src/ui/version-line.ts +28 -0
- package/src/util/config-frame.ts +65 -10
- package/src/util/edit-distance.ts +6 -1
- package/src/util/hidden-prompt.ts +8 -2
- package/src/util/index.ts +2 -15
- package/src/util/paths.ts +20 -2
- package/src/util/secret-mask.ts +39 -3
- package/src/util/secrets.ts +3 -0
- package/src/util/settle.ts +31 -0
- package/src/util/timing.ts +4 -16
- package/src/workspace/affected.ts +89 -30
- package/src/workspace/config-schema.ts +4 -2
- package/src/workspace/dependencies-lock.ts +191 -0
- package/src/workspace/filter.ts +28 -0
- package/src/workspace/index.ts +9 -0
- package/src/workspace/lockfile.ts +159 -6
- package/src/workspace/migration.ts +4 -3
- package/src/workspace/workspace.ts +3 -0
- package/src/orchestrator/run-steps.ts +0 -93
- package/src/util/colors.ts +0 -130
- package/src/util/report.ts +0 -44
- package/src/util/ui.ts +0 -258
- /package/src/{report/path-links.ts → ui/links.ts} +0 -0
- /package/src/{report → ui}/terminal-signals.ts +0 -0
package/src/report/index.ts
CHANGED
|
@@ -30,8 +30,14 @@ export {
|
|
|
30
30
|
resolveOutputView,
|
|
31
31
|
warnOf,
|
|
32
32
|
} from './logger.js'
|
|
33
|
-
export {
|
|
33
|
+
export {
|
|
34
|
+
formatPersistentList,
|
|
35
|
+
formatRecordedRow,
|
|
36
|
+
planList,
|
|
37
|
+
type PlannedRow,
|
|
38
|
+
taskList,
|
|
39
|
+
} from './framed-output.js'
|
|
34
40
|
export { createForecast } from './forecast.js'
|
|
35
|
-
export { fileLocations, fileMemo, type OutputLocation } from './path-links.js'
|
|
36
41
|
export { plainOutput } from './plain-output.js'
|
|
42
|
+
export type { LiveUsage } from './status-line.js'
|
|
37
43
|
export { formatOutcomeTable, formatRunSummary } from './summary.js'
|
package/src/report/logger.ts
CHANGED
|
@@ -6,25 +6,22 @@ import {
|
|
|
6
6
|
formatKeptLines,
|
|
7
7
|
formatPersistentTailBlock,
|
|
8
8
|
formatListHeader,
|
|
9
|
+
usualCell,
|
|
9
10
|
formatTaskAbortedLine,
|
|
10
11
|
formatTaskBlock,
|
|
12
|
+
executedCells,
|
|
11
13
|
formatTaskExecutedLine,
|
|
12
14
|
flakyNote,
|
|
13
15
|
pathNote,
|
|
14
|
-
whereNote,
|
|
15
16
|
formatTaskHashLine,
|
|
16
17
|
formatTaskHitLine,
|
|
17
18
|
formatTaskSkippedLine,
|
|
18
|
-
leavesStyle,
|
|
19
|
-
RESET,
|
|
20
19
|
type OutputChunk,
|
|
21
20
|
} from './framed-output.js'
|
|
22
21
|
import {
|
|
23
|
-
createOutputWriter,
|
|
24
22
|
formatFailureLine,
|
|
25
23
|
formatStatusRegion,
|
|
26
24
|
formatStepLine,
|
|
27
|
-
type StatusStream,
|
|
28
25
|
type WorkerSlot,
|
|
29
26
|
} from './status-line.js'
|
|
30
27
|
import {
|
|
@@ -43,21 +40,26 @@ import {
|
|
|
43
40
|
resetTail,
|
|
44
41
|
tailText,
|
|
45
42
|
type Tail,
|
|
46
|
-
detectColors,
|
|
47
43
|
envFlagOn,
|
|
48
|
-
type ColorSupport,
|
|
49
|
-
ui,
|
|
50
44
|
} from '../util/index.js'
|
|
51
|
-
import
|
|
52
|
-
import { failedLabel, outcomeWord, ranNoCache } from './events.js'
|
|
53
|
-
import type { BlockedTask, Forecast } from './forecast.js'
|
|
45
|
+
import * as ui from '../ui/index.js'
|
|
54
46
|
import {
|
|
47
|
+
createOutputWriter,
|
|
48
|
+
detectColors,
|
|
49
|
+
hasEscape,
|
|
50
|
+
leavesStyle,
|
|
55
51
|
notifyEscape,
|
|
56
52
|
PROGRESS_CLEAR,
|
|
57
53
|
progressEscape,
|
|
54
|
+
STYLE_END,
|
|
58
55
|
terminalLinks,
|
|
59
56
|
terminalSignals,
|
|
60
|
-
|
|
57
|
+
type ColorSupport,
|
|
58
|
+
type StatusStream,
|
|
59
|
+
} from '../ui/index.js'
|
|
60
|
+
import { isCacheHit } from '../graph/index.js'
|
|
61
|
+
import { failedLabel, outcomeWord, ranNoCache } from './events.js'
|
|
62
|
+
import type { BlockedTask, Forecast } from './forecast.js'
|
|
61
63
|
|
|
62
64
|
export interface Logger {
|
|
63
65
|
/** Header / footer / status text. Written verbatim, one trailing \n added. */
|
|
@@ -353,7 +355,7 @@ export function defaultLogger(
|
|
|
353
355
|
// Tasks the region showed on the critical path: their finished rows say so too.
|
|
354
356
|
const onPath = new Set<string>()
|
|
355
357
|
let blockedCount = 0
|
|
356
|
-
|
|
358
|
+
// Each task's usual time once history is read: the results' `±usual`.
|
|
357
359
|
let blocked: readonly BlockedTask[] | undefined
|
|
358
360
|
let blockedBy: ReadonlyMap<string, number> | undefined
|
|
359
361
|
let etaAtMs = 0
|
|
@@ -518,7 +520,6 @@ export function defaultLogger(
|
|
|
518
520
|
: Math.min(deadlineMs ?? now, now)
|
|
519
521
|
critical = f.critical
|
|
520
522
|
blockedCount = f.waiting
|
|
521
|
-
expected = f.expected
|
|
522
523
|
blocked = f.blocked
|
|
523
524
|
blockedBy = f.blockedBy
|
|
524
525
|
}
|
|
@@ -604,7 +605,8 @@ export function defaultLogger(
|
|
|
604
605
|
nowMs: Date.now(),
|
|
605
606
|
summaryLines,
|
|
606
607
|
...(runContext?.whereRunning !== undefined ? { where: runContext.whereRunning } : {}),
|
|
607
|
-
...(
|
|
608
|
+
...(runContext?.usage !== undefined ? { usage: runContext.usage } : {}),
|
|
609
|
+
...(runContext?.usual !== undefined ? { usual: runContext.usual } : {}),
|
|
608
610
|
...(critical !== undefined ? { critical } : {}),
|
|
609
611
|
},
|
|
610
612
|
colors,
|
|
@@ -654,7 +656,7 @@ export function defaultLogger(
|
|
|
654
656
|
// task`, and took its colour.
|
|
655
657
|
let streamStyled = false
|
|
656
658
|
const endStreamLine = (): void => {
|
|
657
|
-
const end = (streamStyled ?
|
|
659
|
+
const end = (streamStyled ? STYLE_END : '') + (streamMidLine ? '\n' : '')
|
|
658
660
|
streamStyled = false
|
|
659
661
|
streamMidLine = false
|
|
660
662
|
if (end.length > 0) logWrite(end)
|
|
@@ -666,10 +668,11 @@ export function defaultLogger(
|
|
|
666
668
|
const streamWrite = (chunk: string): void => {
|
|
667
669
|
streamedSinceBlock = true
|
|
668
670
|
if (chunk.length > 0) streamMidLine = !chunk.endsWith('\n')
|
|
669
|
-
if (chunk
|
|
671
|
+
if (hasEscape(chunk)) streamStyled = leavesStyle(chunk)
|
|
670
672
|
logWrite(chunk)
|
|
671
673
|
}
|
|
672
674
|
const logWrite = (chunk: string): void => {
|
|
675
|
+
if (panelOpen !== undefined && !inPanel && chunk.length > 0) closePanel()
|
|
673
676
|
if (chunk.length > 0) endsBlank = chunk.endsWith('\n\n')
|
|
674
677
|
if (!logOpened && chunk.length > 0) {
|
|
675
678
|
logOpened = true
|
|
@@ -682,15 +685,33 @@ export function defaultLogger(
|
|
|
682
685
|
taskWrite(`${line}\n`)
|
|
683
686
|
lineEmitted = true
|
|
684
687
|
}
|
|
685
|
-
// The
|
|
686
|
-
//
|
|
687
|
-
|
|
688
|
+
// The open panel: rows of one kind share one box, the Tasks list on the
|
|
689
|
+
// log's stream and the Warnings on stderr; anything else said closes it
|
|
690
|
+
// first, and the next row opens it again. Painted, a box; plain on a
|
|
691
|
+
// terminal, the Tasks rule and header over the rows, as the live region
|
|
692
|
+
// heads its own (2026-10-21); piped, the bare rows a script reads.
|
|
693
|
+
const panels = colors.enabled || writer.enabled
|
|
694
|
+
let panelOpen: 'Tasks' | 'Warnings' | undefined
|
|
695
|
+
let inPanel = false
|
|
696
|
+
function closePanel(): void {
|
|
697
|
+
const was = panelOpen
|
|
698
|
+
if (was === undefined) return
|
|
699
|
+
panelOpen = undefined
|
|
700
|
+
}
|
|
688
701
|
const emitRow = (line: string): void => {
|
|
689
|
-
if (!
|
|
690
|
-
|
|
691
|
-
|
|
702
|
+
if (!panels) {
|
|
703
|
+
emitLine(line)
|
|
704
|
+
return
|
|
705
|
+
}
|
|
706
|
+
if (panelOpen === 'Warnings') closePanel()
|
|
707
|
+
inPanel = true
|
|
708
|
+
if (panelOpen !== 'Tasks') {
|
|
709
|
+
emitLine(ui.panelTop('Tasks', colors))
|
|
710
|
+
emitLine(formatListHeader(colors))
|
|
711
|
+
panelOpen = 'Tasks'
|
|
692
712
|
}
|
|
693
713
|
emitLine(line)
|
|
714
|
+
inPanel = false
|
|
694
715
|
}
|
|
695
716
|
// formatTaskBlock returns '' for group tasks (no exec) — skip the
|
|
696
717
|
// write so a stray newline doesn't sneak into the output.
|
|
@@ -731,10 +752,17 @@ export function defaultLogger(
|
|
|
731
752
|
(framesTerminal && holdsTerminal(node)) ||
|
|
732
753
|
(view.mode === 'focused' && isPrimary(node) && !isGroupTask(node) && requestedCount <= 1)
|
|
733
754
|
|
|
755
|
+
// How many tasks are downstream of each: every results row's `blocks`.
|
|
756
|
+
const blocksOf = (id: string): number | undefined => runContext?.blocks?.().get(id)
|
|
757
|
+
// A row's usual time: null for a task history never timed, undefined with no history to ask.
|
|
758
|
+
const usualMsOf = (id: string): number | null | undefined =>
|
|
759
|
+
runContext?.usual === undefined ? undefined : (runContext.usual(id) ?? null)
|
|
734
760
|
const failureRow = (node: TaskNode, outcome: TaskOutcome): string =>
|
|
735
|
-
formatFailureLine(node.id, outcome.durationMs, colors, cacheWordOf(outcome)
|
|
761
|
+
formatFailureLine(node.id, outcome.durationMs, colors, cacheWordOf(outcome), {
|
|
762
|
+
...executedCells(outcome, blocksOf(node.id)),
|
|
763
|
+
usual: usualCell(outcome.durationMs, usualMsOf(node.id), colors),
|
|
764
|
+
}) +
|
|
736
765
|
(onPath.has(node.id) ? pathNote(colors) : '') +
|
|
737
|
-
whereNote(outcome, colors) +
|
|
738
766
|
flakyNote(outcome, colors)
|
|
739
767
|
|
|
740
768
|
return {
|
|
@@ -751,6 +779,7 @@ export function defaultLogger(
|
|
|
751
779
|
// A live-streamed server keeps writing after its frame closes, so a
|
|
752
780
|
// summary row or "exited with code" can follow its partial line.
|
|
753
781
|
endStreamLine()
|
|
782
|
+
closePanel()
|
|
754
783
|
if (line === '' && endsBlank) return
|
|
755
784
|
endsBlank = line === ''
|
|
756
785
|
writer.write(`${line}\n`)
|
|
@@ -758,7 +787,20 @@ export function defaultLogger(
|
|
|
758
787
|
warn(line) {
|
|
759
788
|
flushKept()
|
|
760
789
|
endStreamLine()
|
|
761
|
-
|
|
790
|
+
if (!colors.enabled) {
|
|
791
|
+
writer.writeTo(errOut, `${ui.tagged('warn', line, colors)}\n`)
|
|
792
|
+
return
|
|
793
|
+
}
|
|
794
|
+
if (panelOpen === 'Tasks') closePanel()
|
|
795
|
+
if (panelOpen !== 'Warnings') {
|
|
796
|
+
writer.writeTo(errOut, `${ui.panelTop('Warnings', colors)}\n`)
|
|
797
|
+
panelOpen = 'Warnings'
|
|
798
|
+
}
|
|
799
|
+
const rows = line
|
|
800
|
+
.replace(/\n+$/, '')
|
|
801
|
+
.split('\n')
|
|
802
|
+
.map((l) => ui.tagged('warn', l, colors))
|
|
803
|
+
writer.writeTo(errOut, `${rows.join('\n')}\n`)
|
|
762
804
|
},
|
|
763
805
|
runStart(info) {
|
|
764
806
|
total = info.total
|
|
@@ -766,7 +808,13 @@ export function defaultLogger(
|
|
|
766
808
|
runContext = info.context
|
|
767
809
|
startedAtMs = Date.now()
|
|
768
810
|
started = true
|
|
769
|
-
slots
|
|
811
|
+
// No more slots than tasks: one per allowed worker, every frame walked
|
|
812
|
+
// them all (`--concurrency=100000000` over six tasks took 80 s, and
|
|
813
|
+
// 2^32 threw here).
|
|
814
|
+
slots = Array.from(
|
|
815
|
+
{ length: Math.max(1, Math.min(info.concurrency ?? 10, info.total)) },
|
|
816
|
+
() => null,
|
|
817
|
+
)
|
|
770
818
|
tick()
|
|
771
819
|
refresh(true)
|
|
772
820
|
},
|
|
@@ -820,7 +868,11 @@ export function defaultLogger(
|
|
|
820
868
|
}
|
|
821
869
|
// The rows are the status region's; with none, nothing reads them.
|
|
822
870
|
if (statusDead) return
|
|
823
|
-
const slot: WorkerSlot = {
|
|
871
|
+
const slot: WorkerSlot = {
|
|
872
|
+
id: node.id,
|
|
873
|
+
startedMs: Date.now(),
|
|
874
|
+
cache: ranNoCache({ node }) ? 'no-cache' : 'miss',
|
|
875
|
+
}
|
|
824
876
|
const free = slots.indexOf(null)
|
|
825
877
|
if (free >= 0) slots[free] = slot
|
|
826
878
|
else slotQueue.push(slot)
|
|
@@ -912,6 +964,7 @@ export function defaultLogger(
|
|
|
912
964
|
flushedFailures = true
|
|
913
965
|
for (const block of deferredFailures) emitBlock(fenced(block))
|
|
914
966
|
}
|
|
967
|
+
closePanel()
|
|
915
968
|
// The summary and the CLI's own lines follow on the stream directly:
|
|
916
969
|
// nothing may still be held, and nothing after this is.
|
|
917
970
|
writer.settle()
|
|
@@ -1016,7 +1069,7 @@ export function defaultLogger(
|
|
|
1016
1069
|
// Otherwise a row in the task list, in every view that lists a
|
|
1017
1070
|
// failure: the run exits red, and the row names why.
|
|
1018
1071
|
if (view.mode !== 'none' && view.mode !== 'hash-only') {
|
|
1019
|
-
emitRow(formatTaskAbortedLine(node, outcome, colors))
|
|
1072
|
+
emitRow(formatTaskAbortedLine(node, outcome, colors, blocksOf(node.id)))
|
|
1020
1073
|
}
|
|
1021
1074
|
return
|
|
1022
1075
|
}
|
|
@@ -1099,7 +1152,7 @@ export function defaultLogger(
|
|
|
1099
1152
|
}
|
|
1100
1153
|
case 'errors-only':
|
|
1101
1154
|
if (outcome.status === 'skipped') {
|
|
1102
|
-
emitRow(formatTaskSkippedLine(node, colors, outcome))
|
|
1155
|
+
emitRow(formatTaskSkippedLine(node, colors, outcome, blocksOf(node.id)))
|
|
1103
1156
|
return
|
|
1104
1157
|
}
|
|
1105
1158
|
if (outcome.status !== 'failed') return
|
|
@@ -1136,9 +1189,18 @@ export function defaultLogger(
|
|
|
1136
1189
|
),
|
|
1137
1190
|
)
|
|
1138
1191
|
} else if (outcome.status === 'success') {
|
|
1139
|
-
emitRow(
|
|
1192
|
+
emitRow(
|
|
1193
|
+
formatTaskExecutedLine(
|
|
1194
|
+
node,
|
|
1195
|
+
outcome,
|
|
1196
|
+
colors,
|
|
1197
|
+
onPath.has(node.id),
|
|
1198
|
+
blocksOf(node.id),
|
|
1199
|
+
usualMsOf(node.id),
|
|
1200
|
+
),
|
|
1201
|
+
)
|
|
1140
1202
|
} else if (outcome.status === 'skipped') {
|
|
1141
|
-
emitRow(formatTaskSkippedLine(node, colors, outcome))
|
|
1203
|
+
emitRow(formatTaskSkippedLine(node, colors, outcome, blocksOf(node.id)))
|
|
1142
1204
|
}
|
|
1143
1205
|
return
|
|
1144
1206
|
case 'focused':
|
|
@@ -1147,7 +1209,7 @@ export function defaultLogger(
|
|
|
1147
1209
|
// stopped), so no frame-open fired — and a skip has no output,
|
|
1148
1210
|
// so a one-liner carries everything a frame would.
|
|
1149
1211
|
if (outcome.status === 'skipped') {
|
|
1150
|
-
emitRow(formatTaskSkippedLine(node, colors, outcome))
|
|
1212
|
+
emitRow(formatTaskSkippedLine(node, colors, outcome, blocksOf(node.id)))
|
|
1151
1213
|
return
|
|
1152
1214
|
}
|
|
1153
1215
|
if (streamsLive(node)) {
|
|
@@ -1198,7 +1260,7 @@ export function defaultLogger(
|
|
|
1198
1260
|
// Dependency-pulled nodes: silent on success; a skip gets its
|
|
1199
1261
|
// row, failures the ◼ row now and their frame replayed at runEnd.
|
|
1200
1262
|
if (outcome.status === 'skipped') {
|
|
1201
|
-
emitRow(formatTaskSkippedLine(node, colors, outcome))
|
|
1263
|
+
emitRow(formatTaskSkippedLine(node, colors, outcome, blocksOf(node.id)))
|
|
1202
1264
|
} else if (outcome.status === 'failed') {
|
|
1203
1265
|
emitRow(failureRow(node, outcome))
|
|
1204
1266
|
deferredFailures.push(
|
|
@@ -1222,11 +1284,13 @@ export function defaultLogger(
|
|
|
1222
1284
|
// point); misses/failures are always framed. One-liners
|
|
1223
1285
|
// stay outside ::group:: — there's nothing to collapse.
|
|
1224
1286
|
if (isHit && output.every((c) => c.text.trim().length === 0)) {
|
|
1225
|
-
emitRow(
|
|
1287
|
+
emitRow(
|
|
1288
|
+
formatTaskHitLine(node, outcome, colors, onPath.has(node.id), blocksOf(node.id)),
|
|
1289
|
+
)
|
|
1226
1290
|
return
|
|
1227
1291
|
}
|
|
1228
1292
|
if (outcome.status === 'skipped') {
|
|
1229
|
-
emitRow(formatTaskSkippedLine(node, colors, outcome))
|
|
1293
|
+
emitRow(formatTaskSkippedLine(node, colors, outcome, blocksOf(node.id)))
|
|
1230
1294
|
return
|
|
1231
1295
|
}
|
|
1232
1296
|
const block = formatTaskBlock(
|