nx 23.3.0-beta.0 → 23.3.0-beta.2

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 (184) hide show
  1. package/dist/src/command-line/format/format.js +2 -18
  2. package/dist/src/command-line/graph/graph.js +42 -3
  3. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +0 -3
  4. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +0 -3
  5. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +0 -3
  6. package/dist/src/command-line/init/implementation/angular/index.js +0 -3
  7. package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +0 -3
  8. package/dist/src/command-line/init/implementation/format.js +2 -3
  9. package/dist/src/command-line/init/implementation/utils.d.ts +0 -1
  10. package/dist/src/command-line/init/implementation/utils.js +0 -8
  11. package/dist/src/command-line/init/init-v2.js +0 -3
  12. package/dist/src/command-line/migrate/agentic/definitions.js +75 -19
  13. package/dist/src/command-line/migrate/agentic/format-command.d.ts +14 -0
  14. package/dist/src/command-line/migrate/agentic/format-command.js +44 -0
  15. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +3 -3
  16. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +3 -3
  17. package/dist/src/command-line/migrate/agentic/handoff.d.ts +27 -17
  18. package/dist/src/command-line/migrate/agentic/handoff.js +107 -24
  19. package/dist/src/command-line/migrate/agentic/instruction-files.d.ts +21 -0
  20. package/dist/src/command-line/migrate/agentic/instruction-files.js +36 -0
  21. package/dist/src/command-line/migrate/agentic/prompts/fragments.d.ts +16 -0
  22. package/dist/src/command-line/migrate/agentic/prompts/fragments.js +70 -0
  23. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +4 -3
  24. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +25 -1
  25. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +57 -34
  26. package/dist/src/command-line/migrate/agentic/run-step.js +28 -4
  27. package/dist/src/command-line/migrate/agentic/runner.d.ts +17 -8
  28. package/dist/src/command-line/migrate/agentic/runner.js +110 -55
  29. package/dist/src/command-line/migrate/agentic/types.d.ts +23 -8
  30. package/dist/src/command-line/migrate/agentic/types.js +10 -7
  31. package/dist/src/command-line/migrate/migrate-commits.d.ts +1 -0
  32. package/dist/src/command-line/migrate/migrate-commits.js +9 -0
  33. package/dist/src/command-line/migrate/migrate-output.d.ts +3 -7
  34. package/dist/src/command-line/migrate/migrate-output.js +3 -7
  35. package/dist/src/command-line/migrate/migrate.js +21 -8
  36. package/dist/src/command-line/migrate/run/agent-output.d.ts +10 -0
  37. package/dist/src/command-line/migrate/run/agent-output.js +16 -2
  38. package/dist/src/command-line/migrate/run/agent-work-payload.d.ts +37 -0
  39. package/dist/src/command-line/migrate/run/agent-work-payload.js +142 -0
  40. package/dist/src/command-line/migrate/run/atomic-write.d.ts +8 -0
  41. package/dist/src/command-line/migrate/run/atomic-write.js +17 -0
  42. package/dist/src/command-line/migrate/run/index.d.ts +1 -1
  43. package/dist/src/command-line/migrate/run/issues.d.ts +106 -0
  44. package/dist/src/command-line/migrate/run/issues.js +980 -0
  45. package/dist/src/command-line/migrate/run/orchestrator.d.ts +1 -0
  46. package/dist/src/command-line/migrate/run/orchestrator.js +662 -105
  47. package/dist/src/command-line/migrate/run/run-state.d.ts +43 -8
  48. package/dist/src/command-line/migrate/run/run-state.js +184 -20
  49. package/dist/src/command-line/migrate/run/runbook.d.ts +17 -0
  50. package/dist/src/command-line/migrate/run/runbook.js +97 -0
  51. package/dist/src/command-line/migrate/run/state-lock.d.ts +2 -2
  52. package/dist/src/command-line/migrate/run/state-lock.js +2 -2
  53. package/dist/src/command-line/migrate/run/state-machine.d.ts +5 -1
  54. package/dist/src/command-line/migrate/run/state-machine.js +27 -1
  55. package/dist/src/command-line/migrate/run/worker.js +206 -56
  56. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +5 -11
  57. package/dist/src/command-line/release/publish.js +11 -4
  58. package/dist/src/command-line/release/utils/remote-release-clients/github.js +3 -3
  59. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +3 -3
  60. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +2 -0
  61. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.js +35 -0
  62. package/dist/src/command-line/report/report.d.ts +2 -0
  63. package/dist/src/command-line/report/report.js +28 -1
  64. package/dist/src/command-line/yargs-utils/shared-options.d.ts +1 -1
  65. package/dist/src/command-line/yargs-utils/shared-options.js +22 -4
  66. package/dist/src/config/workspace-json-project-json.d.ts +2 -0
  67. package/dist/src/core/graph/main.js +1 -1
  68. package/dist/src/daemon/client/client.d.ts +6 -2
  69. package/dist/src/daemon/client/client.js +27 -11
  70. package/dist/src/daemon/message-types/get-plugin-capabilities.d.ts +5 -0
  71. package/dist/src/daemon/message-types/get-plugin-capabilities.js +11 -0
  72. package/dist/src/daemon/message-types/run-tasks-execution-hooks.d.ts +3 -2
  73. package/dist/src/daemon/server/handle-get-plugin-capabilities.d.ts +2 -0
  74. package/dist/src/daemon/server/handle-get-plugin-capabilities.js +13 -0
  75. package/dist/src/daemon/server/handle-hash-tasks.d.ts +8 -2
  76. package/dist/src/daemon/server/handle-hash-tasks.js +16 -3
  77. package/dist/src/daemon/server/handle-outputs-changes.d.ts +2 -2
  78. package/dist/src/daemon/server/handle-outputs-changes.js +21 -6
  79. package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +3 -2
  80. package/dist/src/daemon/server/outputs-tracking.d.ts +6 -0
  81. package/dist/src/daemon/server/outputs-tracking.js +18 -0
  82. package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +22 -7
  83. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +100 -70
  84. package/dist/src/daemon/server/restart-checks.d.ts +22 -0
  85. package/dist/src/daemon/server/restart-checks.js +77 -0
  86. package/dist/src/daemon/server/server.js +33 -18
  87. package/dist/src/daemon/server/shutdown-utils.d.ts +0 -5
  88. package/dist/src/daemon/server/shutdown-utils.js +3 -26
  89. package/dist/src/hasher/hash-task.js +20 -16
  90. package/dist/src/hasher/native-task-hasher-impl.d.ts +8 -0
  91. package/dist/src/hasher/native-task-hasher-impl.js +46 -3
  92. package/dist/src/hasher/task-hasher.d.ts +9 -0
  93. package/dist/src/hasher/task-hasher.js +14 -0
  94. package/dist/src/native/index.d.ts +222 -21
  95. package/dist/src/native/index.js +3 -3
  96. package/dist/src/native/native-bindings.js +4 -1
  97. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  98. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  99. package/dist/src/plugins/js/lock-file/pnpm-parser.js +1 -1
  100. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.d.ts +2 -0
  101. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +22 -0
  102. package/dist/src/plugins/js/utils/register.js +2 -1
  103. package/dist/src/project-graph/affected/locators/project-glob-changes.js +19 -26
  104. package/dist/src/project-graph/error-types.d.ts +5 -0
  105. package/dist/src/project-graph/error-types.js +44 -5
  106. package/dist/src/project-graph/file-utils.d.ts +2 -0
  107. package/dist/src/project-graph/file-utils.js +6 -1
  108. package/dist/src/project-graph/nx-deps-cache.d.ts +5 -2
  109. package/dist/src/project-graph/nx-deps-cache.js +4 -4
  110. package/dist/src/project-graph/plugins/get-plugins.d.ts +3 -1
  111. package/dist/src/project-graph/plugins/get-plugins.js +60 -82
  112. package/dist/src/project-graph/plugins/in-process-loader.d.ts +1 -1
  113. package/dist/src/project-graph/plugins/in-process-loader.js +1 -4
  114. package/dist/src/project-graph/plugins/isolation/index.d.ts +1 -1
  115. package/dist/src/project-graph/plugins/isolation/index.js +3 -1
  116. package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +8 -0
  117. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +42 -6
  118. package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.d.ts +10 -1
  119. package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.js +67 -17
  120. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +3 -2
  121. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +5 -1
  122. package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +5 -2
  123. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +14 -1
  124. package/dist/src/project-graph/plugins/nx-plugin-capabilities.d.ts +6 -0
  125. package/dist/src/project-graph/plugins/nx-plugin-capabilities.js +28 -0
  126. package/dist/src/project-graph/plugins/task-results-stub.d.ts +50 -0
  127. package/dist/src/project-graph/plugins/task-results-stub.js +111 -0
  128. package/dist/src/project-graph/plugins/tasks-execution-hooks.d.ts +3 -2
  129. package/dist/src/project-graph/plugins/tasks-execution-hooks.js +14 -1
  130. package/dist/src/project-graph/project-graph.js +43 -42
  131. package/dist/src/tasks-runner/batch/run-batch.js +15 -0
  132. package/dist/src/tasks-runner/cache.d.ts +35 -0
  133. package/dist/src/tasks-runner/cache.js +40 -0
  134. package/dist/src/tasks-runner/create-task-graph.js +1 -0
  135. package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
  136. package/dist/src/tasks-runner/forked-process-task-runner.d.ts +1 -1
  137. package/dist/src/tasks-runner/forked-process-task-runner.js +8 -7
  138. package/dist/src/tasks-runner/init-tasks-runner.js +5 -1
  139. package/dist/src/tasks-runner/is-tui-enabled.js +4 -3
  140. package/dist/src/tasks-runner/life-cycle.d.ts +7 -0
  141. package/dist/src/tasks-runner/life-cycle.js +7 -0
  142. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.d.ts +35 -0
  143. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.js +146 -0
  144. package/dist/src/tasks-runner/prune-task-graph.d.ts +17 -0
  145. package/dist/src/tasks-runner/prune-task-graph.js +45 -0
  146. package/dist/src/tasks-runner/run-command.js +14 -3
  147. package/dist/src/tasks-runner/running-tasks/batch-process.d.ts +93 -19
  148. package/dist/src/tasks-runner/running-tasks/batch-process.js +184 -88
  149. package/dist/src/tasks-runner/task-orchestrator.d.ts +64 -2
  150. package/dist/src/tasks-runner/task-orchestrator.js +232 -46
  151. package/dist/src/tasks-runner/terminal-output-path.d.ts +11 -0
  152. package/dist/src/tasks-runner/terminal-output-path.js +18 -0
  153. package/dist/src/tasks-runner/utils.js +5 -2
  154. package/dist/src/utils/ab-testing.d.ts +4 -1
  155. package/dist/src/utils/ab-testing.js +11 -7
  156. package/dist/src/utils/chunkify.d.ts +1 -7
  157. package/dist/src/utils/chunkify.js +2 -8
  158. package/dist/src/utils/command-line-utils.d.ts +19 -0
  159. package/dist/src/utils/command-line-utils.js +10 -3
  160. package/dist/src/utils/formatters/index.d.ts +6 -0
  161. package/dist/src/utils/formatters/index.js +5 -0
  162. package/dist/src/utils/formatters/prettier.d.ts +0 -8
  163. package/dist/src/utils/formatters/prettier.js +4 -26
  164. package/dist/src/utils/handle-errors.js +5 -43
  165. package/dist/src/utils/installed-nx-version.js +2 -48
  166. package/dist/src/utils/min-release-age/packument.js +1 -1
  167. package/dist/src/utils/output.d.ts +22 -3
  168. package/dist/src/utils/output.js +28 -5
  169. package/dist/src/utils/package-json.d.ts +25 -0
  170. package/dist/src/utils/package-json.js +41 -6
  171. package/dist/src/utils/package-manager.d.ts +6 -0
  172. package/dist/src/utils/package-manager.js +10 -0
  173. package/dist/src/utils/plugins/plugin-capabilities.js +7 -2
  174. package/dist/src/utils/provenance.js +20 -4
  175. package/dist/src/utils/serialize-overrides-into-command-line.js +2 -4
  176. package/dist/src/utils/workspace-context.d.ts +47 -3
  177. package/dist/src/utils/workspace-context.js +162 -10
  178. package/package.json +12 -13
  179. package/schemas/nx-schema.json +4 -0
  180. package/schemas/project-schema.json +4 -0
  181. package/dist/src/daemon/server/file-watching/route-workspace-changes.d.ts +0 -9
  182. package/dist/src/daemon/server/file-watching/route-workspace-changes.js +0 -76
  183. package/dist/src/daemon/server/watcher.d.ts +0 -18
  184. package/dist/src/daemon/server/watcher.js +0 -126
