nx 23.2.0-beta.7 → 23.2.0-beta.9

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 (188) hide show
  1. package/dist/bin/init-local.js +3 -5
  2. package/dist/release/changelog-renderer/index.js +4 -5
  3. package/dist/src/adapter/ngcli-adapter.js +60 -1
  4. package/dist/src/ai/set-up-ai-agents/set-up-ai-agents.js +2 -2
  5. package/dist/src/command-line/completion/command-object.js +7 -12
  6. package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +17 -23
  7. package/dist/src/command-line/format/format.js +84 -101
  8. package/dist/src/command-line/generate/generate.js +35 -35
  9. package/dist/src/command-line/import/import.js +30 -40
  10. package/dist/src/command-line/init/ai-agent-prompts.js +5 -11
  11. package/dist/src/command-line/init/command-object.js +4 -2
  12. package/dist/src/command-line/init/configure-plugins.js +4 -1
  13. package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +12 -32
  14. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +17 -21
  15. package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +8 -21
  16. package/dist/src/command-line/init/implementation/add-nx-to-turborepo.js +3 -17
  17. package/dist/src/command-line/init/implementation/angular/index.js +10 -15
  18. package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +2 -0
  19. package/dist/src/command-line/init/implementation/angular/standalone-workspace.js +8 -2
  20. package/dist/src/command-line/init/implementation/check-compatible-with-plugins.js +2 -0
  21. package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +5 -0
  22. package/dist/src/command-line/init/implementation/format.d.ts +18 -0
  23. package/dist/src/command-line/init/implementation/format.js +114 -0
  24. package/dist/src/command-line/init/implementation/utils.js +8 -0
  25. package/dist/src/command-line/init/init-v1.js +15 -18
  26. package/dist/src/command-line/init/init-v2.js +37 -56
  27. package/dist/src/command-line/migrate/agentic/definitions.js +35 -8
  28. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +22 -3
  29. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +13 -10
  30. package/dist/src/command-line/migrate/agentic/handoff.d.ts +3 -1
  31. package/dist/src/command-line/migrate/agentic/handoff.js +4 -2
  32. package/dist/src/command-line/migrate/agentic/run-step.js +1 -0
  33. package/dist/src/command-line/migrate/agentic/runner.js +24 -24
  34. package/dist/src/command-line/migrate/agentic/select.js +20 -30
  35. package/dist/src/command-line/migrate/agentic/types.d.ts +19 -3
  36. package/dist/src/command-line/migrate/agentic/types.js +13 -4
  37. package/dist/src/command-line/migrate/command-object.d.ts +3 -0
  38. package/dist/src/command-line/migrate/command-object.js +13 -0
  39. package/dist/src/command-line/migrate/execute-migration.d.ts +14 -0
  40. package/dist/src/command-line/migrate/execute-migration.js +30 -9
  41. package/dist/src/command-line/migrate/migrate-analytics.d.ts +28 -0
  42. package/dist/src/command-line/migrate/migrate-analytics.js +51 -1
  43. package/dist/src/command-line/migrate/migrate-commits.d.ts +8 -2
  44. package/dist/src/command-line/migrate/migrate-commits.js +66 -19
  45. package/dist/src/command-line/migrate/migrate-config.d.ts +4 -2
  46. package/dist/src/command-line/migrate/migrate-config.js +12 -4
  47. package/dist/src/command-line/migrate/migrate.d.ts +13 -2
  48. package/dist/src/command-line/migrate/migrate.js +243 -80
  49. package/dist/src/command-line/migrate/multi-major.js +7 -10
  50. package/dist/src/command-line/migrate/resolve-package-version.js +4 -8
  51. package/dist/src/command-line/migrate/run/agent-output.d.ts +20 -0
  52. package/dist/src/command-line/migrate/run/agent-output.js +65 -0
  53. package/dist/src/command-line/migrate/run/index.d.ts +7 -0
  54. package/dist/src/command-line/migrate/run/index.js +19 -1
  55. package/dist/src/command-line/migrate/run/orchestrator.d.ts +20 -0
  56. package/dist/src/command-line/migrate/run/orchestrator.js +1200 -0
  57. package/dist/src/command-line/migrate/run/run-id.d.ts +16 -0
  58. package/dist/src/command-line/migrate/run/run-id.js +56 -0
  59. package/dist/src/command-line/migrate/run/run-state.d.ts +157 -0
  60. package/dist/src/command-line/migrate/run/run-state.js +438 -0
  61. package/dist/src/command-line/migrate/run/state-lock.d.ts +25 -0
  62. package/dist/src/command-line/migrate/run/state-lock.js +76 -0
  63. package/dist/src/command-line/migrate/run/state-machine.d.ts +84 -0
  64. package/dist/src/command-line/migrate/run/state-machine.js +315 -0
  65. package/dist/src/command-line/migrate/run/util.d.ts +58 -0
  66. package/dist/src/command-line/migrate/run/util.js +139 -7
  67. package/dist/src/command-line/migrate/run/worker.d.ts +1 -0
  68. package/dist/src/command-line/migrate/run/worker.js +308 -45
  69. package/dist/src/command-line/migrate/safe-prompt.d.ts +14 -26
  70. package/dist/src/command-line/migrate/safe-prompt.js +32 -43
  71. package/dist/src/command-line/migrate/step-actions.d.ts +5 -0
  72. package/dist/src/command-line/migrate/step-actions.js +12 -0
  73. package/dist/src/command-line/migrate/text.d.ts +18 -0
  74. package/dist/src/command-line/migrate/text.js +26 -0
  75. package/dist/src/command-line/migrate/version-skew-guard.d.ts +6 -4
  76. package/dist/src/command-line/migrate/version-skew-guard.js +34 -14
  77. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +16 -20
  78. package/dist/src/command-line/release/changelog.js +6 -17
  79. package/dist/src/command-line/release/plan.js +15 -28
  80. package/dist/src/command-line/release/release.js +6 -17
  81. package/dist/src/command-line/release/utils/remote-release-clients/github.js +16 -22
  82. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +13 -22
  83. package/dist/src/command-line/release/utils/resolve-semver-specifier.js +19 -41
  84. package/dist/src/command-line/release/version/resolve-current-version.js +7 -10
  85. package/dist/src/command-line/release/version.js +2 -2
  86. package/dist/src/core/graph/main.js +1 -1
  87. package/dist/src/daemon/client/client.js +11 -2
  88. package/dist/src/devkit-internals.d.ts +7 -2
  89. package/dist/src/devkit-internals.js +22 -6
  90. package/dist/src/generators/internal-utils/{format-changed-files-with-prettier-if-available.d.ts → format-changed-files.d.ts} +6 -6
  91. package/dist/src/generators/internal-utils/format-changed-files.js +163 -0
  92. package/dist/src/generators/testing-utils/create-tree-with-empty-workspace.d.ts +15 -0
  93. package/dist/src/generators/testing-utils/create-tree-with-empty-workspace.js +21 -3
  94. package/dist/src/migrations/update-15-0-0/prefix-outputs.js +2 -2
  95. package/dist/src/migrations/update-16-0-0/remove-nrwl-cli.js +2 -2
  96. package/dist/src/migrations/update-16-0-0/update-depends-on-to-tokens.js +2 -2
  97. package/dist/src/migrations/update-16-0-0/update-nx-cloud-runner.js +2 -2
  98. package/dist/src/migrations/update-16-2-0/remove-run-commands-output-path.js +2 -2
  99. package/dist/src/migrations/update-17-0-0/rm-default-collection-npm-scope.js +2 -2
  100. package/dist/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.js +2 -2
  101. package/dist/src/migrations/update-17-2-0/move-default-base.js +2 -2
  102. package/dist/src/migrations/update-18-0-0/disable-crystal-for-existing-workspaces.js +2 -2
  103. package/dist/src/migrations/update-19-2-4/set-project-name.js +2 -2
  104. package/dist/src/migrations/update-20-0-0/move-use-daemon-process.js +2 -2
  105. package/dist/src/migrations/update-20-0-1/use-legacy-cache.js +2 -2
  106. package/dist/src/migrations/update-21-0-0/release-changelog-config-changes.js +2 -2
  107. package/dist/src/migrations/update-21-0-0/release-version-config-changes.js +2 -2
  108. package/dist/src/migrations/update-21-0-0/remove-custom-tasks-runner.js +2 -2
  109. package/dist/src/migrations/update-21-0-0/remove-legacy-cache.js +2 -2
  110. package/dist/src/migrations/update-22-0-0/consolidate-release-tag-config.js +2 -2
  111. package/dist/src/migrations/update-22-0-0/release-version-config-changes.js +2 -2
  112. package/dist/src/migrations/update-22-2-0/add-self-healing-to-gitignore.js +2 -2
  113. package/dist/src/migrations/update-22-6-0/add-claude-settings-local-to-git-ignore.js +2 -2
  114. package/dist/src/migrations/update-22-6-0/add-claude-worktrees-to-git-ignore.js +2 -2
  115. package/dist/src/migrations/update-22-7-0/add-polygraph-to-git-ignore.js +2 -2
  116. package/dist/src/migrations/update-23-0-0/add-migrate-runs-to-git-ignore.js +2 -2
  117. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.d.ts +12 -0
  118. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.js +250 -0
  119. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md +50 -0
  120. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  121. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  122. package/dist/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +3 -3
  123. package/dist/src/plugins/js/lock-file/bun-parser.js +43 -10
  124. package/dist/src/project-graph/utils/project-configuration/target-normalization.js +128 -2
  125. package/dist/src/tasks-runner/run-command.js +17 -32
  126. package/dist/src/tasks-runner/task-env.js +5 -2
  127. package/dist/src/tasks-runner/utils.js +2 -6
  128. package/dist/src/utils/analytics-prompt.js +4 -7
  129. package/dist/src/utils/chunkify.d.ts +7 -1
  130. package/dist/src/utils/chunkify.js +10 -3
  131. package/dist/src/utils/exit-codes.d.ts +9 -0
  132. package/dist/src/utils/exit-codes.js +19 -0
  133. package/dist/src/utils/fileutils.d.ts +5 -0
  134. package/dist/src/utils/fileutils.js +7 -2
  135. package/dist/src/utils/formatters/index.d.ts +13 -0
  136. package/dist/src/utils/formatters/index.js +74 -0
  137. package/dist/src/utils/formatters/oxfmt.d.ts +32 -0
  138. package/dist/src/utils/formatters/oxfmt.js +764 -0
  139. package/dist/src/utils/formatters/prettier.d.ts +26 -0
  140. package/dist/src/utils/formatters/prettier.js +201 -0
  141. package/dist/src/utils/formatters/shared.d.ts +5 -0
  142. package/dist/src/utils/formatters/shared.js +8 -0
  143. package/dist/src/utils/git-utils.d.ts +33 -2
  144. package/dist/src/utils/git-utils.js +156 -8
  145. package/dist/src/utils/ignore.d.ts +47 -5
  146. package/dist/src/utils/ignore.js +93 -11
  147. package/dist/src/utils/long-running-target.d.ts +10 -0
  148. package/dist/src/utils/long-running-target.js +19 -0
  149. package/dist/src/utils/min-release-age/behavior/bun.js +7 -11
  150. package/dist/src/utils/min-release-age/behavior/npm.js +5 -2
  151. package/dist/src/utils/min-release-age/packument.js +1 -1
  152. package/dist/src/utils/nx-console-prompt.js +3 -6
  153. package/dist/src/utils/package-manager-config/bunfig.d.ts +14 -0
  154. package/dist/src/utils/package-manager-config/bunfig.js +49 -0
  155. package/dist/src/utils/package-manager-config/npmrc.d.ts +23 -0
  156. package/dist/src/utils/package-manager-config/npmrc.js +124 -0
  157. package/dist/src/utils/package-manager-config/pnpm-config.d.ts +17 -0
  158. package/dist/src/utils/package-manager-config/pnpm-config.js +60 -0
  159. package/dist/src/utils/package-manager.d.ts +21 -2
  160. package/dist/src/utils/package-manager.js +244 -47
  161. package/dist/src/utils/params.d.ts +7 -1
  162. package/dist/src/utils/params.js +64 -6
  163. package/dist/src/utils/prompt-helpers.d.ts +53 -0
  164. package/dist/src/utils/prompt-helpers.js +111 -0
  165. package/dist/src/utils/provenance.js +6 -14
  166. package/dist/src/utils/registry-config/bun.d.ts +2 -0
  167. package/dist/src/utils/registry-config/bun.js +257 -0
  168. package/dist/src/utils/registry-config/index.d.ts +13 -0
  169. package/dist/src/utils/registry-config/index.js +102 -0
  170. package/dist/src/utils/registry-config/pnpm.d.ts +2 -0
  171. package/dist/src/utils/registry-config/pnpm.js +1551 -0
  172. package/dist/src/utils/registry-config/utils.d.ts +195 -0
  173. package/dist/src/utils/registry-config/utils.js +496 -0
  174. package/dist/src/utils/registry-config/yarn-berry.d.ts +2 -0
  175. package/dist/src/utils/registry-config/yarn-berry.js +612 -0
  176. package/dist/src/utils/registry-config/yarn-classic.d.ts +2 -0
  177. package/dist/src/utils/registry-config/yarn-classic.js +1001 -0
  178. package/dist/src/utils/safe-spawn.d.ts +24 -0
  179. package/dist/src/utils/safe-spawn.js +104 -0
  180. package/dist/src/utils/write-formatted-json-file.d.ts +3 -2
  181. package/dist/src/utils/write-formatted-json-file.js +5 -4
  182. package/migrations.json +6 -0
  183. package/package.json +17 -13
  184. package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +0 -88
  185. package/dist/src/utils/is-using-prettier.d.ts +0 -3
  186. package/dist/src/utils/is-using-prettier.js +0 -62
  187. package/dist/src/utils/min-release-age/npmrc.d.ts +0 -15
  188. package/dist/src/utils/min-release-age/npmrc.js +0 -45
