@depup/nx 23.2.1-depup.7 → 23.3.0-depup.0

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 (350) hide show
  1. package/README.md +8 -19
  2. package/changes.json +10 -54
  3. package/dist/bin/init-local.js +7 -1
  4. package/dist/nx-cloud-internals.d.ts +1 -0
  5. package/dist/nx-cloud-internals.js +9 -0
  6. package/dist/plugins/package-json.js +1 -1
  7. package/dist/src/command-line/add/add.js +5 -1
  8. package/dist/src/command-line/affected/affected.js +70 -9
  9. package/dist/src/command-line/affected/command-object.js +1 -1
  10. package/dist/src/command-line/format/format.js +2 -18
  11. package/dist/src/command-line/graph/graph.d.ts +31 -0
  12. package/dist/src/command-line/graph/graph.js +113 -20
  13. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +0 -3
  14. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +0 -3
  15. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +0 -3
  16. package/dist/src/command-line/init/implementation/angular/index.js +0 -3
  17. package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +0 -3
  18. package/dist/src/command-line/init/implementation/format.js +2 -3
  19. package/dist/src/command-line/init/implementation/utils.d.ts +0 -1
  20. package/dist/src/command-line/init/implementation/utils.js +6 -9
  21. package/dist/src/command-line/init/init-v2.js +0 -3
  22. package/dist/src/command-line/migrate/agentic/capture-generator-output.d.ts +25 -0
  23. package/dist/src/command-line/migrate/agentic/capture-generator-output.js +121 -5
  24. package/dist/src/command-line/migrate/agentic/close-agent-session.d.ts +21 -0
  25. package/dist/src/command-line/migrate/agentic/close-agent-session.js +126 -0
  26. package/dist/src/command-line/migrate/agentic/definitions.d.ts +24 -0
  27. package/dist/src/command-line/migrate/agentic/definitions.js +79 -20
  28. package/dist/src/command-line/migrate/agentic/format-command.d.ts +14 -0
  29. package/dist/src/command-line/migrate/agentic/format-command.js +44 -0
  30. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +3 -3
  31. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +3 -3
  32. package/dist/src/command-line/migrate/agentic/handoff.d.ts +50 -17
  33. package/dist/src/command-line/migrate/agentic/handoff.js +166 -24
  34. package/dist/src/command-line/migrate/agentic/instruction-files.d.ts +23 -0
  35. package/dist/src/command-line/migrate/agentic/instruction-files.js +41 -0
  36. package/dist/src/command-line/migrate/agentic/master/invocations.d.ts +12 -0
  37. package/dist/src/command-line/migrate/agentic/master/invocations.js +54 -0
  38. package/dist/src/command-line/migrate/agentic/master/run-master-session.d.ts +16 -0
  39. package/dist/src/command-line/migrate/agentic/master/run-master-session.js +175 -0
  40. package/dist/src/command-line/migrate/agentic/master/spawn-master.d.ts +31 -0
  41. package/dist/src/command-line/migrate/agentic/master/spawn-master.js +222 -0
  42. package/dist/src/command-line/migrate/agentic/prompts/final-validation.d.ts +13 -0
  43. package/dist/src/command-line/migrate/agentic/prompts/final-validation.js +41 -0
  44. package/dist/src/command-line/migrate/agentic/prompts/fragments.d.ts +17 -0
  45. package/dist/src/command-line/migrate/agentic/prompts/fragments.js +90 -0
  46. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +4 -3
  47. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +25 -1
  48. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +57 -34
  49. package/dist/src/command-line/migrate/agentic/run-step.js +28 -4
  50. package/dist/src/command-line/migrate/agentic/runner.d.ts +3 -15
  51. package/dist/src/command-line/migrate/agentic/runner.js +57 -239
  52. package/dist/src/command-line/migrate/agentic/terminal-repair.d.ts +1 -0
  53. package/dist/src/command-line/migrate/agentic/terminal-repair.js +27 -0
  54. package/dist/src/command-line/migrate/agentic/types.d.ts +23 -8
  55. package/dist/src/command-line/migrate/agentic/types.js +10 -7
  56. package/dist/src/command-line/migrate/agentic/windows-cmd.d.ts +33 -0
  57. package/dist/src/command-line/migrate/agentic/windows-cmd.js +88 -0
  58. package/dist/src/command-line/migrate/command-object.d.ts +2 -0
  59. package/dist/src/command-line/migrate/command-object.js +11 -1
  60. package/dist/src/command-line/migrate/deferred-output.d.ts +44 -0
  61. package/dist/src/command-line/migrate/deferred-output.js +92 -0
  62. package/dist/src/command-line/migrate/execute-migration.d.ts +9 -3
  63. package/dist/src/command-line/migrate/execute-migration.js +53 -16
  64. package/dist/src/command-line/migrate/migrate-analytics.d.ts +34 -9
  65. package/dist/src/command-line/migrate/migrate-analytics.js +71 -10
  66. package/dist/src/command-line/migrate/migrate-commits.d.ts +5 -4
  67. package/dist/src/command-line/migrate/migrate-commits.js +16 -6
  68. package/dist/src/command-line/migrate/migrate-config.d.ts +5 -2
  69. package/dist/src/command-line/migrate/migrate-config.js +19 -11
  70. package/dist/src/command-line/migrate/migrate-output.d.ts +3 -7
  71. package/dist/src/command-line/migrate/migrate-output.js +3 -7
  72. package/dist/src/command-line/migrate/migrate.d.ts +3 -0
  73. package/dist/src/command-line/migrate/migrate.js +183 -46
  74. package/dist/src/command-line/migrate/resolve-package-version.js +2 -19
  75. package/dist/src/command-line/migrate/run/agent-output.d.ts +11 -0
  76. package/dist/src/command-line/migrate/run/agent-output.js +21 -2
  77. package/dist/src/command-line/migrate/run/agent-work-payload.d.ts +37 -0
  78. package/dist/src/command-line/migrate/run/agent-work-payload.js +156 -0
  79. package/dist/src/command-line/migrate/run/atomic-write.d.ts +8 -0
  80. package/dist/src/command-line/migrate/run/atomic-write.js +17 -0
  81. package/dist/src/command-line/migrate/run/broker.d.ts +150 -0
  82. package/dist/src/command-line/migrate/run/broker.js +568 -0
  83. package/dist/src/command-line/migrate/run/clean-retry.d.ts +12 -0
  84. package/dist/src/command-line/migrate/run/clean-retry.js +99 -0
  85. package/dist/src/command-line/migrate/run/existing-run-report.d.ts +55 -0
  86. package/dist/src/command-line/migrate/run/existing-run-report.js +227 -0
  87. package/dist/src/command-line/migrate/run/give-up.d.ts +41 -0
  88. package/dist/src/command-line/migrate/run/give-up.js +148 -0
  89. package/dist/src/command-line/migrate/run/index.d.ts +9 -6
  90. package/dist/src/command-line/migrate/run/index.js +21 -2
  91. package/dist/src/command-line/migrate/run/issues.d.ts +127 -0
  92. package/dist/src/command-line/migrate/run/issues.js +1121 -0
  93. package/dist/src/command-line/migrate/run/orchestrator.d.ts +59 -1
  94. package/dist/src/command-line/migrate/run/orchestrator.js +1529 -457
  95. package/dist/src/command-line/migrate/run/run-id.d.ts +0 -8
  96. package/dist/src/command-line/migrate/run/run-id.js +0 -30
  97. package/dist/src/command-line/migrate/run/run-state.d.ts +77 -17
  98. package/dist/src/command-line/migrate/run/run-state.js +263 -32
  99. package/dist/src/command-line/migrate/run/runbook.d.ts +18 -0
  100. package/dist/src/command-line/migrate/run/runbook.js +118 -0
  101. package/dist/src/command-line/migrate/run/state-lock.d.ts +33 -2
  102. package/dist/src/command-line/migrate/run/state-lock.js +128 -2
  103. package/dist/src/command-line/migrate/run/state-machine.d.ts +50 -1
  104. package/dist/src/command-line/migrate/run/state-machine.js +339 -26
  105. package/dist/src/command-line/migrate/run/util.d.ts +3 -1
  106. package/dist/src/command-line/migrate/run/util.js +24 -3
  107. package/dist/src/command-line/migrate/run/worker.js +290 -129
  108. package/dist/src/command-line/migrate/step-actions.d.ts +1 -1
  109. package/dist/src/command-line/migrate/step-actions.js +7 -1
  110. package/dist/src/command-line/migrate/text.d.ts +6 -0
  111. package/dist/src/command-line/migrate/text.js +25 -0
  112. package/dist/src/command-line/migrate/version-skew-guard.js +2 -0
  113. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +5 -11
  114. package/dist/src/command-line/release/publish.js +11 -8
  115. package/dist/src/command-line/release/utils/get-touched-projects-for-group.js +3 -3
  116. package/dist/src/command-line/release/utils/release-graph.js +1 -1
  117. package/dist/src/command-line/release/utils/remote-release-clients/github.js +5 -8
  118. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +3 -3
  119. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +4 -2
  120. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.js +37 -3
  121. package/dist/src/command-line/release/version/version-actions.d.ts +3 -0
  122. package/dist/src/command-line/reset/reset.js +10 -4
  123. package/dist/src/command-line/run/run-one.js +5 -1
  124. package/dist/src/command-line/run-many/run-many.js +6 -12
  125. package/dist/src/command-line/show/command-object.js +1 -1
  126. package/dist/src/command-line/show/projects.js +52 -1
  127. package/dist/src/command-line/yargs-utils/shared-options.d.ts +5 -1
  128. package/dist/src/command-line/yargs-utils/shared-options.js +38 -4
  129. package/dist/src/config/task-graph.d.ts +1 -1
  130. package/dist/src/config/workspace-json-project-json.d.ts +23 -1
  131. package/dist/src/core/graph/main.js +1 -1
  132. package/dist/src/core/graph/runtime.js +1 -1
  133. package/dist/src/core/graph/styles.js +1 -1
  134. package/dist/src/daemon/client/client.d.ts +14 -8
  135. package/dist/src/daemon/client/client.js +41 -12
  136. package/dist/src/daemon/message-types/get-plugin-capabilities.d.ts +5 -0
  137. package/dist/src/daemon/message-types/get-plugin-capabilities.js +11 -0
  138. package/dist/src/daemon/message-types/run-tasks-execution-hooks.d.ts +3 -2
  139. package/dist/src/daemon/message-types/select-affected-tasks.d.ts +21 -0
  140. package/dist/src/daemon/message-types/select-affected-tasks.js +11 -0
  141. package/dist/src/daemon/message-types/ultracache-configuration-version.d.ts +8 -0
  142. package/dist/src/daemon/message-types/ultracache-configuration-version.js +2 -0
  143. package/dist/src/daemon/server/dotenv-graph-changes.d.ts +1 -1
  144. package/dist/src/daemon/server/dotenv-graph-changes.js +2 -2
  145. package/dist/src/daemon/server/handle-get-plugin-capabilities.d.ts +2 -0
  146. package/dist/src/daemon/server/handle-get-plugin-capabilities.js +13 -0
  147. package/dist/src/daemon/server/handle-hash-tasks.d.ts +10 -2
  148. package/dist/src/daemon/server/handle-hash-tasks.js +18 -3
  149. package/dist/src/daemon/server/handle-select-affected-tasks.d.ts +3 -0
  150. package/dist/src/daemon/server/handle-select-affected-tasks.js +26 -0
  151. package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +3 -2
  152. package/dist/src/daemon/server/{handle-outputs-changes.d.ts → handle-watch-events.d.ts} +4 -4
  153. package/dist/src/daemon/server/{handle-outputs-changes.js → handle-watch-events.js} +36 -37
  154. package/dist/src/daemon/server/outputs-tracking.d.ts +7 -19
  155. package/dist/src/daemon/server/outputs-tracking.js +7 -107
  156. package/dist/src/daemon/server/planning-context.d.ts +8 -0
  157. package/dist/src/daemon/server/planning-context.js +18 -0
  158. package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +22 -7
  159. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +104 -74
  160. package/dist/src/daemon/server/restart-checks.d.ts +22 -0
  161. package/dist/src/daemon/server/restart-checks.js +77 -0
  162. package/dist/src/daemon/server/server.d.ts +1 -0
  163. package/dist/src/daemon/server/server.js +54 -30
  164. package/dist/src/daemon/server/shutdown-utils.d.ts +0 -5
  165. package/dist/src/daemon/server/shutdown-utils.js +3 -26
  166. package/dist/src/daemon/server/ultracache-configuration-state.d.ts +7 -0
  167. package/dist/src/daemon/server/ultracache-configuration-state.js +36 -0
  168. package/dist/src/devkit-internals.d.ts +3 -1
  169. package/dist/src/devkit-internals.js +8 -3
  170. package/dist/src/executors/run-commands/run-commands.impl.d.ts +2 -1
  171. package/dist/src/executors/run-commands/run-commands.impl.js +19 -5
  172. package/dist/src/executors/run-commands/running-tasks.d.ts +5 -4
  173. package/dist/src/executors/run-commands/running-tasks.js +13 -13
  174. package/dist/src/hasher/create-task-hasher.d.ts +8 -1
  175. package/dist/src/hasher/create-task-hasher.js +13 -3
  176. package/dist/src/hasher/hash-plan-inspector.js +2 -2
  177. package/dist/src/hasher/hash-task.d.ts +2 -2
  178. package/dist/src/hasher/hash-task.js +28 -17
  179. package/dist/src/hasher/native-task-hasher-impl.d.ts +20 -4
  180. package/dist/src/hasher/native-task-hasher-impl.js +75 -9
  181. package/dist/src/hasher/task-hasher.d.ts +24 -7
  182. package/dist/src/hasher/task-hasher.js +27 -8
  183. package/dist/src/hasher/task-planning-context.d.ts +13 -0
  184. package/dist/src/hasher/task-planning-context.js +12 -0
  185. package/dist/src/native/index.d.ts +582 -21
  186. package/dist/src/native/index.js +3 -3
  187. package/dist/src/native/native-bindings.js +13 -1
  188. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  189. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  190. package/dist/src/native/transform-objects.d.ts +11 -2
  191. package/dist/src/native/transform-objects.js +46 -0
  192. package/dist/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +15 -8
  193. package/dist/src/nx-cloud/update-manager.d.ts +3 -0
  194. package/dist/src/nx-cloud/update-manager.js +19 -13
  195. package/dist/src/nx-cloud/utilities/client.d.ts +1 -1
  196. package/dist/src/nx-cloud/utilities/client.js +1 -1
  197. package/dist/src/nx-cloud/utilities/is-workspace-claimed.js +2 -1
  198. package/dist/src/nx-cloud/utilities/nx-cloud-http-client.d.ts +5 -0
  199. package/dist/src/nx-cloud/utilities/nx-cloud-http-client.js +16 -0
  200. package/dist/src/nx-cloud/utilities/url-shorten.js +17 -10
  201. package/dist/src/plugins/js/index.js +45 -64
  202. package/dist/src/plugins/js/lock-file/lock-file.d.ts +4 -4
  203. package/dist/src/plugins/js/lock-file/lock-file.js +6 -7
  204. package/dist/src/plugins/js/lock-file/pnpm-parser.js +1 -1
  205. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.d.ts +2 -0
  206. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +22 -0
  207. package/dist/src/plugins/js/project-graph/affected/lock-file-changes.d.ts +10 -2
  208. package/dist/src/plugins/js/project-graph/affected/lock-file-changes.js +51 -29
  209. package/dist/src/plugins/js/project-graph/affected/npm-packages.d.ts +10 -2
  210. package/dist/src/plugins/js/project-graph/affected/npm-packages.js +32 -11
  211. package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +22 -18
  212. package/dist/src/plugins/js/utils/register.js +13 -4
  213. package/dist/src/plugins/package-json/create-nodes.d.ts +2 -2
  214. package/dist/src/plugins/package-json/create-nodes.js +13 -13
  215. package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +14 -0
  216. package/dist/src/project-graph/affected/affected-project-graph.js +5 -18
  217. package/dist/src/project-graph/affected/affected-projects.d.ts +7 -0
  218. package/dist/src/project-graph/affected/affected-projects.js +42 -0
  219. package/dist/src/project-graph/affected/affected-reasons.d.ts +116 -0
  220. package/dist/src/project-graph/affected/affected-reasons.js +459 -0
  221. package/dist/src/project-graph/affected/affected-tasks.d.ts +103 -0
  222. package/dist/src/project-graph/affected/affected-tasks.js +386 -0
  223. package/dist/src/project-graph/affected/print-explanation.d.ts +11 -0
  224. package/dist/src/project-graph/affected/print-explanation.js +44 -0
  225. package/dist/src/project-graph/error-types.d.ts +5 -0
  226. package/dist/src/project-graph/error-types.js +44 -5
  227. package/dist/src/project-graph/file-utils.d.ts +2 -0
  228. package/dist/src/project-graph/file-utils.js +12 -3
  229. package/dist/src/project-graph/nx-deps-cache.d.ts +5 -2
  230. package/dist/src/project-graph/nx-deps-cache.js +4 -4
  231. package/dist/src/project-graph/plugins/get-plugins.d.ts +3 -1
  232. package/dist/src/project-graph/plugins/get-plugins.js +60 -82
  233. package/dist/src/project-graph/plugins/in-process-loader.d.ts +1 -1
  234. package/dist/src/project-graph/plugins/in-process-loader.js +1 -4
  235. package/dist/src/project-graph/plugins/isolation/index.d.ts +1 -1
  236. package/dist/src/project-graph/plugins/isolation/index.js +3 -1
  237. package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +8 -0
  238. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +42 -6
  239. package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.d.ts +10 -1
  240. package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.js +67 -17
  241. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +3 -2
  242. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +5 -1
  243. package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +5 -2
  244. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +14 -1
  245. package/dist/src/project-graph/plugins/nx-plugin-capabilities.d.ts +6 -0
  246. package/dist/src/project-graph/plugins/nx-plugin-capabilities.js +28 -0
  247. package/dist/src/project-graph/plugins/task-results-stub.d.ts +50 -0
  248. package/dist/src/project-graph/plugins/task-results-stub.js +111 -0
  249. package/dist/src/project-graph/plugins/tasks-execution-hooks.d.ts +3 -2
  250. package/dist/src/project-graph/plugins/tasks-execution-hooks.js +14 -1
  251. package/dist/src/project-graph/project-graph.js +43 -42
  252. package/dist/src/project-graph/utils/project-configuration/target-merging.js +67 -0
  253. package/dist/src/project-graph/utils/project-configuration/target-normalization.js +83 -0
  254. package/dist/src/project-graph/utils/project-configuration/utils.d.ts +1 -0
  255. package/dist/src/project-graph/utils/project-configuration/utils.js +1 -0
  256. package/dist/src/tasks-runner/batch/run-batch.js +15 -0
  257. package/dist/src/tasks-runner/cache.d.ts +37 -2
  258. package/dist/src/tasks-runner/cache.js +42 -1
  259. package/dist/src/tasks-runner/create-task-graph.d.ts +24 -1
  260. package/dist/src/tasks-runner/create-task-graph.js +57 -2
  261. package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
  262. package/dist/src/tasks-runner/forked-process-task-runner.d.ts +1 -1
  263. package/dist/src/tasks-runner/forked-process-task-runner.js +11 -10
  264. package/dist/src/tasks-runner/init-tasks-runner.d.ts +7 -2
  265. package/dist/src/tasks-runner/init-tasks-runner.js +15 -7
  266. package/dist/src/tasks-runner/is-tui-enabled.js +4 -3
  267. package/dist/src/tasks-runner/life-cycle.d.ts +7 -0
  268. package/dist/src/tasks-runner/life-cycle.js +7 -0
  269. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.d.ts +35 -0
  270. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.js +146 -0
  271. package/dist/src/tasks-runner/prune-task-graph.d.ts +17 -0
  272. package/dist/src/tasks-runner/prune-task-graph.js +45 -0
  273. package/dist/src/tasks-runner/run-command.d.ts +41 -5
  274. package/dist/src/tasks-runner/run-command.js +98 -22
  275. package/dist/src/tasks-runner/running-tasks/batch-process.d.ts +93 -19
  276. package/dist/src/tasks-runner/running-tasks/batch-process.js +184 -88
  277. package/dist/src/tasks-runner/task-io-service.d.ts +11 -3
  278. package/dist/src/tasks-runner/task-io-service.js +14 -5
  279. package/dist/src/tasks-runner/task-orchestrator.d.ts +71 -4
  280. package/dist/src/tasks-runner/task-orchestrator.js +266 -66
  281. package/dist/src/tasks-runner/tasks-runner.d.ts +2 -0
  282. package/dist/src/tasks-runner/terminal-output-path.d.ts +11 -0
  283. package/dist/src/tasks-runner/terminal-output-path.js +18 -0
  284. package/dist/src/tasks-runner/utils.d.ts +5 -0
  285. package/dist/src/tasks-runner/utils.js +14 -2
  286. package/dist/src/ultracache/config.d.ts +21 -0
  287. package/dist/src/ultracache/config.js +29 -0
  288. package/dist/src/ultracache/fetch.d.ts +21 -0
  289. package/dist/src/ultracache/fetch.js +43 -0
  290. package/dist/src/ultracache/overrides.d.ts +17 -0
  291. package/dist/src/ultracache/overrides.js +61 -0
  292. package/dist/src/ultracache/report.d.ts +13 -0
  293. package/dist/src/ultracache/report.js +62 -0
  294. package/dist/src/ultracache/store.d.ts +41 -0
  295. package/dist/src/ultracache/store.js +158 -0
  296. package/dist/src/utils/ab-testing.d.ts +4 -1
  297. package/dist/src/utils/ab-testing.js +22 -19
  298. package/dist/src/utils/chunkify.d.ts +1 -7
  299. package/dist/src/utils/chunkify.js +2 -8
  300. package/dist/src/utils/command-line-utils.d.ts +20 -0
  301. package/dist/src/utils/command-line-utils.js +10 -3
  302. package/dist/src/utils/create-cli-options.d.ts +6 -0
  303. package/dist/src/utils/create-cli-options.js +29 -0
  304. package/dist/src/utils/db-connection.d.ts +2 -0
  305. package/dist/src/utils/db-connection.js +2 -0
  306. package/dist/src/utils/formatters/index.d.ts +6 -0
  307. package/dist/src/utils/formatters/index.js +5 -0
  308. package/dist/src/utils/formatters/prettier.d.ts +0 -8
  309. package/dist/src/utils/formatters/prettier.js +4 -26
  310. package/dist/src/utils/git-utils.d.ts +19 -0
  311. package/dist/src/utils/git-utils.js +97 -39
  312. package/dist/src/utils/handle-errors.js +5 -43
  313. package/dist/src/utils/http-client.d.ts +27 -0
  314. package/dist/src/utils/http-client.js +193 -0
  315. package/dist/src/utils/installed-nx-version.js +2 -48
  316. package/dist/src/utils/json-diff.d.ts +4 -2
  317. package/dist/src/utils/json-diff.js +6 -94
  318. package/dist/src/utils/min-release-age/packument.js +1 -1
  319. package/dist/src/utils/nx-cloud-utils.d.ts +2 -0
  320. package/dist/src/utils/nx-cloud-utils.js +6 -1
  321. package/dist/src/utils/output.d.ts +22 -3
  322. package/dist/src/utils/output.js +28 -5
  323. package/dist/src/utils/package-json.d.ts +25 -0
  324. package/dist/src/utils/package-json.js +49 -6
  325. package/dist/src/utils/package-manager.d.ts +6 -0
  326. package/dist/src/utils/package-manager.js +10 -0
  327. package/dist/src/utils/plugins/plugin-capabilities.js +7 -2
  328. package/dist/src/utils/project-graph-utils.d.ts +2 -0
  329. package/dist/src/utils/project-graph-utils.js +12 -0
  330. package/dist/src/utils/provenance.js +20 -4
  331. package/dist/src/utils/serialize-overrides-into-command-line.js +2 -4
  332. package/dist/src/utils/workspace-context.d.ts +51 -3
  333. package/dist/src/utils/workspace-context.js +174 -10
  334. package/package.json +38 -100
  335. package/schemas/nx-schema.json +38 -0
  336. package/schemas/project-schema.json +35 -0
  337. package/dist/src/daemon/server/file-watching/route-workspace-changes.d.ts +0 -9
  338. package/dist/src/daemon/server/file-watching/route-workspace-changes.js +0 -76
  339. package/dist/src/daemon/server/watcher.d.ts +0 -18
  340. package/dist/src/daemon/server/watcher.js +0 -126
  341. package/dist/src/nx-cloud/utilities/axios.d.ts +0 -4
  342. package/dist/src/nx-cloud/utilities/axios.js +0 -17
  343. package/dist/src/project-graph/affected/locators/project-glob-changes.d.ts +0 -2
  344. package/dist/src/project-graph/affected/locators/project-glob-changes.js +0 -47
  345. package/dist/src/project-graph/affected/locators/workspace-json-changes.d.ts +0 -4
  346. package/dist/src/project-graph/affected/locators/workspace-json-changes.js +0 -47
  347. package/dist/src/project-graph/affected/locators/workspace-projects.d.ts +0 -3
  348. package/dist/src/project-graph/affected/locators/workspace-projects.js +0 -74
  349. package/dist/src/utils/collapse-expanded-outputs.d.ts +0 -10
  350. package/dist/src/utils/collapse-expanded-outputs.js +0 -72