@@ -37,9 +37,22 @@ const utils_1 = require("./utils");
37
37
  function resolveBatchTaskStatus(result) {
38
38
  return result.status ?? (result.success ? 'success' : 'failure');
39
39
  }
40
+ /** Whether a path names a file with bytes in it. */
41
+ function hasContent(path) {
42
+ try {
43
+ return (0, fs_1.statSync)(path).size > 0;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
40
49
  class TaskOrchestrator {
41
50
  // endregion internal state
42
- constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, fullTaskGraph = taskGraph) {
51
+ constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon,
52
+ /** What the user named; undefined means they named nothing. */
53
+ specifiedOutputStyle,
54
+ /** What this run renders with, after defaults. */
55
+ resolvedOutputStyle, fullTaskGraph = taskGraph) {
43
56
  this.hasher = hasher;
44
57
  this.initiatingProject = initiatingProject;
45
58
  this.initiatingTasks = initiatingTasks;
@@ -49,7 +62,8 @@ class TaskOrchestrator {
49
62
  this.options = options;
50
63
  this.bail = bail;
51
64
  this.daemon = daemon;
52
- this.outputStyle = outputStyle;
65
+ this.specifiedOutputStyle = specifiedOutputStyle;
66
+ this.resolvedOutputStyle = resolvedOutputStyle;
53
67
  this.fullTaskGraph = fullTaskGraph;
54
68
  this.taskDetails = (0, hash_task_1.getTaskDetails)();
55
69
  this.cache = (0, cache_1.getCache)(this.options);
@@ -106,6 +120,13 @@ class TaskOrchestrator {
106
120
  this.continuousTaskExitHandled = new Map();
107
121
  this.cleanupPromise = null;
108
122
  this.signalHandlers = [];
123
+ // Tasks whose runner already owns the write to
124
+ // `<cacheDir>/terminalOutputs/<hash>` — forked processes write it as they
125
+ // exit, and the paths that never spawn one write it inline. The backstop in
126
+ // postRunSteps consults this so a task's output is written exactly once.
127
+ this.tasksWithPersistedOutput = new Set();
128
+ /** Batches whose worker log was handed to the life cycle, so it must survive. */
129
+ this.announcedBatchLogs = new Set();
109
130
  }
110
131
  async init() {
111
132
  this.setupSignalHandlers();
@@ -158,6 +179,10 @@ class TaskOrchestrator {
158
179
  perf_hooks_1.performance.measure('task-execution', 'task-execution:start', 'task-execution:end');
159
180
  if (!this.stopRequested) {
160
181
  this.cache.removeOldCacheRecords();
182
+ // Free function, not a cache method: `BatchProcess` writes these logs
183
+ // whichever cache implementation is active. It no-ops under WASM, where
184
+ // the native half does not exist.
185
+ (0, cache_1.sweepBatchOutputs)();
161
186
  }
162
187
  await this.cleanup();
163
188
  await this.dispose();
@@ -586,7 +611,7 @@ class TaskOrchestrator {
586
611
  const runBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:start');
587
612
  let batchProcess;
588
613
  try {
589
- batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.fullTaskGraph, env);
614
+ batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.fullTaskGraph, env, (0, output_1.printsTaskOutput)(this.resolvedOutputStyle));
590
615
  // Stream output from batch process to the batch
591
616
  batchProcess.onOutput((output) => {
592
617
  this.options.lifeCycle.appendBatchOutput?.(batch.id, output);
@@ -633,9 +658,13 @@ class TaskOrchestrator {
633
658
  terminalOutput: result.terminalOutput,
634
659
  };
635
660
  });
661
+ // The capture stream buffers, so both readers below would otherwise be
662
+ // racing bytes that have not reached the file yet.
663
+ await batchProcess.flushCapturedOutput();
636
664
  if ((0, output_1.shouldGroupBatchOutput)()) {
637
665
  this.renderBatchOutputSafely(batch.id, () => this.printGroupedBatchOutput(batch, taskResults, batchProcess.getCapturedOutputPath()));
638
666
  }
667
+ this.announceBatchWorkerLog(batch.id, taskResults, batchProcess.getCapturedOutputPath());
639
668
  return taskResults;
640
669
  }
641
670
  catch (e) {
@@ -652,15 +681,19 @@ class TaskOrchestrator {
652
681
  terminalOutput: isBatchStopping ? '' : (e.stack ?? e.message ?? ''),
653
682
  };
654
683
  });
684
+ await batchProcess?.flushCapturedOutput();
685
+ this.announceBatchWorkerLog(batch.id, taskResults, batchProcess?.getCapturedOutputPath());
655
686
  // The worker died without reporting results, so nothing was attributed to
656
687
  // a task and no per-task output ran. Everything it wrote went to
657
- // stdout/stderr, held back under log grouping — surface it as one fold.
658
- // Outside grouping it already streamed live. This matters just as much
659
- // when the batch was stopped: every task is marked stopped whether or not
660
- // it finished, so the log is the only record of what got through. Only
661
- // the exit-code error is dropped there, since it restates the
662
- // cancellation.
663
- if ((0, output_1.shouldGroupBatchOutput)()) {
688
+ // stdout/stderr, held back under grouping - surface it as one fold. Under
689
+ // a style that prints nothing there is no fold; the log is announced by
690
+ // path above instead. Outside both, it already streamed live. This
691
+ // matters just as much when the batch was stopped: every task
692
+ // is marked stopped whether or not it finished, so the log is the only
693
+ // record of what got through. Only the exit-code error is dropped there,
694
+ // since it restates the cancellation.
695
+ if ((0, output_1.shouldGroupBatchOutput)() &&
696
+ (0, output_1.printsTaskOutput)(this.resolvedOutputStyle)) {
664
697
  const capturedOutputPath = batchProcess?.getCapturedOutputPath();
665
698
  const trailer = isBatchStopping ? undefined : e.message;
666
699
  if (capturedOutputPath || trailer) {
@@ -673,11 +706,42 @@ class TaskOrchestrator {
673
706
  return taskResults;
674
707
  }
675
708
  finally {
676
- batchProcess?.discardCapturedOutput();
709
+ // Kept only when something failed and the log was announced; an all-green
710
+ // batch's chatter explains nothing and would sit in `batchOutputs/` until
711
+ // the sweep.
712
+ if (!this.announcedBatchLogs.has(batch.id)) {
713
+ batchProcess?.discardCapturedOutput();
714
+ }
677
715
  const runBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:end');
678
716
  perf_hooks_1.performance.measure('TaskOrchestrator-run-batch', runBatchStart.name, runBatchEnd.name);
679
717
  }
680
718
  }
719
+ /**
720
+ * Tells the life cycle where the batch worker's own log is, when something
721
+ * failed and a style that prints nothing would otherwise leave it unread.
722
+ *
723
+ * The path is announced rather than the bytes copied into a task: one worker
724
+ * produces one log, it explains the batch rather than any single task, and a
725
+ * task's own output file is read back verbatim on a cache hit.
726
+ */
727
+ announceBatchWorkerLog(batchId, results, capturedOutputPath) {
728
+ if (!capturedOutputPath || (0, output_1.printsTaskOutput)(this.resolvedOutputStyle)) {
729
+ return;
730
+ }
731
+ const failed = results.some((r) => r.status === 'failure' || r.status === 'stopped');
732
+ if (!failed) {
733
+ return;
734
+ }
735
+ // The path is minted when the file is opened, before any byte reaches it,
736
+ // so a capture that failed on its first write leaves one that exists and is
737
+ // empty. Announcing that offers the reader an address holding nothing.
738
+ // Checked after the flush, so the size is what a reader will actually see.
739
+ if (!hasContent(capturedOutputPath)) {
740
+ return;
741
+ }
742
+ this.announcedBatchLogs.add(batchId);
743
+ this.options.lifeCycle.batchOutputAvailable?.(batchId, capturedOutputPath);
744
+ }
681
745
  /**
682
746
  * Rendering a batch's output must never change the batch's results. A throw
683
747
  * from the printer would otherwise land in `runBatch`'s own error handling:
@@ -741,17 +805,20 @@ class TaskOrchestrator {
741
805
  * A batch that never reported results is handled by the caller instead.
742
806
  */
743
807
  printGroupedBatchOutput(batch, taskResults, capturedOutputPath) {
744
- // Read from the same field the streaming decision uses. `this.options` has
745
- // its own `outputStyle`, merged from `nx.json`'s tasksRunnerOptions, so the
746
- // two disagree whenever a style is configured there but not named on the
747
- // command line - and `init-tasks-runner` passes a populated `options` with
748
- // no style argument at all, so on that path only `options` can carry one.
808
+ // Reads `resolvedOutputStyle` - what the run actually renders with. The
809
+ // streaming decision deliberately reads `specifiedOutputStyle` instead,
810
+ // since it has to tell a named style from an inferred default. `this.options`
811
+ // has its own `outputStyle`, merged from `nx.json`'s tasksRunnerOptions, so
812
+ // the two disagree whenever a style is configured there but not named on the
813
+ // command line.
749
814
  const printsFullOutput = (0, output_1.printsFullTaskOutput)({
750
815
  verbose: this.options.verbose,
751
- outputStyle: this.outputStyle,
816
+ outputStyle: this.resolvedOutputStyle,
752
817
  });
753
818
  const batchOwnsTheDiagnostic = taskResults.some((r) => r.status === 'failure' || r.status === 'stopped');
754
- if ((printsFullOutput || batchOwnsTheDiagnostic) && capturedOutputPath) {
819
+ if ((0, output_1.printsTaskOutput)(this.resolvedOutputStyle) &&
820
+ (printsFullOutput || batchOwnsTheDiagnostic) &&
821
+ capturedOutputPath) {
755
822
  // No redirect lines: every task renders itself below, so there is nothing
756
823
  // to redirect anyone to.
757
824
  this.printBatchFold(batch, taskResults, { capturedOutputPath }, { redirectLines: false });
@@ -866,6 +933,10 @@ class TaskOrchestrator {
866
933
  if (this.completedTasks.has(task.id))
867
934
  return;
868
935
  const terminalOutput = e?.message ?? '';
936
+ // The worker rejected, so whatever the runner was going to leave on disk
937
+ // either never landed or can't be trusted. Hand the file back to
938
+ // postRunSteps so the failure itself is what the task's output path holds.
939
+ this.tasksWithPersistedOutput.delete(task.id);
869
940
  this.options.lifeCycle.printTaskTerminalOutput(task, 'failure', terminalOutput);
870
941
  await this.postRunSteps([{ task, status: 'failure', terminalOutput }], doNotSkipCache, groupId);
871
942
  }
@@ -880,7 +951,12 @@ class TaskOrchestrator {
880
951
  await this.preRunSteps([task], { groupId });
881
952
  const pipeOutput = await this.pipeOutputCapture(task);
882
953
  const temporaryOutputPath = this.cache.temporaryOutputPath(task);
883
- const streamOutput = (0, output_1.isStaticOutputStyle)(this.outputStyle)
954
+ // `summary` prints log paths rather than logs, and `shouldStreamOutput`
955
+ // would otherwise stream the initiating project's output in full - the one
956
+ // task a run-one is most likely to have. Continuous tasks are deliberately
957
+ // NOT suppressed the same way; see `startContinuousTask`.
958
+ const streamOutput = (0, output_1.isStaticOutputStyle)(this.specifiedOutputStyle) ||
959
+ !(0, output_1.printsTaskOutput)(this.resolvedOutputStyle)
884
960
  ? false
885
961
  : (0, utils_1.shouldStreamOutput)(task, this.initiatingProject);
886
962
  const env = pipeOutput
@@ -970,13 +1046,18 @@ class TaskOrchestrator {
970
1046
  });
971
1047
  }
972
1048
  }
973
- if (!streamOutput && !shouldPrefix) {
974
- // TODO: shouldn't this be checking if the task is continuous before writing anything to disk or calling printTaskTerminalOutput?
975
- runningTask.onExit((code, terminalOutput) => {
1049
+ runningTask.onExit((code, terminalOutput) => {
1050
+ if (!streamOutput && !shouldPrefix) {
976
1051
  this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
1052
+ }
1053
+ // A continuous task never reaches postRunSteps, so exiting is its
1054
+ // only chance to leave its output on disk. A discrete one is written
1055
+ // there instead, whatever its output style — writing here too would
1056
+ // just duplicate it.
1057
+ if (task.continuous) {
977
1058
  (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
978
- });
979
- }
1059
+ }
1060
+ });
980
1061
  return runningTask;
981
1062
  }
982
1063
  catch (e) {
@@ -988,6 +1069,7 @@ class TaskOrchestrator {
988
1069
  }
989
1070
  const terminalOutput = e.stack ?? e.message ?? '';
990
1071
  (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
1072
+ this.tasksWithPersistedOutput.add(task.id);
991
1073
  return new noop_child_process_1.NoopChildProcess({
992
1074
  code: 1,
993
1075
  terminalOutput,
@@ -996,6 +1078,7 @@ class TaskOrchestrator {
996
1078
  }
997
1079
  else if (targetConfiguration.executor === 'nx:noop') {
998
1080
  (0, fs_1.writeFileSync)(temporaryOutputPath, '');
1081
+ this.tasksWithPersistedOutput.add(task.id);
999
1082
  return new noop_child_process_1.NoopChildProcess({
1000
1083
  code: 0,
1001
1084
  terminalOutput: '',
@@ -1004,6 +1087,12 @@ class TaskOrchestrator {
1004
1087
  else {
1005
1088
  // cache prep
1006
1089
  const runningTask = await this.runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput);
1090
+ // Every forked path leaves the file behind whatever the output style:
1091
+ // the pseudo-terminal and prefixed processes write it when they exit,
1092
+ // the direct-output capture has the child write it itself, and the
1093
+ // fork-failure fallback writes the error. Continuous tasks depend on
1094
+ // that — they never reach postRunSteps.
1095
+ this.tasksWithPersistedOutput.add(task.id);
1007
1096
  if (this.tuiEnabled) {
1008
1097
  if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
1009
1098
  // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
@@ -1056,9 +1145,14 @@ class TaskOrchestrator {
1056
1145
  if (process.env.NX_VERBOSE_LOGGING === 'true') {
1057
1146
  console.error(e);
1058
1147
  }
1148
+ const terminalOutput = e.stack ?? e.message ?? '';
1149
+ // No process ever started, so nothing else will write the file. Record
1150
+ // why, so the task's terminal output path resolves to the fork error
1151
+ // rather than to nothing.
1152
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
1059
1153
  return new noop_child_process_1.NoopChildProcess({
1060
1154
  code: 1,
1061
- terminalOutput: e.stack ?? e.message ?? '',
1155
+ terminalOutput,
1062
1156
  });
1063
1157
  }
1064
1158
  }
@@ -1091,7 +1185,13 @@ class TaskOrchestrator {
1091
1185
  const pipeOutput = await this.pipeOutputCapture(task);
1092
1186
  // obtain metadata
1093
1187
  const temporaryOutputPath = this.cache.temporaryOutputPath(task);
1094
- const streamOutput = (0, output_1.isStaticOutputStyle)(this.outputStyle)
1188
+ // Deliberately not gated on `printsTaskOutput`, unlike `runTaskDirectly`.
1189
+ // `SummaryTerminalOutputLifeCycle.printTaskTerminalOutput` is a no-op and it
1190
+ // only reports at `endCommand`, which never runs for a task that does not
1191
+ // end - so suppressing here would leave a `nx serve` under `summary` with a
1192
+ // permanently silent terminal and no file to read yet. Streaming is the only
1193
+ // channel a continuous task has.
1194
+ const streamOutput = (0, output_1.isStaticOutputStyle)(this.specifiedOutputStyle)
1095
1195
  ? false
1096
1196
  : (0, utils_1.shouldStreamOutput)(task, this.initiatingProject);
1097
1197
  let env = pipeOutput
@@ -1108,6 +1208,9 @@ class TaskOrchestrator {
1108
1208
  this.continuousTaskExitHandled.set(task.id, new Promise((resolve) => {
1109
1209
  childProcess.onExit(async (code) => {
1110
1210
  await this.handleContinuousTaskExit(code, task, groupId, true);
1211
+ // Registered after the runner's own exit handler, which is what
1212
+ // wrote the file.
1213
+ this.recordContinuousTerminalOutput(task);
1111
1214
  resolve();
1112
1215
  });
1113
1216
  }));
@@ -1143,34 +1246,117 @@ class TaskOrchestrator {
1143
1246
  // Caller decides whether these results should be written to the cache.
1144
1247
  // Cache replays pass false so a replayed failure (reported as 'failure' so
1145
1248
  // it counts as a failed run) isn't re-written to the cache on every replay.
1146
- if (shouldCache && !this.stopRequested) {
1249
+ const resultsToCache = shouldCache && !this.stopRequested ? this.resultsToCache(results) : [];
1250
+ // Resolved before the cache writes so the two never write the same file.
1251
+ this.persistTerminalOutputs(results, resultsToCache);
1252
+ if (resultsToCache.length > 0) {
1147
1253
  // cache the results
1148
1254
  perf_hooks_1.performance.mark('cache-results-start');
1149
- await Promise.all(results
1150
- .filter(({ status }) => status !== 'local-cache' &&
1151
- status !== 'local-cache-kept-existing' &&
1152
- status !== 'remote-cache' &&
1153
- status !== 'skipped' &&
1154
- status !== 'stopped')
1155
- .map((result) => ({
1156
- ...result,
1157
- code: result.status === 'local-cache' ||
1158
- result.status === 'local-cache-kept-existing' ||
1159
- result.status === 'remote-cache' ||
1160
- result.status === 'success'
1161
- ? 0
1162
- : 1,
1163
- outputs: result.task.outputs,
1164
- }))
1165
- .filter(({ task, code }) => this.shouldCacheTaskResult(task, code))
1166
- .filter(({ terminalOutput, outputs }) => terminalOutput || outputs)
1167
- .map(async ({ task, code, terminalOutput, outputs }) => this.cache.put(task, terminalOutput, outputs, code)));
1255
+ await Promise.all(resultsToCache.map(async ({ task, code, terminalOutput, outputs }) => this.cache.put(task, terminalOutput, outputs, code)));
1168
1256
  perf_hooks_1.performance.mark('cache-results-end');
1169
1257
  perf_hooks_1.performance.measure('cache-results', 'cache-results-start', 'cache-results-end');
1170
1258
  }
1171
1259
  await this.complete(results, groupId);
1172
1260
  await this.scheduleNextTasksAndReleaseThreads();
1173
1261
  }
1262
+ /**
1263
+ * The results `cache.put` will write, in the shape it wants them. Pulled out
1264
+ * of postRunSteps so the terminal-output backstop can be told exactly which
1265
+ * tasks the cache is already writing a file for.
1266
+ */
1267
+ resultsToCache(results) {
1268
+ return results
1269
+ .filter(({ status }) => status !== 'local-cache' &&
1270
+ status !== 'local-cache-kept-existing' &&
1271
+ status !== 'remote-cache' &&
1272
+ status !== 'skipped' &&
1273
+ status !== 'stopped')
1274
+ .map((result) => ({
1275
+ ...result,
1276
+ code: result.status === 'local-cache' ||
1277
+ result.status === 'local-cache-kept-existing' ||
1278
+ result.status === 'remote-cache' ||
1279
+ result.status === 'success'
1280
+ ? 0
1281
+ : 1,
1282
+ outputs: result.task.outputs,
1283
+ }))
1284
+ .filter(({ task, code }) => this.shouldCacheTaskResult(task, code))
1285
+ .filter(({ terminalOutput, outputs }) => terminalOutput || outputs);
1286
+ }
1287
+ /**
1288
+ * Guarantee that every task that actually ran leaves its terminal output at
1289
+ * `<cacheDir>/terminalOutputs/<hash>`, whatever its cache setting, output
1290
+ * style, or batch membership. That path is what `--output-style=summary`
1291
+ * addresses each failure by, what the DB cache reads back on a hit
1292
+ * (`build_cached_result`), and what Nx Cloud falls back to reading when a
1293
+ * task's in-memory output is undefined, so a task that reaches a terminal
1294
+ * state without a file there is a dangling reference.
1295
+ *
1296
+ * Batch tasks are why this exists. Their output only ever arrives over IPC,
1297
+ * so the sole thing that ever put it on disk was `cache.put` — leaving a
1298
+ * `cache:false` batch task (the shape CI runs under `NX_BATCH_MODE`) with no
1299
+ * file at all.
1300
+ *
1301
+ * Written exactly once per task: tasks whose runner owns the file are
1302
+ * recorded in `tasksWithPersistedOutput`, and tasks `cache.put` is about to
1303
+ * write are skipped here. Cache hits are skipped by status — their output was
1304
+ * read from this very file — except a replayed cached *failure*, which comes
1305
+ * back as `failure` and is rewritten with the bytes it was just read with.
1306
+ * Skipped tasks never ran, so there is nothing to write.
1307
+ *
1308
+ * Every file written without a cache entry behind it is then registered with
1309
+ * the cache, because `removeOldCacheRecords` only collects hashes it finds in
1310
+ * the database — an unregistered file would never be cleaned up. That covers
1311
+ * files this method wrote AND ones a runner wrote, which are equally
1312
+ * invisible to the GC.
1313
+ */
1314
+ persistTerminalOutputs(results, resultsToCache) {
1315
+ const writtenByCache = new Set(resultsToCache.map(({ task }) => task.id));
1316
+ const toRecord = [];
1317
+ for (const { task, status, terminalOutput } of results) {
1318
+ if (terminalOutput === undefined ||
1319
+ // A task that failed before it was hashed has no path to write to.
1320
+ !task.hash ||
1321
+ status === 'skipped' ||
1322
+ status === 'local-cache' ||
1323
+ status === 'local-cache-kept-existing' ||
1324
+ status === 'remote-cache' ||
1325
+ // `cache.put` writes the file and records the hash itself.
1326
+ writtenByCache.has(task.id)) {
1327
+ continue;
1328
+ }
1329
+ if (!this.tasksWithPersistedOutput.has(task.id)) {
1330
+ this.tasksWithPersistedOutput.add(task.id);
1331
+ (0, fs_1.writeFileSync)(this.cache.temporaryOutputPath(task), terminalOutput);
1332
+ }
1333
+ toRecord.push({
1334
+ hash: task.hash,
1335
+ size: Buffer.byteLength(terminalOutput),
1336
+ });
1337
+ }
1338
+ if (toRecord.length > 0) {
1339
+ this.cache.recordTerminalOutputs(toRecord);
1340
+ }
1341
+ }
1342
+ /**
1343
+ * Register a continuous task's terminal output with the cache so the GC can
1344
+ * collect it. Continuous tasks never reach postRunSteps — their file is
1345
+ * written by whichever runner ran them, as the process exits — so this is
1346
+ * the only place their hash gets recorded. Read off disk rather than from a
1347
+ * result, because a continuous task completes without one.
1348
+ */
1349
+ recordContinuousTerminalOutput(task) {
1350
+ if (!task.hash)
1351
+ return;
1352
+ try {
1353
+ const { size } = (0, fs_1.statSync)(this.cache.temporaryOutputPath(task));
1354
+ this.cache.recordTerminalOutputs([{ hash: task.hash, size }]);
1355
+ }
1356
+ catch {
1357
+ // Exit handler: a throw here would be an unhandled rejection.
1358
+ }
1359
+ }
1174
1360
  async scheduleNextTasksAndReleaseThreads() {
1175
1361
  if (this.stopRequested) {
1176
1362
  this.waitingForTasks.forEach((f) => f(null));
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where a task's terminal output lives on disk, for callers that have a hash but
3
+ * no cache instance. Mirrors the native layout (`get_task_outputs_path_internal`
4
+ * in cache.rs) and the legacy cache's `terminalOutputsDir`; both resolve
5
+ * `<cacheDir>/terminalOutputs/<hash>`.
6
+ *
7
+ * Its own module rather than part of `cache.ts` so the graph and plugin paths
8
+ * can resolve a path without pulling the cache — and the database, cloud and
9
+ * task-IO modules behind it — into their import graph.
10
+ */
11
+ export declare function terminalOutputPathForHash(hash: string): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.terminalOutputPathForHash = terminalOutputPathForHash;
4
+ const path_1 = require("path");
5
+ const cache_directory_1 = require("../utils/cache-directory");
6
+ /**
7
+ * Where a task's terminal output lives on disk, for callers that have a hash but
8
+ * no cache instance. Mirrors the native layout (`get_task_outputs_path_internal`
9
+ * in cache.rs) and the legacy cache's `terminalOutputsDir`; both resolve
10
+ * `<cacheDir>/terminalOutputs/<hash>`.
11
+ *
12
+ * Its own module rather than part of `cache.ts` so the graph and plugin paths
13
+ * can resolve a path without pulling the cache — and the database, cloud and
14
+ * task-IO modules behind it — into their import graph.
15
+ */
16
+ function terminalOutputPathForHash(hash) {
17
+ return (0, path_1.join)(cache_directory_1.cacheDir, 'terminalOutputs', hash);
18
+ }
@@ -221,7 +221,10 @@ function getOutputsForTargetAndConfiguration(taskTargetOrTask, overridesOrNode,
221
221
  validateOutputs(targetConfiguration.outputs);
222
222
  const result = new Set();
223
223
  for (const output of targetConfiguration.outputs) {
224
- const interpolatedOutput = interpolate(output, {
224
+ // A leading `!` is negation, not part of the path: strip it so
225
+ // `{workspaceRoot}` still sits where interpolate requires it.
226
+ const isNegated = output.startsWith('!');
227
+ const interpolatedOutput = interpolate(isNegated ? output.substring(1) : output, {
225
228
  projectRoot: node.data.root,
226
229
  projectName: node.name,
227
230
  project: { ...node.data, name: node.name }, // this is legacy
@@ -229,7 +232,7 @@ function getOutputsForTargetAndConfiguration(taskTargetOrTask, overridesOrNode,
229
232
  });
230
233
  if (!!interpolatedOutput &&
231
234
  !interpolatedOutput.match(/{(projectRoot|workspaceRoot|(options.*))}/)) {
232
- result.add(interpolatedOutput);
235
+ result.add(isNegated ? `!${interpolatedOutput}` : interpolatedOutput);
233
236
  }
234
237
  }
235
238
  return Array.from(result);
@@ -1,4 +1,5 @@
1
1
  export declare const NX_CLOUD_URL = "https://nx.dev/nx-cloud";
2
+ export declare const NX_CLOUD_DEMO_URL = "https://cloud.nx.app/demo/intro";
2
3
  /**
3
4
  * Clickable Nx Cloud marketing link for cloud prompt footers. The visible text
4
5
  * stays the clean `NX_CLOUD_URL` while clicks carry UTM attribution; terminals
@@ -7,6 +8,8 @@ export declare const NX_CLOUD_URL = "https://nx.dev/nx-cloud";
7
8
  * different commands.
8
9
  */
9
10
  export declare function nxCloudHyperlink(utmContent: string): string;
11
+ /** Same as `nxCloudHyperlink`, pointing at the Nx Cloud demo (CLOUD-4640). */
12
+ export declare function nxCloudDemoHyperlink(utmContent: string): string;
10
13
  /**
11
14
  * Meta payload types for recordStat telemetry (matches CNW format).
12
15
  */
@@ -25,7 +28,7 @@ export interface RecordStatMetaError {
25
28
  [key: string]: string | boolean;
26
29
  }
27
30
  export type RecordStatMeta = RecordStatMetaStart | RecordStatMetaComplete | RecordStatMetaError;
28
- export type MessageOptionKey = 'yes' | 'skip' | 'never';
31
+ export type MessageOptionKey = 'yes' | 'skip';
29
32
  interface MessageData {
30
33
  code: string;
31
34
  message: string;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.messages = exports.PromptMessages = exports.NX_CLOUD_URL = void 0;
3
+ exports.messages = exports.PromptMessages = exports.NX_CLOUD_DEMO_URL = exports.NX_CLOUD_URL = void 0;
4
4
  exports.nxCloudHyperlink = nxCloudHyperlink;
5
+ exports.nxCloudDemoHyperlink = nxCloudDemoHyperlink;
5
6
  exports.recordStat = recordStat;
6
- const tslib_1 = require("tslib");
7
7
  const node_child_process_1 = require("node:child_process");
8
8
  const is_ci_1 = require("./is-ci");
9
9
  const package_manager_1 = require("./package-manager");
10
10
  const get_cloud_options_1 = require("../nx-cloud/utilities/get-cloud-options");
11
11
  const terminal_link_1 = require("./terminal-link");
12
- const pc = tslib_1.__importStar(require("picocolors"));
13
12
  exports.NX_CLOUD_URL = 'https://nx.dev/nx-cloud';
13
+ exports.NX_CLOUD_DEMO_URL = 'https://cloud.nx.app/demo/intro';
14
14
  /**
15
15
  * Clickable Nx Cloud marketing link for cloud prompt footers. The visible text
16
16
  * stays the clean `NX_CLOUD_URL` while clicks carry UTM attribution; terminals
@@ -19,8 +19,14 @@ exports.NX_CLOUD_URL = 'https://nx.dev/nx-cloud';
19
19
  * different commands.
20
20
  */
21
21
  function nxCloudHyperlink(utmContent) {
22
- const tracked = `${exports.NX_CLOUD_URL}?utm_source=nx-cli&utm_medium=cli&utm_campaign=nx-cloud-connect&utm_content=${utmContent}`;
23
- return (0, terminal_link_1.terminalLink)(exports.NX_CLOUD_URL, tracked);
22
+ return trackedHyperlink(exports.NX_CLOUD_URL, utmContent);
23
+ }
24
+ /** Same as `nxCloudHyperlink`, pointing at the Nx Cloud demo (CLOUD-4640). */
25
+ function nxCloudDemoHyperlink(utmContent) {
26
+ return trackedHyperlink(exports.NX_CLOUD_DEMO_URL, utmContent);
27
+ }
28
+ function trackedHyperlink(url, utmContent) {
29
+ return (0, terminal_link_1.terminalLink)(url, `${url}?utm_source=nx-cli&utm_medium=cli&utm_campaign=nx-cloud-connect&utm_content=${utmContent}`);
24
30
  }
25
31
  const messageOptions = {
26
32
  setupNxCloud: [
@@ -31,7 +37,6 @@ const messageOptions = {
31
37
  choices: [
32
38
  { value: 'yes', name: 'Yes' },
33
39
  { value: 'skip', name: 'Skip for now' },
34
- { value: 'never', name: pc.dim("No, don't ask again") },
35
40
  ],
36
41
  footer: '\nFree for small teams. Remote caching and task distribution. 2-minute setup:',
37
42
  },
@@ -42,7 +47,6 @@ const messageOptions = {
42
47
  choices: [
43
48
  { value: 'yes', name: 'Yes' },
44
49
  { value: 'skip', name: 'Skip for now' },
45
- { value: 'never', name: pc.dim("No, don't ask again") },
46
50
  ],
47
51
  footer: '\nLearn about it at',
48
52
  hint: `\n(it's free and can be disabled any time)`,
@@ -1,10 +1,4 @@
1
- export declare function chunkify(target: string[], maxChunkLength?: number,
2
- /**
3
- * How long each entry will be once it reaches the command line. Callers that
4
- * quote or escape afterwards pass that transformation's length here, so the
5
- * chunk is sized against what is actually spawned rather than the raw string.
6
- */
7
- measure?: (item: string) => number): string[][];
1
+ export declare function chunkify(target: string[], maxChunkLength?: number): string[][];
8
2
  /**
9
3
  * Get the maximum length of a command-line argument string based on current platform
10
4
  *
@@ -3,18 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chunkify = chunkify;
4
4
  exports.getMaxArgLength = getMaxArgLength;
5
5
  const TERMINAL_SIZE = getMaxArgLength();
6
- function chunkify(target, maxChunkLength = TERMINAL_SIZE - 500,
7
- /**
8
- * How long each entry will be once it reaches the command line. Callers that
9
- * quote or escape afterwards pass that transformation's length here, so the
10
- * chunk is sized against what is actually spawned rather than the raw string.
11
- */
12
- measure = (item) => item.length) {
6
+ function chunkify(target, maxChunkLength = TERMINAL_SIZE - 500) {
13
7
  const chunks = [];
14
8
  let currentChunk = [];
15
9
  let currentChunkLength = 0;
16
10
  for (const file of target) {
17
- const length = measure(file);
11
+ const length = file.length;
18
12
  if (
19
13
  // Prevent empty chunk if first file path is longer than maxChunkLength
20
14
  currentChunk.length &&
@@ -1,6 +1,7 @@
1
1
  import type { Arguments } from 'yargs';
2
2
  import { NxJsonConfiguration } from '../config/nx-json';
3
3
  import { ProjectGraph } from '../config/project-graph';
4
+ import type { OutputStyle } from '../command-line/yargs-utils/shared-options';
4
5
  export interface RawNxArgs extends NxArgs {
5
6
  prod?: boolean;
6
7
  }
@@ -28,6 +29,24 @@ export interface NxArgs {
28
29
  graph?: string | boolean;
29
30
  skipNxCache?: boolean;
30
31
  skipRemoteCache?: boolean;
32
+ /**
33
+ * The style the user named - CLI flag or `NX_DEFAULT_OUTPUT_STYLE`. Left
34
+ * undefined when they named none, and that absence is load-bearing: it is how
35
+ * the streaming and renderer-selection decisions tell "the user wants static"
36
+ * from "we defaulted to static", which stream continuous tasks differently.
37
+ */
38
+ specifiedOutputStyle?: OutputStyle;
39
+ /**
40
+ * What the run actually renders with, after the TUI, agent and failures-only
41
+ * defaults are applied. Always set. Every decision about what to PRINT reads
42
+ * this; every decision about what the user ASKED FOR reads the field above.
43
+ */
44
+ resolvedOutputStyle?: OutputStyle;
45
+ /**
46
+ * @deprecated Read `specifiedOutputStyle` for what the user named, or
47
+ * `resolvedOutputStyle` for what the run renders with. This will be removed
48
+ * in Nx 24.
49
+ */
31
50
  outputStyle?: string;
32
51
  tui?: boolean;
33
52
  nxBail?: boolean;