@@ -9,7 +9,7 @@ exports.createFetcher = createFetcher;
9
9
  exports.generateMigrationsJsonAndUpdatePackageJson = generateMigrationsJsonAndUpdatePackageJson;
10
10
  exports.formatSkippedPromptsNextStep = formatSkippedPromptsNextStep;
11
11
  exports.executeMigrations = executeMigrations;
12
- exports.isSingleMigrationInvocation = isSingleMigrationInvocation;
12
+ exports.isRunPhaseInvocation = isRunPhaseInvocation;
13
13
  exports.migrate = migrate;
14
14
  exports.readLocalNxVersion = readLocalNxVersion;
15
15
  exports.runMigration = runMigration;
@@ -31,7 +31,6 @@ const write_formatted_json_file_1 = require("../../utils/write-formatted-json-fi
31
31
  const shell_quoting_1 = require("../../utils/shell-quoting");
32
32
  const logger_1 = require("../../utils/logger");
33
33
  const git_utils_1 = require("../../utils/git-utils");
34
- const command_line_utils_1 = require("../../utils/command-line-utils");
35
34
  const package_json_1 = require("../../utils/package-json");
36
35
  const package_manager_1 = require("../../utils/package-manager");
37
36
  const errors_1 = require("../../utils/min-release-age/errors");
@@ -48,7 +47,7 @@ const configuration_1 = require("../../config/configuration");
48
47
  const child_process_2 = require("../../utils/child-process");
49
48
  const client_1 = require("../../daemon/client/client");
50
49
  const nx_cloud_utils_1 = require("../../utils/nx-cloud-utils");
51
- const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
50
+ const format_changed_files_1 = require("../../generators/internal-utils/format-changed-files");
52
51
  const provenance_1 = require("../../utils/provenance");
53
52
  const catalog_1 = require("../../utils/catalog");
54
53
  const migrate_analytics_1 = require("./migrate-analytics");
@@ -66,7 +65,9 @@ Object.defineProperty(exports, "filterDowngradedUpdates", { enumerable: true, ge
66
65
  const version_utils_1 = require("./version-utils");
67
66
  Object.defineProperty(exports, "normalizeVersion", { enumerable: true, get: function () { return version_utils_1.normalizeVersion; } });
68
67
  const execute_migration_1 = require("./execute-migration");
68
+ const step_actions_1 = require("./step-actions");
69
69
  const sort_migrations_1 = require("./sort-migrations");
70
+ const inception_1 = require("./agentic/inception");
70
71
  const version_skew_guard_1 = require("./version-skew-guard");
71
72
  const versions_1 = require("../../utils/versions");
72
73
  tslib_1.__exportStar(require("./execute-migration"), exports);
@@ -112,6 +113,8 @@ class Migrator {
112
113
  this.packageUpdates = {};
113
114
  this.collectedVersions = {};
114
115
  this.promptAnswers = {};
116
+ this.pendingPackageJsonUpdates = new Map();
117
+ this.appliedPackageJsonUpdates = new Set();
115
118
  if ((opts.include === 'required' || opts.include === 'optional') &&
116
119
  !opts.requiredPackages) {
117
120
  throw new Error(`Error: 'requiredPackages' is required when 'include' is '${opts.include}'.`);
@@ -139,6 +142,7 @@ class Migrator {
139
142
  version: targetVersion,
140
143
  addToPackageJson: false,
141
144
  });
145
+ await this.applyPendingPackageJsonUpdates();
142
146
  this.applyIncludeFilter();
143
147
  const { migrations, promptContents } = await this.createMigrateJson();
144
148
  return {
@@ -184,29 +188,66 @@ class Migrator {
184
188
  for (const packageToCheck of packagesToCheck) {
185
189
  const filteredUpdates = {};
186
190
  for (const [packageUpdateKey, packageUpdate] of Object.entries(packageToCheck.updates)) {
187
- if (this.areRequirementsMet(packageUpdate.requires) &&
188
- !this.areIncompatiblePackagesPresent(packageUpdate.incompatibleWith) &&
189
- (!this.interactive ||
190
- (await this.runPackageJsonUpdatesConfirmationPrompt(packageUpdate, packageUpdateKey, packageToCheck.package)))) {
191
- const updateEntries = Object.entries(packageUpdate.packages);
192
- // Validate all up front so invalid metadata fails fast, before any
193
- // resolution does I/O.
194
- for (const [name, update] of updateEntries) {
195
- this.validatePackageUpdateVersion(packageToCheck.package, name, update);
196
- }
197
- // Resolve serially: resolution can prompt (pnpm strict cooldown) and
198
- // append to minimumReleaseAgeExclude, so a serial loop avoids
199
- // overlapping prompts and keeps packageUpdates ordering stable.
200
- for (const [name, update] of updateEntries) {
201
- const resolvedUpdate = {
202
- ...update,
203
- version: await this.resolveVersionForCascade(name, update.version),
204
- };
205
- filteredUpdates[name] = resolvedUpdate;
206
- this.packageUpdates[name] = resolvedUpdate;
207
- }
191
+ Object.assign(filteredUpdates, await this.applyPackageJsonUpdate(packageToCheck.package, packageUpdateKey, packageUpdate));
192
+ }
193
+ await Promise.all(Object.entries(filteredUpdates).map(([name, update]) => this.buildPackageJsonUpdates(name, update)));
194
+ }
195
+ }
196
+ async applyPackageJsonUpdate(sourcePackage, packageUpdateKey, packageUpdate) {
197
+ const appliedKey = JSON.stringify([sourcePackage, packageUpdateKey]);
198
+ if (this.appliedPackageJsonUpdates.has(appliedKey)) {
199
+ this.pendingPackageJsonUpdates.delete(appliedKey);
200
+ return {};
201
+ }
202
+ if (!this.areRequirementsMet(packageUpdate.requires) ||
203
+ this.areIncompatiblePackagesPresent(packageUpdate.incompatibleWith)) {
204
+ this.pendingPackageJsonUpdates.set(appliedKey, {
205
+ package: sourcePackage,
206
+ key: packageUpdateKey,
207
+ update: packageUpdate,
208
+ });
209
+ return {};
210
+ }
211
+ this.pendingPackageJsonUpdates.delete(appliedKey);
212
+ if (this.interactive &&
213
+ !(await this.runPackageJsonUpdatesConfirmationPrompt(packageUpdate, packageUpdateKey, sourcePackage))) {
214
+ return {};
215
+ }
216
+ this.appliedPackageJsonUpdates.add(appliedKey);
217
+ const updateEntries = Object.entries(packageUpdate.packages);
218
+ // Validate all up front so invalid metadata fails fast, before any
219
+ // resolution does I/O.
220
+ for (const [name, update] of updateEntries) {
221
+ this.validatePackageUpdateVersion(sourcePackage, name, update);
222
+ }
223
+ const filteredUpdates = {};
224
+ // Resolve serially: resolution can prompt (pnpm strict cooldown) and append
225
+ // to minimumReleaseAgeExclude, so a serial loop avoids overlapping prompts
226
+ // and keeps packageUpdates ordering stable.
227
+ for (const [name, update] of updateEntries) {
228
+ const resolvedUpdate = {
229
+ ...update,
230
+ version: await this.resolveVersionForCascade(name, update.version),
231
+ };
232
+ this.addPackageUpdate(name, resolvedUpdate);
233
+ filteredUpdates[name] = this.packageUpdates[name];
234
+ }
235
+ return filteredUpdates;
236
+ }
237
+ async applyPendingPackageJsonUpdates() {
238
+ while (this.pendingPackageJsonUpdates.size) {
239
+ let applied = false;
240
+ const filteredUpdates = {};
241
+ for (const pending of [...this.pendingPackageJsonUpdates.values()]) {
242
+ const updates = await this.applyPackageJsonUpdate(pending.package, pending.key, pending.update);
243
+ if (Object.keys(updates).length) {
244
+ applied = true;
245
+ Object.assign(filteredUpdates, updates);
208
246
  }
209
247
  }
248
+ if (!applied) {
249
+ return;
250
+ }
210
251
  await Promise.all(Object.entries(filteredUpdates).map(([name, update]) => this.buildPackageJsonUpdates(name, update)));
211
252
  }
212
253
  }
@@ -410,7 +451,7 @@ class Migrator {
410
451
  }
411
452
  addPackageUpdate(name, packageUpdate) {
412
453
  if (!this.packageUpdates[name] ||
413
- this.gt(packageUpdate.version, this.packageUpdates[name].version)) {
454
+ !this.lt(packageUpdate.version, this.packageUpdates[name].version)) {
414
455
  this.packageUpdates[name] = packageUpdate;
415
456
  }
416
457
  }
@@ -476,17 +517,14 @@ class Migrator {
476
517
  // a same prompt was already answered, skip
477
518
  return Promise.resolve(false);
478
519
  }
479
- const promptConfig = {
480
- name: 'shouldApply',
481
- type: 'confirm',
482
- message: packageUpdate['x-prompt'],
520
+ // No footer slot, so the docs link is appended to the message.
521
+ const detailsLink = packageName.startsWith('@nx/')
522
+ ? pc.dim(`\n View migration details at https://nx.dev/nx-api/${packageName.replace('@nx/', '')}#${packageUpdateKey.replace(/[-\.]/g, '')}packageupdates`)
523
+ : '';
524
+ return await (0, safe_prompt_1.migrateConfirm)({
525
+ message: `${packageUpdate['x-prompt']}${detailsLink}`,
483
526
  initial: true,
484
- };
485
- if (packageName.startsWith('@nx/')) {
486
- // @ts-expect-error -- enquirer types aren't correct, footer does exist
487
- promptConfig.footer = () => pc.dim(` View migration details at https://nx.dev/nx-api/${packageName.replace('@nx/', '')}#${packageUpdateKey.replace(/[-\.]/g, '')}packageupdates`);
488
- }
489
- return await (0, safe_prompt_1.migratePrompt)([promptConfig]).then(({ shouldApply }) => {
527
+ }).then((shouldApply) => {
490
528
  this.promptAnswers[promptKey] = shouldApply;
491
529
  if (!shouldApply &&
492
530
  (!this.minVersionWithSkippedUpdates ||
@@ -587,8 +625,8 @@ async function resolveInclude(include, context, configuredInclude) {
587
625
  }
588
626
  const choices = [
589
627
  {
590
- name: 'required',
591
- message: 'Required only (the target package and the packages it ships with)',
628
+ value: 'required',
629
+ label: 'Required only (the target package and the packages it ships with)',
592
630
  },
593
631
  ];
594
632
  // `--interactive` keeps the legacy x-prompt flow, which the `optional` value
@@ -597,8 +635,8 @@ async function resolveInclude(include, context, configuredInclude) {
597
635
  !context.hasExcludeAppliedMigrations &&
598
636
  context.interactive !== true) {
599
637
  choices.push({
600
- name: 'optional',
601
- message: 'Optional only (the dependency updates those packages recommend)',
638
+ value: 'optional',
639
+ label: 'Optional only (the dependency updates those packages recommend)',
602
640
  });
603
641
  }
604
642
  if (!(0, safe_prompt_1.canPrompt)(context.interactive)) {
@@ -606,12 +644,10 @@ async function resolveInclude(include, context, configuredInclude) {
606
644
  return 'all';
607
645
  }
608
646
  choices.push({
609
- name: 'all',
610
- message: 'All (required and optional)',
647
+ value: 'all',
648
+ label: 'All (required and optional)',
611
649
  });
612
- const { include: selected } = await (0, safe_prompt_1.migratePrompt)({
613
- type: 'select',
614
- name: 'include',
650
+ const selected = await (0, safe_prompt_1.migrateChoice)({
615
651
  message: 'Which packages would you like to migrate?',
616
652
  choices,
617
653
  });
@@ -671,10 +707,25 @@ async function parseTargetPackageAndVersion(args) {
671
707
  return { targetPackage: args, targetVersion: 'latest' };
672
708
  }
673
709
  async function parseMigrationsOptions(options, fetch) {
710
+ // A run recorded or reconciled via `--run-id` is driven by the outer agent;
711
+ // spawning another agent from it would double-drive the run. Only the
712
+ // explicit "on" values conflict; the nx.json default is ignored for
713
+ // `--run-id` invocations instead.
714
+ if (options.runId !== undefined &&
715
+ options.agentic !== undefined &&
716
+ options.agentic !== false) {
717
+ throw new Error(`Error: '--agentic' cannot be combined with '--run-id'.`);
718
+ }
674
719
  if (options.runMigration !== undefined) {
675
720
  if (options.runMigration === '') {
676
721
  throw new Error(`Error: '--run-migration' requires a migration id, e.g. '--run-migration=@nx/js:my-migration'.`);
677
722
  }
723
+ if (options.runId === '') {
724
+ throw new Error(`Error: '--run-id' requires the id of the migrate run to record into.`);
725
+ }
726
+ if (options.stepAction !== undefined) {
727
+ throw new Error(`Error: '--step-action' cannot be combined with '--run-migration'. It applies to an orchestrated reconcile ('--run-id' without '--run-migration').`);
728
+ }
678
729
  if (options.runMigrations !== undefined) {
679
730
  throw new Error(`Error: '--run-migration' (run a single migration) cannot be combined with '--run-migrations' (run the whole migrations file).`);
680
731
  }
@@ -692,11 +743,39 @@ async function parseMigrationsOptions(options, fetch) {
692
743
  return {
693
744
  type: 'runSingleMigration',
694
745
  runMigration: options.runMigration,
746
+ runId: options.runId,
695
747
  agentic: options.agentic,
696
748
  validate: options.validate,
697
749
  interactive: options.interactive,
698
750
  };
699
751
  }
752
+ if (options.runId !== undefined) {
753
+ // Empty '--run-id' is an error on every path.
754
+ if (options.runId === '') {
755
+ throw new Error(`Error: '--run-id' requires the id of the migrate run to record into.`);
756
+ }
757
+ if (options.runMigrations !== undefined) {
758
+ throw new Error(`Error: '--run-id' (reconcile an orchestrated run) cannot be combined with '--run-migrations' (run the whole migrations file).`);
759
+ }
760
+ // A bare '--run-id' reconciles the run it names. Ungated, unlike init:
761
+ // the id has to name a run directory that exists, and only a gated init
762
+ // ever creates one.
763
+ // yargs' choices already reject bad CLI values; this guards programmatic
764
+ // callers, where silently dropping the action would reconcile without it.
765
+ if (options.stepAction !== undefined && !(0, step_actions_1.isStepAction)(options.stepAction)) {
766
+ throw new Error(`Error: '--step-action' must be one of ${step_actions_1.STEP_ACTIONS.join(', ')}.`);
767
+ }
768
+ return {
769
+ type: 'orchestratorReconcile',
770
+ runId: options.runId,
771
+ ...(options.stepAction !== undefined
772
+ ? { stepAction: options.stepAction }
773
+ : {}),
774
+ };
775
+ }
776
+ if (options.stepAction !== undefined) {
777
+ throw new Error(`Error: '--step-action' requires '--run-id'.`);
778
+ }
700
779
  if (options.runMigrations === '') {
701
780
  options.runMigrations = 'migrations.json';
702
781
  }
@@ -1121,8 +1200,30 @@ async function getPackageMigrationsUsingRegistry(packageName, packageVersion) {
1121
1200
  // try to obtain the migrations from the registry directly
1122
1201
  return await downloadPackageMigrationsFromRegistry(packageName, packageVersion, migrationsConfig);
1123
1202
  }
1203
+ // Matched exactly: a hostname that merely contains one of these is a different
1204
+ // registry. registry.yarnpkg.com is npmjs' CNAME, so it serves the same
1205
+ // metadata; the two loopback literals are the spellings of a local registry
1206
+ // that the substring below cannot reach, since neither contains "localhost".
1207
+ const FULL_METADATA_REGISTRIES = [
1208
+ 'registry.npmjs.org',
1209
+ 'registry.yarnpkg.com',
1210
+ '127.0.0.1',
1211
+ '[::1]',
1212
+ ];
1213
+ // Matched as substrings, since neither names a single host: a local registry
1214
+ // can sit on a subdomain of localhost, and an Artifactory instance is
1215
+ // identified only by that word appearing somewhere in its hostname.
1216
+ const FULL_METADATA_REGISTRY_MARKERS = [
1217
+ 'localhost',
1218
+ 'artifactory',
1219
+ ];
1124
1220
  async function getPackageMigrationsConfigFromRegistry(packageName, packageVersion) {
1125
- const result = await (0, package_manager_1.packageRegistryView)(packageName, packageVersion, 'nx-migrations ng-update dist --json');
1221
+ const result = await (0, package_manager_1.packageRegistryView)(packageName, packageVersion, [
1222
+ 'nx-migrations',
1223
+ 'ng-update',
1224
+ 'dist',
1225
+ '--json',
1226
+ ]);
1126
1227
  if (!result) {
1127
1228
  return null;
1128
1229
  }
@@ -1130,9 +1231,10 @@ async function getPackageMigrationsConfigFromRegistry(packageName, packageVersio
1130
1231
  if (!json['nx-migrations'] && !json['ng-update']) {
1131
1232
  const registry = new node_url_1.URL('dist' in json ? json.dist.tarball : json.tarball)
1132
1233
  .hostname;
1133
- // Registries other than npmjs and the local registry may not support full metadata via npm view
1134
- // so throw error so that fetcher falls back to getting config via install
1135
- if (!['registry.npmjs.org', 'localhost', 'artifactory'].some((v) => registry.includes(v))) {
1234
+ // Other registries may not support full metadata via npm view; throw to
1235
+ // trigger the install fallback.
1236
+ if (!FULL_METADATA_REGISTRIES.includes(registry) &&
1237
+ !FULL_METADATA_REGISTRY_MARKERS.some((v) => registry.includes(v))) {
1136
1238
  throw new Error(`Getting migration config from registry is not supported from ${registry}`);
1137
1239
  }
1138
1240
  }
@@ -1325,7 +1427,7 @@ async function formatCatalogDefinitionFiles(manager, root) {
1325
1427
  content: (0, fs_1.readFileSync)(absolutePath, 'utf-8'),
1326
1428
  };
1327
1429
  });
1328
- const results = await (0, format_changed_files_with_prettier_if_available_1.formatFilesWithPrettierIfAvailable)(catalogDefinitionFiles.map(({ path, content }) => ({ path, content })), root, { silent: true });
1430
+ const results = await (0, format_changed_files_1.formatFileContents)(catalogDefinitionFiles.map(({ path, content }) => ({ path, content })), root, { silent: true });
1329
1431
  for (const { path, absolutePath, content } of catalogDefinitionFiles) {
1330
1432
  (0, fs_1.writeFileSync)(absolutePath, results.has(path) ? results.get(path) : content, { encoding: 'utf-8' });
1331
1433
  }
@@ -2024,6 +2126,46 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits, c
2024
2126
  }
2025
2127
  const migrationsJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, opts.runMigrations));
2026
2128
  const migrations = migrationsJson.migrations;
2129
+ // An outer agent drives the loop, so hand off to the orchestrator instead of
2130
+ // the classic loop: init either starts a fresh run or resumes an already-
2131
+ // active one. `--run-id` reconciles are dispatched separately and never
2132
+ // reach here.
2133
+ if (process.env.NX_MIGRATE_ORCHESTRATOR === 'true' && (0, inception_1.isInsideAgent)()) {
2134
+ // Orchestrated runs are agent-driven, so commits default on exactly as they
2135
+ // do under `--agentic=enabled`; the orchestrator replaces `resolveAgentic`.
2136
+ const { effective: effectiveCreateCommits, warning: createCommitsWarning, error: createCommitsError, } = (0, migrate_commits_1.resolveCreateCommits)({
2137
+ createCommits: shouldCreateCommits,
2138
+ mode: 'orchestrated',
2139
+ isGitRepo: (0, git_utils_1.isGitRepository)(root),
2140
+ commitPrefixIsCustom: commitPrefix !== command_object_1.DEFAULT_MIGRATION_COMMIT_PREFIX,
2141
+ });
2142
+ if (createCommitsError) {
2143
+ throw new Error(createCommitsError);
2144
+ }
2145
+ if (createCommitsWarning) {
2146
+ output_1.output.warn({ title: createCommitsWarning });
2147
+ }
2148
+ // The run commits on the user's behalf across many invocations, so the
2149
+ // default-branch confirmation belongs here, once, before any of them.
2150
+ if (effectiveCreateCommits &&
2151
+ (0, safe_prompt_1.canPrompt)(opts.interactive) &&
2152
+ !(await (0, migrate_commits_1.confirmMigrationCommitsOnDefaultBranch)(root, 'running migrations'))) {
2153
+ return;
2154
+ }
2155
+ const { packageJson: orchestratorNxPackageJson } = (0, package_json_1.readModulePackageJson)('nx', (0, installation_directory_1.getNxRequirePaths)(root));
2156
+ const { runOrchestratorInit } = require('./run');
2157
+ return await runOrchestratorInit({
2158
+ root,
2159
+ migrationsJson,
2160
+ createCommits: effectiveCreateCommits,
2161
+ commitPrefix,
2162
+ // The flag only, never NX_MIGRATE_SKIP_INSTALL: the wrapper's local
2163
+ // re-exec sets that env var for its own hop, and it says nothing about
2164
+ // what the user asked for.
2165
+ skipInstall: shouldSkipInstall,
2166
+ installedNxVersion: orchestratorNxPackageJson.version,
2167
+ });
2168
+ }
2027
2169
  (0, migrate_analytics_1.reportMigrateRunStart)({
2028
2170
  createCommits: shouldCreateCommits ?? false,
2029
2171
  migrationCount: migrations.length,
@@ -2043,7 +2185,7 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits, c
2043
2185
  }
2044
2186
  const { effective: effectiveCreateCommits, agenticHasDiffContext, warning: createCommitsWarning, error: createCommitsError, } = (0, migrate_commits_1.resolveCreateCommits)({
2045
2187
  createCommits: shouldCreateCommits,
2046
- agenticKind: agentic.kind,
2188
+ mode: agentic.kind,
2047
2189
  isGitRepo: (0, git_utils_1.isGitRepository)(root),
2048
2190
  commitPrefixIsCustom: commitPrefix !== command_object_1.DEFAULT_MIGRATION_COMMIT_PREFIX,
2049
2191
  });
@@ -2053,24 +2195,10 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits, c
2053
2195
  if (createCommitsWarning) {
2054
2196
  output_1.output.warn({ title: createCommitsWarning });
2055
2197
  }
2056
- if (effectiveCreateCommits && (0, safe_prompt_1.canPrompt)(opts.interactive)) {
2057
- const currentBranch = (0, git_utils_1.getGitCurrentBranch)(root);
2058
- // `getBaseRef` may carry an `origin/` prefix (set by the CI-workflow
2059
- // generator); compare against the local branch name.
2060
- const defaultBranch = (0, command_line_utils_1.getBaseRef)((0, configuration_1.readNxJson)(root)).replace(/^origin\//, '');
2061
- const proceed = await (0, migrate_commits_1.confirmCommitsOnDefaultBranch)({
2062
- currentBranch,
2063
- defaultBranch,
2064
- });
2065
- if (!proceed) {
2066
- output_1.output.log({
2067
- title: `Skipped running migrations to avoid committing to the default branch '${currentBranch}'.`,
2068
- bodyLines: [
2069
- 'Switch to a different branch and re-run, or re-run and confirm to proceed.',
2070
- ],
2071
- });
2072
- return;
2073
- }
2198
+ if (effectiveCreateCommits &&
2199
+ (0, safe_prompt_1.canPrompt)(opts.interactive) &&
2200
+ !(await (0, migrate_commits_1.confirmMigrationCommitsOnDefaultBranch)(root, 'running migrations'))) {
2201
+ return;
2074
2202
  }
2075
2203
  const shouldRunValidation = resolveShouldRunValidation({
2076
2204
  validate: opts.validate,
@@ -2189,17 +2317,21 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits, c
2189
2317
  appliedCount,
2190
2318
  });
2191
2319
  }
2192
- function isSingleMigrationInvocation(args) {
2193
- return args.runMigration !== undefined;
2320
+ function isRunPhaseInvocation(args) {
2321
+ return (args.runMigration !== undefined ||
2322
+ args.runId !== undefined ||
2323
+ args.stepAction !== undefined);
2194
2324
  }
2195
2325
  async function migrate(root, args, rawArgs) {
2196
2326
  await client_1.daemonClient.stop();
2197
2327
  return (0, handle_errors_1.handleErrors)(process.env.NX_VERBOSE_LOGGING === 'true', async () => {
2198
2328
  const mergedArgs = (0, migrate_config_1.applyNxJsonMigrateDefaults)(args, (0, configuration_1.readNxJson)().migrate);
2199
- // A single-migration invocation resolves its commit config downstream via
2200
- // resolveCreateCommits, so this assert must not fire for it.
2201
- const singleMigration = isSingleMigrationInvocation(mergedArgs);
2202
- if (!singleMigration) {
2329
+ // Run-phase invocations resolve their commit config downstream (run.json
2330
+ // for recorded runs, resolveCreateCommits for standalone), so this assert
2331
+ // must not fire for them; otherwise an nx.json prefix the whole-file run
2332
+ // legitimately uses would wedge every dispensed command.
2333
+ const runPhase = isRunPhaseInvocation(mergedArgs);
2334
+ if (!runPhase) {
2203
2335
  (0, migrate_config_1.assertCommitPrefixHasCommits)(mergedArgs);
2204
2336
  }
2205
2337
  // One fetcher (registry-first, install fallback) shared by the `--include`
@@ -2207,8 +2339,8 @@ async function migrate(root, args, rawArgs) {
2207
2339
  // at most once per package/version.
2208
2340
  const fetch = createFetcher((0, package_manager_1.getPackageManagerCommand)());
2209
2341
  // `--run-migrations` without a value parses as '', so only undefined (and
2210
- // no single-migration flag) means the generate phase.
2211
- const isGenerateInvocation = mergedArgs['runMigrations'] === undefined && !singleMigration;
2342
+ // no run-phase flag) means the generate phase.
2343
+ const isGenerateInvocation = mergedArgs['runMigrations'] === undefined && !runPhase;
2212
2344
  let opts;
2213
2345
  try {
2214
2346
  opts = await parseMigrationsOptions(mergedArgs, fetch);
@@ -2217,7 +2349,7 @@ async function migrate(root, args, rawArgs) {
2217
2349
  if (isGenerateInvocation) {
2218
2350
  (0, migrate_analytics_1.reportMigrateGenerateError)('resolve_version', e);
2219
2351
  }
2220
- else if (singleMigration) {
2352
+ else if (runPhase) {
2221
2353
  (0, migrate_analytics_1.reportMigrateRunError)({ code: 'other', error: e });
2222
2354
  }
2223
2355
  throw e;
@@ -2240,6 +2372,8 @@ async function migrate(root, args, rawArgs) {
2240
2372
  (0, migrate_analytics_1.reportMigrateRunError)({ code: 'other', error: e });
2241
2373
  throw e;
2242
2374
  }
2375
+ case 'orchestratorReconcile':
2376
+ return await runOrchestratorReconcileFromCli(root, opts, rawArgs);
2243
2377
  case 'runMigrations':
2244
2378
  try {
2245
2379
  return await runMigrations(root, opts, rawArgs, mergedArgs['verbose'], mergedArgs['createCommits'], mergedArgs['commitPrefix'] ?? command_object_1.DEFAULT_MIGRATION_COMMIT_PREFIX, mergedArgs['skipInstall']);
@@ -2425,11 +2559,37 @@ function readNxVersionFromNodeModules(searchPaths) {
2425
2559
  }
2426
2560
  return undefined;
2427
2561
  }
2562
+ // Mirrors the local-nx hand-off of the other run paths so a reconcile always
2563
+ // executes against the workspace-local nx that owns the run state, never the
2564
+ // temp installation. Reconciles only read state and commit, so no install.
2565
+ async function runOrchestratorReconcileFromCli(root, opts, args) {
2566
+ if (!__dirname.startsWith(workspace_root_1.workspaceRoot)) {
2567
+ // The workspace-local nx we are about to hand off to must be new enough to
2568
+ // understand the new flags we forward to it.
2569
+ (0, version_skew_guard_1.assertWorkspaceNxSupportsNewMigrateFlags)({
2570
+ argv: args,
2571
+ readLocalNxVersion: () => readLocalNxVersion(root),
2572
+ });
2573
+ return handOffToLocalNx(args);
2574
+ }
2575
+ const { runOrchestratorReconcile } = require('./run');
2576
+ return runOrchestratorReconcile({
2577
+ root,
2578
+ runId: opts.runId,
2579
+ stepAction: opts.stepAction,
2580
+ });
2581
+ }
2428
2582
  // Keeps `--run-migration` behaving like `--run-migrations` when invoked from
2429
2583
  // a temp `nx@latest` install: same pre-install, same local-nx hand-off.
2430
2584
  async function runSingleMigrationFromCli(root, opts, args, mergedArgs) {
2431
2585
  const shouldSkipInstall = mergedArgs['skipInstall'] ?? false;
2432
- if (!shouldSkipInstall && !process.env.NX_MIGRATE_SKIP_INSTALL) {
2586
+ // A recorded execution skips the pre-install: the run carries its own
2587
+ // install policy and its worker installs what the migration changed, so
2588
+ // paying for a full install ahead of every dispensed command would be
2589
+ // redundant.
2590
+ if (opts.runId === undefined &&
2591
+ !shouldSkipInstall &&
2592
+ !process.env.NX_MIGRATE_SKIP_INSTALL) {
2433
2593
  await (0, execute_migration_1.runInstall)(undefined, 'pre-migration', (0, execute_migration_1.formatSingleMigrationRerunCommand)(opts.runMigration));
2434
2594
  }
2435
2595
  if (!__dirname.startsWith(workspace_root_1.workspaceRoot)) {
@@ -2446,13 +2606,15 @@ async function runSingleMigrationFromCli(root, opts, args, mergedArgs) {
2446
2606
  return handOffToLocalNx(args);
2447
2607
  }
2448
2608
  // The worker resolves the agentic flow, the effective commit config, and
2449
- // the default-branch confirmation itself; hand it the raw flags.
2609
+ // the default-branch confirmation itself; hand it the raw flags. Recorded
2610
+ // runs (--run-id) take their commit config from run.json instead.
2450
2611
  // Lazy-load run/ so plain migrate and repair runs don't pay for the agentic
2451
2612
  // selection chain its barrel pulls in eagerly.
2452
2613
  const { runSingleMigrationWorker } = require('./run');
2453
2614
  await runSingleMigrationWorker({
2454
2615
  root,
2455
2616
  runMigration: opts.runMigration,
2617
+ runId: opts.runId,
2456
2618
  agentic: opts.agentic,
2457
2619
  validate: opts.validate,
2458
2620
  createCommits: mergedArgs['createCommits'],
@@ -2479,7 +2641,8 @@ async function runMigration() {
2479
2641
  const runLocalMigrate = () => runOrReturnExitCode(() => (0, child_process_2.runNxArgvSync)(['_migrate', ...forwardedArgv], {
2480
2642
  stdio: ['inherit', 'inherit', 'inherit'],
2481
2643
  }));
2482
- if (process.env.NX_USE_LOCAL !== 'true' &&
2644
+ if (!(0, version_skew_guard_1.targetsExistingRun)(process.argv.slice(3)) &&
2645
+ process.env.NX_USE_LOCAL !== 'true' &&
2483
2646
  process.env.NX_MIGRATE_USE_LOCAL === undefined) {
2484
2647
  // The version spec mirrors nxCliPath's; keep the two in sync.
2485
2648
  const cliVersionSpec = process.env.NX_MIGRATE_CLI_VERSION || 'latest';
@@ -63,32 +63,29 @@ async function promptMultiMajorMigration(args) {
63
63
  let recommendedMarked = false;
64
64
  if (args.latestInCurrent) {
65
65
  choices.push({
66
- name: args.latestInCurrent,
67
- message: `Migrate to ${args.targetPackage}@${args.latestInCurrent} (latest in current major) [recommended]`,
66
+ value: args.latestInCurrent,
67
+ label: `Migrate to ${args.targetPackage}@${args.latestInCurrent} (latest in current major) [recommended]`,
68
68
  });
69
69
  recommendedMarked = true;
70
70
  }
71
71
  if (args.latestInNext) {
72
72
  choices.push({
73
- name: args.latestInNext,
74
- message: `Migrate to ${args.targetPackage}@${args.latestInNext} (next major)${recommendedMarked ? '' : ' [recommended]'}`,
73
+ value: args.latestInNext,
74
+ label: `Migrate to ${args.targetPackage}@${args.latestInNext} (next major)${recommendedMarked ? '' : ' [recommended]'}`,
75
75
  });
76
76
  }
77
77
  choices.push({
78
- name: args.target,
79
- message: `Migrate directly to ${args.targetPackage}@${args.target}`,
78
+ value: args.target,
79
+ label: `Migrate directly to ${args.targetPackage}@${args.target}`,
80
80
  });
81
81
  output_1.output.log({
82
82
  title: multiMajorHeader(args.targetPackage, args.installed, args.target),
83
83
  bodyLines: multiMajorBodyLines,
84
84
  });
85
- const { chosen } = await (0, safe_prompt_1.migratePrompt)({
86
- type: 'select',
87
- name: 'chosen',
85
+ return (0, safe_prompt_1.migrateChoice)({
88
86
  message: 'How would you like to proceed?',
89
87
  choices,
90
88
  });
91
- return chosen;
92
89
  }
93
90
  // Flag wins over env var; only the two literal values are honoured.
94
91
  function resolveMultiMajorMode(options) {
@@ -198,14 +198,10 @@ async function handleViolation(packageName, error, policy) {
198
198
  const blockedLine = ` ${packageName}@${resolved.version} (published ${formatPublishAge(resolved.publishedAt)})`;
199
199
  // pnpm prompts once for the whole run; remember an approval for later picks.
200
200
  if (!strictApprovalGranted) {
201
- const { approved } = await (0, safe_prompt_1.migratePrompt)([
202
- {
203
- name: 'approved',
204
- type: 'confirm',
205
- initial: false,
206
- message: `The following version does not meet the ${policy.sourceDescription} constraint:\n${blockedLine}\nInstall anyway and add it to minimumReleaseAgeExclude in pnpm-workspace.yaml?`,
207
- },
208
- ]);
201
+ const approved = await (0, safe_prompt_1.migrateConfirm)({
202
+ initial: false,
203
+ message: `The following version does not meet the ${policy.sourceDescription} constraint:\n${blockedLine}\nInstall anyway and add it to minimumReleaseAgeExclude in pnpm-workspace.yaml?`,
204
+ });
209
205
  if (!approved) {
210
206
  // Deny must surface as a violation: migrate.ts only rethrows
211
207
  // MinReleaseAgeViolationError, so a plain Error would silently fall back
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Lines are kept unjoined all the way here on purpose. Joining them and
3
+ * splitting them back turns an injected break into its own entry before this
4
+ * module sees it, indistinguishable from a line the caller meant to write, and
5
+ * nothing downstream can undo that.
6
+ */
7
+ export interface AgentMessage {
8
+ title: string;
9
+ bodyLines?: string[];
10
+ }
11
+ /**
12
+ * The safe form of a set of lines. Exported so a caller that needs the same
13
+ * text twice, once for a human and once inside a block payload, derives both
14
+ * from one array instead of sanitizing one copy and not the other.
15
+ */
16
+ export declare function safeLines(lines: readonly string[]): string[];
17
+ export declare function logToAgent(message: AgentMessage): void;
18
+ export declare function warnToAgent(message: AgentMessage): void;
19
+ export declare function emitStepBlock(runId: string, stepId: string, action: string, payload: object): void;
20
+ export declare function emitPromptBlock(migrationId: string, payload: object): void;