@@ -12,7 +12,6 @@ const project_graph_1 = require("../project-graph/project-graph");
12
12
  const run_commands_impl_1 = require("../executors/run-commands/run-commands.impl");
13
13
  const hash_task_1 = require("../hasher/hash-task");
14
14
  const task_graph_utils_1 = require("./task-graph-utils");
15
- const task_hasher_1 = require("../hasher/task-hasher");
16
15
  const native_1 = require("../native");
17
16
  const db_connection_1 = require("../utils/db-connection");
18
17
  const exit_codes_1 = require("../utils/exit-codes");
@@ -37,9 +36,24 @@ const utils_1 = require("./utils");
37
36
  function resolveBatchTaskStatus(result) {
38
37
  return result.status ?? (result.success ? 'success' : 'failure');
39
38
  }
39
+ /** Whether a path names a file with bytes in it. */
40
+ function hasContent(path) {
41
+ try {
42
+ return (0, fs_1.statSync)(path).size > 0;
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
40
48
  class TaskOrchestrator {
41
49
  // endregion internal state
42
- constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, fullTaskGraph = taskGraph) {
50
+ constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon,
51
+ /** What the user named; undefined means they named nothing. */
52
+ specifiedOutputStyle,
53
+ /** What this run renders with, after defaults. */
54
+ resolvedOutputStyle, fullTaskGraph = taskGraph,
55
+ /** Tasks the up-front pass left to hash once the tasks they read from have run. */
56
+ deferredTaskIds) {
43
57
  this.hasher = hasher;
44
58
  this.initiatingProject = initiatingProject;
45
59
  this.initiatingTasks = initiatingTasks;
@@ -49,8 +63,10 @@ class TaskOrchestrator {
49
63
  this.options = options;
50
64
  this.bail = bail;
51
65
  this.daemon = daemon;
52
- this.outputStyle = outputStyle;
66
+ this.specifiedOutputStyle = specifiedOutputStyle;
67
+ this.resolvedOutputStyle = resolvedOutputStyle;
53
68
  this.fullTaskGraph = fullTaskGraph;
69
+ this.deferredTaskIds = deferredTaskIds;
54
70
  this.taskDetails = (0, hash_task_1.getTaskDetails)();
55
71
  this.cache = (0, cache_1.getCache)(this.options);
56
72
  this.tuiEnabled = (0, is_tui_enabled_1.isTuiEnabled)();
@@ -85,6 +101,9 @@ class TaskOrchestrator {
85
101
  // miss waiting for a worker slot is re-queried (including the remote
86
102
  // retrieval) on every coordinator cycle.
87
103
  this.cacheMissedHashes = new Set();
104
+ // The files the cache just wrote or restored, by task id, for postRunSteps
105
+ // to hand the daemon instead of it walking the outputs again.
106
+ this.copiedOutputFiles = new Map();
88
107
  this.completedTasks = new Map();
89
108
  this.waitingForTasks = [];
90
109
  this.pendingDiscreteWorkers = new Set();
@@ -106,6 +125,13 @@ class TaskOrchestrator {
106
125
  this.continuousTaskExitHandled = new Map();
107
126
  this.cleanupPromise = null;
108
127
  this.signalHandlers = [];
128
+ // Tasks whose runner already owns the write to
129
+ // `<cacheDir>/terminalOutputs/<hash>` — forked processes write it as they
130
+ // exit, and the paths that never spawn one write it inline. The backstop in
131
+ // postRunSteps consults this so a task's output is written exactly once.
132
+ this.tasksWithPersistedOutput = new Set();
133
+ /** Batches whose worker log was handed to the life cycle, so it must survive. */
134
+ this.announcedBatchLogs = new Set();
109
135
  }
110
136
  async init() {
111
137
  this.setupSignalHandlers();
@@ -158,6 +184,10 @@ class TaskOrchestrator {
158
184
  perf_hooks_1.performance.measure('task-execution', 'task-execution:start', 'task-execution:end');
159
185
  if (!this.stopRequested) {
160
186
  this.cache.removeOldCacheRecords();
187
+ // Free function, not a cache method: `BatchProcess` writes these logs
188
+ // whichever cache implementation is active. It no-ops under WASM, where
189
+ // the native half does not exist.
190
+ (0, cache_1.sweepBatchOutputs)();
161
191
  }
162
192
  await this.cleanup();
163
193
  await this.dispose();
@@ -377,7 +407,9 @@ class TaskOrchestrator {
377
407
  // Copy outputs in parallel for tasks that need it.
378
408
  await Promise.all(cacheHits.map(async ({ task, cachedResult }) => {
379
409
  if (shouldCopyMap.get(task.hash)) {
380
- await this.cache.copyFilesFromCache(task.hash, cachedResult, task.outputs);
410
+ const files = await this.cache.copyFilesFromCache(task.hash, cachedResult, task.outputs);
411
+ if (files)
412
+ this.copiedOutputFiles.set(task.id, files);
381
413
  }
382
414
  }));
383
415
  // Derive status, print terminal output, build results.
@@ -452,8 +484,8 @@ class TaskOrchestrator {
452
484
  * Hash all batch tasks and resolve cache hits topologically.
453
485
  *
454
486
  * Walks the task graph level by level. Every task gets a preliminary hash
455
- * (so startTasks always has a valid hash for Cloud). Tasks with depsOutputs
456
- * whose deps weren't cached are ineligible for cache lookup but still
487
+ * (so startTasks always has a valid hash for Cloud). Tasks the up-front
488
+ * pass deferred, whose deps weren't cached, are ineligible for cache lookup but still
457
489
  * receive a preliminary hash — they'll be re-hashed after execution.
458
490
  */
459
491
  async applyBatchCachedResults(batch, doNotSkipCache, groupId) {
@@ -473,8 +505,7 @@ class TaskOrchestrator {
473
505
  for (const task of rootTasks) {
474
506
  const depIds = batch.taskGraph.dependencies[task.id];
475
507
  const hasNonCachedDep = depIds.some((id) => nonCachedTaskIds.has(id));
476
- if (hasNonCachedDep &&
477
- (0, task_hasher_1.getInputs)(task, this.projectGraph, this.nxJson).depsOutputs.length > 0) {
508
+ if (hasNonCachedDep && this.deferredTaskIds?.has(task.id)) {
478
509
  nonCachedTaskIds.add(task.id);
479
510
  needsRehashAfterExecution.add(task.id);
480
511
  }
@@ -530,7 +561,7 @@ class TaskOrchestrator {
530
561
  await Promise.all(nonCachedTasks.map((task) => this.options.lifeCycle.scheduleTask(task)));
531
562
  await this.preRunSteps(nonCachedTasks, { groupId });
532
563
  }
533
- // Phase 2: Run non-cached tasks, then re-hash depsOutputs tasks
564
+ // Phase 2: Run non-cached tasks, then re-hash tasks that read their outputs
534
565
  const taskIdsToSkip = cachedResults.map((r) => r.task.id);
535
566
  let batchResults = [];
536
567
  if (taskIdsToSkip.length < tasks.length) {
@@ -543,7 +574,7 @@ class TaskOrchestrator {
543
574
  executorName: batch.executorName,
544
575
  taskGraph: runGraph,
545
576
  }, this.batchEnv, groupId);
546
- // Re-hash depsOutputs tasks — their dep outputs are now on disk
577
+ // Re-hash tasks that read dep outputs — those outputs are now on disk
547
578
  const tasksToRehash = batchResults
548
579
  .filter((r) => needsRehashAfterExecution.has(r.task.id) &&
549
580
  (r.status === 'success' || r.status === 'failure'))
@@ -586,7 +617,7 @@ class TaskOrchestrator {
586
617
  const runBatchStart = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:start');
587
618
  let batchProcess;
588
619
  try {
589
- batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.fullTaskGraph, env);
620
+ batchProcess = await this.forkedProcessTaskRunner.forkProcessForBatch(batch, this.projectGraph, this.fullTaskGraph, env, (0, output_1.printsTaskOutput)(this.resolvedOutputStyle));
590
621
  // Stream output from batch process to the batch
591
622
  batchProcess.onOutput((output) => {
592
623
  this.options.lifeCycle.appendBatchOutput?.(batch.id, output);
@@ -633,9 +664,13 @@ class TaskOrchestrator {
633
664
  terminalOutput: result.terminalOutput,
634
665
  };
635
666
  });
667
+ // The capture stream buffers, so both readers below would otherwise be
668
+ // racing bytes that have not reached the file yet.
669
+ await batchProcess.flushCapturedOutput();
636
670
  if ((0, output_1.shouldGroupBatchOutput)()) {
637
671
  this.renderBatchOutputSafely(batch.id, () => this.printGroupedBatchOutput(batch, taskResults, batchProcess.getCapturedOutputPath()));
638
672
  }
673
+ this.announceBatchWorkerLog(batch.id, taskResults, batchProcess.getCapturedOutputPath());
639
674
  return taskResults;
640
675
  }
641
676
  catch (e) {
@@ -652,15 +687,19 @@ class TaskOrchestrator {
652
687
  terminalOutput: isBatchStopping ? '' : (e.stack ?? e.message ?? ''),
653
688
  };
654
689
  });
690
+ await batchProcess?.flushCapturedOutput();
691
+ this.announceBatchWorkerLog(batch.id, taskResults, batchProcess?.getCapturedOutputPath());
655
692
  // The worker died without reporting results, so nothing was attributed to
656
693
  // 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)()) {
694
+ // stdout/stderr, held back under grouping - surface it as one fold. Under
695
+ // a style that prints nothing there is no fold; the log is announced by
696
+ // path above instead. Outside both, it already streamed live. This
697
+ // matters just as much when the batch was stopped: every task
698
+ // is marked stopped whether or not it finished, so the log is the only
699
+ // record of what got through. Only the exit-code error is dropped there,
700
+ // since it restates the cancellation.
701
+ if ((0, output_1.shouldGroupBatchOutput)() &&
702
+ (0, output_1.printsTaskOutput)(this.resolvedOutputStyle)) {
664
703
  const capturedOutputPath = batchProcess?.getCapturedOutputPath();
665
704
  const trailer = isBatchStopping ? undefined : e.message;
666
705
  if (capturedOutputPath || trailer) {
@@ -673,11 +712,42 @@ class TaskOrchestrator {
673
712
  return taskResults;
674
713
  }
675
714
  finally {
676
- batchProcess?.discardCapturedOutput();
715
+ // Kept only when something failed and the log was announced; an all-green
716
+ // batch's chatter explains nothing and would sit in `batchOutputs/` until
717
+ // the sweep.
718
+ if (!this.announcedBatchLogs.has(batch.id)) {
719
+ batchProcess?.discardCapturedOutput();
720
+ }
677
721
  const runBatchEnd = perf_hooks_1.performance.mark('TaskOrchestrator-run-batch:end');
678
722
  perf_hooks_1.performance.measure('TaskOrchestrator-run-batch', runBatchStart.name, runBatchEnd.name);
679
723
  }
680
724
  }
725
+ /**
726
+ * Tells the life cycle where the batch worker's own log is, when something
727
+ * failed and a style that prints nothing would otherwise leave it unread.
728
+ *
729
+ * The path is announced rather than the bytes copied into a task: one worker
730
+ * produces one log, it explains the batch rather than any single task, and a
731
+ * task's own output file is read back verbatim on a cache hit.
732
+ */
733
+ announceBatchWorkerLog(batchId, results, capturedOutputPath) {
734
+ if (!capturedOutputPath || (0, output_1.printsTaskOutput)(this.resolvedOutputStyle)) {
735
+ return;
736
+ }
737
+ const failed = results.some((r) => r.status === 'failure' || r.status === 'stopped');
738
+ if (!failed) {
739
+ return;
740
+ }
741
+ // The path is minted when the file is opened, before any byte reaches it,
742
+ // so a capture that failed on its first write leaves one that exists and is
743
+ // empty. Announcing that offers the reader an address holding nothing.
744
+ // Checked after the flush, so the size is what a reader will actually see.
745
+ if (!hasContent(capturedOutputPath)) {
746
+ return;
747
+ }
748
+ this.announcedBatchLogs.add(batchId);
749
+ this.options.lifeCycle.batchOutputAvailable?.(batchId, capturedOutputPath);
750
+ }
681
751
  /**
682
752
  * Rendering a batch's output must never change the batch's results. A throw
683
753
  * from the printer would otherwise land in `runBatch`'s own error handling:
@@ -741,17 +811,20 @@ class TaskOrchestrator {
741
811
  * A batch that never reported results is handled by the caller instead.
742
812
  */
743
813
  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.
814
+ // Reads `resolvedOutputStyle` - what the run actually renders with. The
815
+ // streaming decision deliberately reads `specifiedOutputStyle` instead,
816
+ // since it has to tell a named style from an inferred default. `this.options`
817
+ // has its own `outputStyle`, merged from `nx.json`'s tasksRunnerOptions, so
818
+ // the two disagree whenever a style is configured there but not named on the
819
+ // command line.
749
820
  const printsFullOutput = (0, output_1.printsFullTaskOutput)({
750
821
  verbose: this.options.verbose,
751
- outputStyle: this.outputStyle,
822
+ outputStyle: this.resolvedOutputStyle,
752
823
  });
753
824
  const batchOwnsTheDiagnostic = taskResults.some((r) => r.status === 'failure' || r.status === 'stopped');
754
- if ((printsFullOutput || batchOwnsTheDiagnostic) && capturedOutputPath) {
825
+ if ((0, output_1.printsTaskOutput)(this.resolvedOutputStyle) &&
826
+ (printsFullOutput || batchOwnsTheDiagnostic) &&
827
+ capturedOutputPath) {
755
828
  // No redirect lines: every task renders itself below, so there is nothing
756
829
  // to redirect anyone to.
757
830
  this.printBatchFold(batch, taskResults, { capturedOutputPath }, { redirectLines: false });
@@ -866,6 +939,10 @@ class TaskOrchestrator {
866
939
  if (this.completedTasks.has(task.id))
867
940
  return;
868
941
  const terminalOutput = e?.message ?? '';
942
+ // The worker rejected, so whatever the runner was going to leave on disk
943
+ // either never landed or can't be trusted. Hand the file back to
944
+ // postRunSteps so the failure itself is what the task's output path holds.
945
+ this.tasksWithPersistedOutput.delete(task.id);
869
946
  this.options.lifeCycle.printTaskTerminalOutput(task, 'failure', terminalOutput);
870
947
  await this.postRunSteps([{ task, status: 'failure', terminalOutput }], doNotSkipCache, groupId);
871
948
  }
@@ -880,7 +957,12 @@ class TaskOrchestrator {
880
957
  await this.preRunSteps([task], { groupId });
881
958
  const pipeOutput = await this.pipeOutputCapture(task);
882
959
  const temporaryOutputPath = this.cache.temporaryOutputPath(task);
883
- const streamOutput = (0, output_1.isStaticOutputStyle)(this.outputStyle)
960
+ // `summary` prints log paths rather than logs, and `shouldStreamOutput`
961
+ // would otherwise stream the initiating project's output in full - the one
962
+ // task a run-one is most likely to have. Continuous tasks are deliberately
963
+ // NOT suppressed the same way; see `startContinuousTask`.
964
+ const streamOutput = (0, output_1.isStaticOutputStyle)(this.specifiedOutputStyle) ||
965
+ !(0, output_1.printsTaskOutput)(this.resolvedOutputStyle)
884
966
  ? false
885
967
  : (0, utils_1.shouldStreamOutput)(task, this.initiatingProject);
886
968
  const env = pipeOutput
@@ -943,7 +1025,7 @@ class TaskOrchestrator {
943
1025
  };
944
1026
  const runningTask = await (0, run_commands_impl_1.runCommands)(runCommandsOptions, {
945
1027
  root: workspace_root_1.workspaceRoot, // only root is needed in runCommands
946
- }, task.id);
1028
+ }, task);
947
1029
  this.runningRunCommandsTasks.set(task.id, runningTask);
948
1030
  runningTask.onExit(() => {
949
1031
  this.runningRunCommandsTasks.delete(task.id);
@@ -970,13 +1052,18 @@ class TaskOrchestrator {
970
1052
  });
971
1053
  }
972
1054
  }
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) => {
1055
+ runningTask.onExit((code, terminalOutput) => {
1056
+ if (!streamOutput && !shouldPrefix) {
976
1057
  this.options.lifeCycle.printTaskTerminalOutput(task, code === 0 ? 'success' : 'failure', terminalOutput);
1058
+ }
1059
+ // A continuous task never reaches postRunSteps, so exiting is its
1060
+ // only chance to leave its output on disk. A discrete one is written
1061
+ // there instead, whatever its output style — writing here too would
1062
+ // just duplicate it.
1063
+ if (task.continuous) {
977
1064
  (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
978
- });
979
- }
1065
+ }
1066
+ });
980
1067
  return runningTask;
981
1068
  }
982
1069
  catch (e) {
@@ -988,6 +1075,7 @@ class TaskOrchestrator {
988
1075
  }
989
1076
  const terminalOutput = e.stack ?? e.message ?? '';
990
1077
  (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
1078
+ this.tasksWithPersistedOutput.add(task.id);
991
1079
  return new noop_child_process_1.NoopChildProcess({
992
1080
  code: 1,
993
1081
  terminalOutput,
@@ -996,6 +1084,7 @@ class TaskOrchestrator {
996
1084
  }
997
1085
  else if (targetConfiguration.executor === 'nx:noop') {
998
1086
  (0, fs_1.writeFileSync)(temporaryOutputPath, '');
1087
+ this.tasksWithPersistedOutput.add(task.id);
999
1088
  return new noop_child_process_1.NoopChildProcess({
1000
1089
  code: 0,
1001
1090
  terminalOutput: '',
@@ -1004,6 +1093,12 @@ class TaskOrchestrator {
1004
1093
  else {
1005
1094
  // cache prep
1006
1095
  const runningTask = await this.runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput);
1096
+ // Every forked path leaves the file behind whatever the output style:
1097
+ // the pseudo-terminal and prefixed processes write it when they exit,
1098
+ // the direct-output capture has the child write it itself, and the
1099
+ // fork-failure fallback writes the error. Continuous tasks depend on
1100
+ // that — they never reach postRunSteps.
1101
+ this.tasksWithPersistedOutput.add(task.id);
1007
1102
  if (this.tuiEnabled) {
1008
1103
  if (runningTask instanceof pseudo_terminal_1.PseudoTtyProcess) {
1009
1104
  // This is an external of a the pseudo terminal where a task is running and can be passed to the TUI
@@ -1056,9 +1151,14 @@ class TaskOrchestrator {
1056
1151
  if (process.env.NX_VERBOSE_LOGGING === 'true') {
1057
1152
  console.error(e);
1058
1153
  }
1154
+ const terminalOutput = e.stack ?? e.message ?? '';
1155
+ // No process ever started, so nothing else will write the file. Record
1156
+ // why, so the task's terminal output path resolves to the fork error
1157
+ // rather than to nothing.
1158
+ (0, fs_1.writeFileSync)(temporaryOutputPath, terminalOutput);
1059
1159
  return new noop_child_process_1.NoopChildProcess({
1060
1160
  code: 1,
1061
- terminalOutput: e.stack ?? e.message ?? '',
1161
+ terminalOutput,
1062
1162
  });
1063
1163
  }
1064
1164
  }
@@ -1091,7 +1191,13 @@ class TaskOrchestrator {
1091
1191
  const pipeOutput = await this.pipeOutputCapture(task);
1092
1192
  // obtain metadata
1093
1193
  const temporaryOutputPath = this.cache.temporaryOutputPath(task);
1094
- const streamOutput = (0, output_1.isStaticOutputStyle)(this.outputStyle)
1194
+ // Deliberately not gated on `printsTaskOutput`, unlike `runTaskDirectly`.
1195
+ // `SummaryTerminalOutputLifeCycle.printTaskTerminalOutput` is a no-op and it
1196
+ // only reports at `endCommand`, which never runs for a task that does not
1197
+ // end - so suppressing here would leave a `nx serve` under `summary` with a
1198
+ // permanently silent terminal and no file to read yet. Streaming is the only
1199
+ // channel a continuous task has.
1200
+ const streamOutput = (0, output_1.isStaticOutputStyle)(this.specifiedOutputStyle)
1095
1201
  ? false
1096
1202
  : (0, utils_1.shouldStreamOutput)(task, this.initiatingProject);
1097
1203
  let env = pipeOutput
@@ -1108,6 +1214,9 @@ class TaskOrchestrator {
1108
1214
  this.continuousTaskExitHandled.set(task.id, new Promise((resolve) => {
1109
1215
  childProcess.onExit(async (code) => {
1110
1216
  await this.handleContinuousTaskExit(code, task, groupId, true);
1217
+ // Registered after the runner's own exit handler, which is what
1218
+ // wrote the file.
1219
+ this.recordContinuousTerminalOutput(task);
1111
1220
  resolve();
1112
1221
  });
1113
1222
  }));
@@ -1125,52 +1234,143 @@ class TaskOrchestrator {
1125
1234
  }
1126
1235
  async postRunSteps(results, shouldCache, groupId) {
1127
1236
  const now = Date.now();
1128
- const tasksToRecord = [];
1129
- for (const { task, status } of results) {
1237
+ for (const { task } of results) {
1130
1238
  // Only set endTime as fallback (batch provides timing via result.task)
1131
1239
  task.endTime ??= now;
1240
+ }
1241
+ // Caller decides whether these results should be written to the cache.
1242
+ // Cache replays pass false so a replayed failure (reported as 'failure' so
1243
+ // it counts as a failed run) isn't re-written to the cache on every replay.
1244
+ const resultsToCache = shouldCache && !this.stopRequested ? this.resultsToCache(results) : [];
1245
+ // Resolved before the cache writes so the two never write the same file.
1246
+ this.persistTerminalOutputs(results, resultsToCache);
1247
+ if (resultsToCache.length > 0) {
1248
+ // cache the results
1249
+ perf_hooks_1.performance.mark('cache-results-start');
1250
+ await Promise.all(resultsToCache.map(async ({ task, code, terminalOutput, outputs }) => {
1251
+ const files = await this.cache.put(task, terminalOutput, outputs, code);
1252
+ if (files)
1253
+ this.copiedOutputFiles.set(task.id, files);
1254
+ }));
1255
+ perf_hooks_1.performance.mark('cache-results-end');
1256
+ perf_hooks_1.performance.measure('cache-results', 'cache-results-start', 'cache-results-end');
1257
+ }
1258
+ const tasksToRecord = [];
1259
+ for (const { task, status } of results) {
1260
+ const files = this.copiedOutputFiles.get(task.id);
1261
+ this.copiedOutputFiles.delete(task.id);
1132
1262
  // Skip recording for tasks whose outputs already match the cache —
1133
1263
  // the daemon already has the correct hash recorded.
1134
1264
  if (!this.stopRequested &&
1135
1265
  task.outputs.length > 0 &&
1136
1266
  status !== 'local-cache-kept-existing') {
1137
- tasksToRecord.push({ outputs: task.outputs, hash: task.hash });
1267
+ tasksToRecord.push({ outputs: task.outputs, hash: task.hash, files });
1138
1268
  }
1139
1269
  }
1140
1270
  if (tasksToRecord.length > 0) {
1141
1271
  await this.recordOutputsHashBatch(tasksToRecord);
1142
1272
  }
1143
- // Caller decides whether these results should be written to the cache.
1144
- // Cache replays pass false so a replayed failure (reported as 'failure' so
1145
- // it counts as a failed run) isn't re-written to the cache on every replay.
1146
- if (shouldCache && !this.stopRequested) {
1147
- // cache the results
1148
- 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)));
1168
- perf_hooks_1.performance.mark('cache-results-end');
1169
- perf_hooks_1.performance.measure('cache-results', 'cache-results-start', 'cache-results-end');
1170
- }
1171
1273
  await this.complete(results, groupId);
1172
1274
  await this.scheduleNextTasksAndReleaseThreads();
1173
1275
  }
1276
+ /**
1277
+ * The results `cache.put` will write, in the shape it wants them. Pulled out
1278
+ * of postRunSteps so the terminal-output backstop can be told exactly which
1279
+ * tasks the cache is already writing a file for.
1280
+ */
1281
+ resultsToCache(results) {
1282
+ return results
1283
+ .filter(({ status }) => status !== 'local-cache' &&
1284
+ status !== 'local-cache-kept-existing' &&
1285
+ status !== 'remote-cache' &&
1286
+ status !== 'skipped' &&
1287
+ status !== 'stopped')
1288
+ .map((result) => ({
1289
+ ...result,
1290
+ code: result.status === 'local-cache' ||
1291
+ result.status === 'local-cache-kept-existing' ||
1292
+ result.status === 'remote-cache' ||
1293
+ result.status === 'success'
1294
+ ? 0
1295
+ : 1,
1296
+ outputs: result.task.outputs,
1297
+ }))
1298
+ .filter(({ task, code }) => this.shouldCacheTaskResult(task, code))
1299
+ .filter(({ terminalOutput, outputs }) => terminalOutput || outputs);
1300
+ }
1301
+ /**
1302
+ * Guarantee that every task that actually ran leaves its terminal output at
1303
+ * `<cacheDir>/terminalOutputs/<hash>`, whatever its cache setting, output
1304
+ * style, or batch membership. That path is what `--output-style=summary`
1305
+ * addresses each failure by, what the DB cache reads back on a hit
1306
+ * (`build_cached_result`), and what Nx Cloud falls back to reading when a
1307
+ * task's in-memory output is undefined, so a task that reaches a terminal
1308
+ * state without a file there is a dangling reference.
1309
+ *
1310
+ * Batch tasks are why this exists. Their output only ever arrives over IPC,
1311
+ * so the sole thing that ever put it on disk was `cache.put` — leaving a
1312
+ * `cache:false` batch task (the shape CI runs under `NX_BATCH_MODE`) with no
1313
+ * file at all.
1314
+ *
1315
+ * Written exactly once per task: tasks whose runner owns the file are
1316
+ * recorded in `tasksWithPersistedOutput`, and tasks `cache.put` is about to
1317
+ * write are skipped here. Cache hits are skipped by status — their output was
1318
+ * read from this very file — except a replayed cached *failure*, which comes
1319
+ * back as `failure` and is rewritten with the bytes it was just read with.
1320
+ * Skipped tasks never ran, so there is nothing to write.
1321
+ *
1322
+ * Every file written without a cache entry behind it is then registered with
1323
+ * the cache, because `removeOldCacheRecords` only collects hashes it finds in
1324
+ * the database — an unregistered file would never be cleaned up. That covers
1325
+ * files this method wrote AND ones a runner wrote, which are equally
1326
+ * invisible to the GC.
1327
+ */
1328
+ persistTerminalOutputs(results, resultsToCache) {
1329
+ const writtenByCache = new Set(resultsToCache.map(({ task }) => task.id));
1330
+ const toRecord = [];
1331
+ for (const { task, status, terminalOutput } of results) {
1332
+ if (terminalOutput === undefined ||
1333
+ // A task that failed before it was hashed has no path to write to.
1334
+ !task.hash ||
1335
+ status === 'skipped' ||
1336
+ status === 'local-cache' ||
1337
+ status === 'local-cache-kept-existing' ||
1338
+ status === 'remote-cache' ||
1339
+ // `cache.put` writes the file and records the hash itself.
1340
+ writtenByCache.has(task.id)) {
1341
+ continue;
1342
+ }
1343
+ if (!this.tasksWithPersistedOutput.has(task.id)) {
1344
+ this.tasksWithPersistedOutput.add(task.id);
1345
+ (0, fs_1.writeFileSync)(this.cache.temporaryOutputPath(task), terminalOutput);
1346
+ }
1347
+ toRecord.push({
1348
+ hash: task.hash,
1349
+ size: Buffer.byteLength(terminalOutput),
1350
+ });
1351
+ }
1352
+ if (toRecord.length > 0) {
1353
+ this.cache.recordTerminalOutputs(toRecord);
1354
+ }
1355
+ }
1356
+ /**
1357
+ * Register a continuous task's terminal output with the cache so the GC can
1358
+ * collect it. Continuous tasks never reach postRunSteps — their file is
1359
+ * written by whichever runner ran them, as the process exits — so this is
1360
+ * the only place their hash gets recorded. Read off disk rather than from a
1361
+ * result, because a continuous task completes without one.
1362
+ */
1363
+ recordContinuousTerminalOutput(task) {
1364
+ if (!task.hash)
1365
+ return;
1366
+ try {
1367
+ const { size } = (0, fs_1.statSync)(this.cache.temporaryOutputPath(task));
1368
+ this.cache.recordTerminalOutputs([{ hash: task.hash, size }]);
1369
+ }
1370
+ catch {
1371
+ // Exit handler: a throw here would be an unhandled rejection.
1372
+ }
1373
+ }
1174
1374
  async scheduleNextTasksAndReleaseThreads() {
1175
1375
  if (this.stopRequested) {
1176
1376
  this.waitingForTasks.forEach((f) => f(null));
@@ -19,6 +19,8 @@ export type TasksRunner<T = unknown> = (tasks: Task[], options: T, context?: {
19
19
  taskGraph?: TaskGraph;
20
20
  hasher?: TaskHasher;
21
21
  daemon?: DaemonClient;
22
+ /** Tasks hashed only once the tasks they read outputs from have run. */
23
+ deferredTaskIds?: ReadonlySet<string>;
22
24
  }) => any | Promise<{
23
25
  [id: string]: TaskStatus;
24
26
  }>;
@@ -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
+ }
@@ -49,6 +49,11 @@ export declare function getExecutorForTask(task: Task, projects: Record<string,
49
49
  isNxExecutor: boolean;
50
50
  };
51
51
  export declare function getCustomHasher(task: Task, projects: Record<string, ProjectConfiguration>): CustomHasher | null;
52
+ /**
53
+ * `taskGraph` pruned to `required`, which must already hold its dependencies.
54
+ * Unknown ids are ignored: a sync generator can remove a task after selection.
55
+ */
56
+ export declare function pruneToSelectedTasks(taskGraph: TaskGraph, required: Iterable<string>): TaskGraph;
52
57
  export declare function removeTasksFromTaskGraph(graph: TaskGraph, ids: string[]): TaskGraph;
53
58
  export declare function calculateReverseDeps(taskGraph: TaskGraph): Record<string, string[]>;
54
59
  export declare function getCliPath(): string;
@@ -17,6 +17,7 @@ exports.getExecutorNameForTask = getExecutorNameForTask;
17
17
  exports.expandInitiatingTasksThroughNoop = expandInitiatingTasksThroughNoop;
18
18
  exports.getExecutorForTask = getExecutorForTask;
19
19
  exports.getCustomHasher = getCustomHasher;
20
+ exports.pruneToSelectedTasks = pruneToSelectedTasks;
20
21
  exports.removeTasksFromTaskGraph = removeTasksFromTaskGraph;
21
22
  exports.calculateReverseDeps = calculateReverseDeps;
22
23
  exports.getCliPath = getCliPath;
@@ -221,7 +222,10 @@ function getOutputsForTargetAndConfiguration(taskTargetOrTask, overridesOrNode,
221
222
  validateOutputs(targetConfiguration.outputs);
222
223
  const result = new Set();
223
224
  for (const output of targetConfiguration.outputs) {
224
- const interpolatedOutput = interpolate(output, {
225
+ // A leading `!` is negation, not part of the path: strip it so
226
+ // `{workspaceRoot}` still sits where interpolate requires it.
227
+ const isNegated = output.startsWith('!');
228
+ const interpolatedOutput = interpolate(isNegated ? output.substring(1) : output, {
225
229
  projectRoot: node.data.root,
226
230
  projectName: node.name,
227
231
  project: { ...node.data, name: node.name }, // this is legacy
@@ -229,7 +233,7 @@ function getOutputsForTargetAndConfiguration(taskTargetOrTask, overridesOrNode,
229
233
  });
230
234
  if (!!interpolatedOutput &&
231
235
  !interpolatedOutput.match(/{(projectRoot|workspaceRoot|(options.*))}/)) {
232
- result.add(interpolatedOutput);
236
+ result.add(isNegated ? `!${interpolatedOutput}` : interpolatedOutput);
233
237
  }
234
238
  }
235
239
  return Array.from(result);
@@ -341,6 +345,14 @@ function getCustomHasher(task, projects) {
341
345
  const factory = getExecutorForTask(task, projects).hasherFactory;
342
346
  return factory ? factory() : null;
343
347
  }
348
+ /**
349
+ * `taskGraph` pruned to `required`, which must already hold its dependencies.
350
+ * Unknown ids are ignored: a sync generator can remove a task after selection.
351
+ */
352
+ function pruneToSelectedTasks(taskGraph, required) {
353
+ const keep = new Set(required);
354
+ return removeTasksFromTaskGraph(taskGraph, Object.keys(taskGraph.tasks).filter((id) => !keep.has(id)));
355
+ }
344
356
  function removeTasksFromTaskGraph(graph, ids) {
345
357
  const newGraph = removeIdsFromTaskGraph(graph, ids, graph.tasks);
346
358
  return {