nx 23.2.0-beta.4 → 23.2.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/nx.js +1 -0
- package/dist/src/command-line/affected/affected.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +2 -2
- package/dist/src/command-line/init/init-v2.js +2 -2
- package/dist/src/command-line/migrate/agentic/definitions.js +2 -2
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +15 -19
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +19 -31
- package/dist/src/command-line/migrate/agentic/handoff.d.ts +4 -6
- package/dist/src/command-line/migrate/agentic/handoff.js +9 -8
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.d.ts +7 -12
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.js +7 -0
- package/dist/src/command-line/migrate/agentic/run-step.d.ts +10 -0
- package/dist/src/command-line/migrate/agentic/select.d.ts +10 -2
- package/dist/src/command-line/migrate/agentic/select.js +10 -2
- package/dist/src/command-line/migrate/agentic/types.d.ts +17 -3
- package/dist/src/command-line/migrate/agentic/types.js +26 -0
- package/dist/src/command-line/migrate/command-object.d.ts +3 -0
- package/dist/src/command-line/migrate/command-object.js +6 -1
- package/dist/src/command-line/migrate/execute-migration.d.ts +14 -9
- package/dist/src/command-line/migrate/execute-migration.js +82 -18
- package/dist/src/command-line/migrate/migrate-analytics.d.ts +7 -0
- package/dist/src/command-line/migrate/migrate-analytics.js +14 -0
- package/dist/src/command-line/migrate/migrate-commits.d.ts +32 -8
- package/dist/src/command-line/migrate/migrate-commits.js +77 -9
- package/dist/src/command-line/migrate/migrate-config.d.ts +11 -12
- package/dist/src/command-line/migrate/migrate-config.js +14 -14
- package/dist/src/command-line/migrate/migrate-output.d.ts +45 -7
- package/dist/src/command-line/migrate/migrate-output.js +52 -8
- package/dist/src/command-line/migrate/migrate-ui-api.d.ts +2 -1
- package/dist/src/command-line/migrate/migrate-ui-api.js +16 -7
- package/dist/src/command-line/migrate/migrate.d.ts +17 -68
- package/dist/src/command-line/migrate/migrate.js +411 -229
- package/dist/src/command-line/migrate/migration-shape.d.ts +8 -0
- package/dist/src/command-line/migrate/run/index.d.ts +2 -0
- package/dist/src/command-line/migrate/run/index.js +5 -0
- package/dist/src/command-line/migrate/run/util.d.ts +1 -0
- package/dist/src/command-line/migrate/run/util.js +16 -0
- package/dist/src/command-line/migrate/run/worker.d.ts +15 -0
- package/dist/src/command-line/migrate/run/worker.js +419 -0
- package/dist/src/command-line/migrate/run-migration-process.js +6 -5
- package/dist/src/command-line/migrate/sort-migrations.d.ts +16 -0
- package/dist/src/command-line/migrate/sort-migrations.js +32 -0
- package/dist/src/command-line/migrate/version-skew-guard.d.ts +58 -0
- package/dist/src/command-line/migrate/version-skew-guard.js +155 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/command-object.d.ts +2 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/command-object.js +16 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/start-nx-agents.d.ts +4 -0
- package/dist/src/command-line/nx-cloud/start-nx-agents/start-nx-agents.js +13 -0
- package/dist/src/command-line/nx-commands.js +26 -24
- package/dist/src/command-line/release/changelog.js +5 -0
- package/dist/src/command-line/release/utils/git.js +1 -1
- package/dist/src/command-line/release/utils/release-graph.d.ts +1 -0
- package/dist/src/command-line/release/utils/release-graph.js +15 -3
- package/dist/src/command-line/release/version/version-actions.d.ts +8 -0
- package/dist/src/command-line/release/version/version-actions.js +8 -0
- package/dist/src/command-line/release/version.js +9 -5
- package/dist/src/command-line/reset/reset.js +6 -1
- package/dist/src/command-line/run/run-one.js +1 -0
- package/dist/src/command-line/run-many/run-many.js +1 -0
- package/dist/src/config/misc-interfaces.d.ts +19 -7
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +45 -1
- package/dist/src/daemon/client/client.js +128 -32
- package/dist/src/daemon/client/daemon-socket-messenger.js +4 -0
- package/dist/src/daemon/message-types/daemon-message.d.ts +32 -0
- package/dist/src/daemon/message-types/daemon-message.js +25 -0
- package/dist/src/daemon/server/latest-nx.js +5 -2
- package/dist/src/daemon/server/server.js +22 -0
- package/dist/src/daemon/server/shutdown-utils.d.ts +5 -0
- package/dist/src/daemon/server/shutdown-utils.js +11 -4
- package/dist/src/daemon/socket-utils.d.ts +1 -0
- package/dist/src/daemon/socket-utils.js +24 -3
- package/dist/src/daemon/tmp-dir.d.ts +43 -3
- package/dist/src/daemon/tmp-dir.js +437 -15
- package/dist/src/devkit-internals.d.ts +92 -3
- package/dist/src/devkit-internals.js +189 -5
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.d.ts +5 -0
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +9 -2
- package/dist/src/generators/tree.d.ts +4 -2
- package/dist/src/native/index.d.ts +10 -0
- package/dist/src/native/index.js +71 -28
- package/dist/src/native/native-bindings.js +1 -0
- package/dist/src/native/native-file-cache-location.d.ts +17 -1
- package/dist/src/native/native-file-cache-location.js +86 -12
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/utilities/get-cloud-options.js +5 -2
- package/dist/src/nx-cloud/utilities/onboarding.js +5 -2
- package/dist/src/nx-cloud/utilities/url-shorten.d.ts +1 -4
- package/dist/src/nx-cloud/utilities/url-shorten.js +9 -8
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +14 -8
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +2 -0
- package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.js +2 -2
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +5 -2
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +18 -1
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +16 -3
- package/dist/src/project-graph/plugins/isolation/messaging.js +3 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +58 -8
- package/dist/src/project-graph/project-graph.js +20 -0
- package/dist/src/tasks-runner/life-cycles/performance-report.d.ts +12 -0
- package/dist/src/tasks-runner/life-cycles/performance-report.js +62 -3
- package/dist/src/tasks-runner/run-command.js +4 -0
- package/dist/src/utils/assert-workspace-validity.js +7 -2
- package/dist/src/utils/child-process.d.ts +31 -1
- package/dist/src/utils/child-process.js +103 -0
- package/dist/src/utils/ignore.d.ts +128 -1
- package/dist/src/utils/ignore.js +182 -12
- package/dist/src/utils/nx-tmp-dir.d.ts +18 -0
- package/dist/src/utils/nx-tmp-dir.js +40 -0
- package/dist/src/utils/owned-private-dir.d.ts +132 -0
- package/dist/src/utils/owned-private-dir.js +323 -0
- package/dist/src/utils/shell-quoting.d.ts +15 -0
- package/dist/src/utils/shell-quoting.js +35 -0
- package/dist/src/utils/wait-for-socket-connection.d.ts +11 -0
- package/dist/src/utils/wait-for-socket-connection.js +14 -8
- package/package.json +12 -12
|
@@ -4,13 +4,16 @@ exports.getNgCompatLayer = exports.MigrationImplementationMissingError = exports
|
|
|
4
4
|
exports.readPackageMigrationConfig = readPackageMigrationConfig;
|
|
5
5
|
exports.runInstall = runInstall;
|
|
6
6
|
exports.isNpmPeerDepsError = isNpmPeerDepsError;
|
|
7
|
+
exports.formatSingleMigrationRerunCommand = formatSingleMigrationRerunCommand;
|
|
7
8
|
exports.logNpmPeerDepsError = logNpmPeerDepsError;
|
|
9
|
+
exports.logSkippedPostMigrationInstall = logSkippedPostMigrationInstall;
|
|
8
10
|
exports.runNxOrAngularMigration = runNxOrAngularMigration;
|
|
9
11
|
exports.getStringifiedPackageJsonDeps = getStringifiedPackageJsonDeps;
|
|
10
12
|
exports.runNxMigration = runNxMigration;
|
|
11
13
|
exports.parseMigrationReturn = parseMigrationReturn;
|
|
12
14
|
exports.filterStrings = filterStrings;
|
|
13
15
|
exports.readMigrationCollection = readMigrationCollection;
|
|
16
|
+
exports.resolveDocumentationFileToWorkspacePath = resolveDocumentationFileToWorkspacePath;
|
|
14
17
|
exports.getImplementationPath = getImplementationPath;
|
|
15
18
|
exports.isAngularMigration = isAngularMigration;
|
|
16
19
|
const tslib_1 = require("tslib");
|
|
@@ -27,6 +30,7 @@ const package_manager_1 = require("../../utils/package-manager");
|
|
|
27
30
|
const output_1 = require("../../utils/output");
|
|
28
31
|
const fs_1 = require("fs");
|
|
29
32
|
const installation_directory_1 = require("../../utils/installation-directory");
|
|
33
|
+
const shell_quoting_1 = require("../../utils/shell-quoting");
|
|
30
34
|
const project_graph_1 = require("../../project-graph/project-graph");
|
|
31
35
|
const version_utils_1 = require("./version-utils");
|
|
32
36
|
function readPackageMigrationConfig(packageName, dir) {
|
|
@@ -55,7 +59,7 @@ function readPackageMigrationConfig(packageName, dir) {
|
|
|
55
59
|
};
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
|
-
function runInstall(nxWorkspaceRoot, phase = 'pre-migration') {
|
|
62
|
+
function runInstall(nxWorkspaceRoot, phase = 'pre-migration', rerunCommand) {
|
|
59
63
|
const cwd = nxWorkspaceRoot ?? process.cwd();
|
|
60
64
|
const packageManager = (0, package_manager_1.detectPackageManager)(cwd);
|
|
61
65
|
const pmCommands = (0, package_manager_1.getPackageManagerCommand)(packageManager, cwd);
|
|
@@ -92,7 +96,7 @@ function runInstall(nxWorkspaceRoot, phase = 'pre-migration') {
|
|
|
92
96
|
// (CLI migrate, `nx repair`, single-migration runner, etc.) surfaces
|
|
93
97
|
// it consistently. Top-level callers catch `NpmPeerDepsInstallError`
|
|
94
98
|
// and return a non-zero exit code without re-logging.
|
|
95
|
-
logNpmPeerDepsError(phase);
|
|
99
|
+
logNpmPeerDepsError(phase, rerunCommand);
|
|
96
100
|
reject(new NpmPeerDepsInstallError());
|
|
97
101
|
return;
|
|
98
102
|
}
|
|
@@ -124,7 +128,20 @@ function isNpmPeerDepsError(stderr) {
|
|
|
124
128
|
lowerStderr.includes('could not resolve dependency') ||
|
|
125
129
|
lowerStderr.includes('conflicting peer dependency'));
|
|
126
130
|
}
|
|
127
|
-
|
|
131
|
+
// The single-migration rerun command lands in copyable guidance (see
|
|
132
|
+
// `logNpmPeerDepsError` below), so quote ids a shell would split or expand.
|
|
133
|
+
// Single quotes stay literal in POSIX shells and PowerShell alike; double
|
|
134
|
+
// quotes would leave $-expansion active in both. The embedded-quote escape is
|
|
135
|
+
// the POSIX '\'' sequence, the one character PowerShell disagrees on (it wants
|
|
136
|
+
// ''). cmd.exe is knowingly not covered: it does not group on single quotes,
|
|
137
|
+
// and no quoting suppresses its %VAR% expansion.
|
|
138
|
+
function formatSingleMigrationRerunCommand(migrationId) {
|
|
139
|
+
const id = (0, shell_quoting_1.needsShellQuoting)(migrationId)
|
|
140
|
+
? `'${migrationId.replace(/'/g, String.raw `'\''`)}'`
|
|
141
|
+
: migrationId;
|
|
142
|
+
return `nx migrate --run-migration=${id}`;
|
|
143
|
+
}
|
|
144
|
+
function logNpmPeerDepsError(phase, rerunCommand = 'nx migrate --run-migrations') {
|
|
128
145
|
const peerDepsResolutionSteps = [
|
|
129
146
|
'Recommended approaches (in order of preference):',
|
|
130
147
|
'',
|
|
@@ -138,7 +155,7 @@ function logNpmPeerDepsError(phase) {
|
|
|
138
155
|
];
|
|
139
156
|
const manualInstallHint = [
|
|
140
157
|
'If you installed the dependencies manually, pass "--skip-install" to avoid re-installing them:',
|
|
141
|
-
|
|
158
|
+
` ${rerunCommand} --skip-install`,
|
|
142
159
|
];
|
|
143
160
|
if (phase === 'pre-migration') {
|
|
144
161
|
output_1.output.error({
|
|
@@ -146,8 +163,8 @@ function logNpmPeerDepsError(phase) {
|
|
|
146
163
|
bodyLines: [
|
|
147
164
|
...peerDepsResolutionSteps,
|
|
148
165
|
'',
|
|
149
|
-
'Once the conflicts are resolved, re-run the
|
|
150
|
-
|
|
166
|
+
'Once the conflicts are resolved, re-run the migration command:',
|
|
167
|
+
` ${rerunCommand}`,
|
|
151
168
|
'',
|
|
152
169
|
...manualInstallHint,
|
|
153
170
|
],
|
|
@@ -160,18 +177,27 @@ function logNpmPeerDepsError(phase) {
|
|
|
160
177
|
...peerDepsResolutionSteps,
|
|
161
178
|
'',
|
|
162
179
|
'Once the conflicts are resolved, run "npm install" to install the updated dependencies.',
|
|
163
|
-
'If the migration was interrupted before completing, re-run
|
|
164
|
-
|
|
180
|
+
'If the migration run was interrupted before completing, re-run it:',
|
|
181
|
+
` ${rerunCommand}`,
|
|
165
182
|
'',
|
|
166
183
|
...manualInstallHint,
|
|
167
184
|
],
|
|
168
185
|
});
|
|
169
186
|
}
|
|
170
187
|
}
|
|
188
|
+
function logSkippedPostMigrationInstall(root) {
|
|
189
|
+
const packageManager = (0, package_manager_1.detectPackageManager)(root);
|
|
190
|
+
const installCommand = (0, package_manager_1.getPackageManagerCommand)(packageManager, root).install;
|
|
191
|
+
output_1.output.warn({
|
|
192
|
+
title: 'Migrations updated your dependencies, but the install was skipped',
|
|
193
|
+
bodyLines: [`Run "${installCommand}" to install the updated dependencies.`],
|
|
194
|
+
});
|
|
195
|
+
}
|
|
171
196
|
class ChangedDepInstaller {
|
|
172
|
-
constructor(root, shouldSkipInstall = false) {
|
|
197
|
+
constructor(root, shouldSkipInstall = false, rerunCommand) {
|
|
173
198
|
this.root = root;
|
|
174
199
|
this.shouldSkipInstall = shouldSkipInstall;
|
|
200
|
+
this.rerunCommand = rerunCommand;
|
|
175
201
|
this._skippedInstall = false;
|
|
176
202
|
this.initialDeps = getStringifiedPackageJsonDeps(root);
|
|
177
203
|
}
|
|
@@ -185,7 +211,7 @@ class ChangedDepInstaller {
|
|
|
185
211
|
this._skippedInstall = true;
|
|
186
212
|
}
|
|
187
213
|
else {
|
|
188
|
-
await runInstall(this.root, 'post-migration');
|
|
214
|
+
await runInstall(this.root, 'post-migration', this.rerunCommand);
|
|
189
215
|
}
|
|
190
216
|
}
|
|
191
217
|
this.initialDeps = currentDeps;
|
|
@@ -197,6 +223,8 @@ async function runNxOrAngularMigration(root, migration, isVerbose, captureGenera
|
|
|
197
223
|
let changes = [];
|
|
198
224
|
let nextSteps = [];
|
|
199
225
|
let agentContext = [];
|
|
226
|
+
// Angular schematics have no return channel, so they can never waive it.
|
|
227
|
+
let skipAgentic = false;
|
|
200
228
|
let logs = '';
|
|
201
229
|
// Angular's `ngResult.changes` is synthesized from the schematic's
|
|
202
230
|
// DryRunEvent stream so Nx and Angular paths can share commit/validation
|
|
@@ -204,7 +232,8 @@ async function runNxOrAngularMigration(root, migration, isVerbose, captureGenera
|
|
|
204
232
|
let madeChanges = false;
|
|
205
233
|
logger_1.logger.info(pc.dim('→ Running generator…'));
|
|
206
234
|
if (!isAngularMigration(collection, migration.name)) {
|
|
207
|
-
({ nextSteps, changes, agentContext, logs } =
|
|
235
|
+
({ nextSteps, changes, agentContext, skipAgentic, logs } =
|
|
236
|
+
await runNxMigration(root, collectionPath, collection, migration.name, migration.version, captureGeneratorOutput));
|
|
208
237
|
madeChanges = changes.length > 0;
|
|
209
238
|
logger_1.logger.info(`Ran ${migration.name} from ${migration.package}`);
|
|
210
239
|
if (migration.description) {
|
|
@@ -213,7 +242,14 @@ async function runNxOrAngularMigration(root, migration, isVerbose, captureGenera
|
|
|
213
242
|
logger_1.logger.info('');
|
|
214
243
|
if (!madeChanges) {
|
|
215
244
|
logger_1.logger.info(`No changes were made\n`);
|
|
216
|
-
return {
|
|
245
|
+
return {
|
|
246
|
+
changes,
|
|
247
|
+
nextSteps,
|
|
248
|
+
agentContext,
|
|
249
|
+
skipAgentic,
|
|
250
|
+
logs,
|
|
251
|
+
madeChanges,
|
|
252
|
+
};
|
|
217
253
|
}
|
|
218
254
|
logger_1.logger.info('Changes:');
|
|
219
255
|
(0, tree_1.printChanges)(changes, ' ');
|
|
@@ -233,13 +269,20 @@ async function runNxOrAngularMigration(root, migration, isVerbose, captureGenera
|
|
|
233
269
|
logger_1.logger.info('');
|
|
234
270
|
if (!madeChanges) {
|
|
235
271
|
logger_1.logger.info(`No changes were made\n`);
|
|
236
|
-
return {
|
|
272
|
+
return {
|
|
273
|
+
changes,
|
|
274
|
+
nextSteps,
|
|
275
|
+
agentContext,
|
|
276
|
+
skipAgentic,
|
|
277
|
+
logs,
|
|
278
|
+
madeChanges,
|
|
279
|
+
};
|
|
237
280
|
}
|
|
238
281
|
logger_1.logger.info('Changes:');
|
|
239
282
|
ngResult.loggingQueue.forEach((log) => logger_1.logger.info(' ' + log));
|
|
240
283
|
logger_1.logger.info('');
|
|
241
284
|
}
|
|
242
|
-
return { changes, nextSteps, agentContext, logs, madeChanges };
|
|
285
|
+
return { changes, nextSteps, agentContext, skipAgentic, logs, madeChanges };
|
|
243
286
|
}
|
|
244
287
|
function getStringifiedPackageJsonDeps(root) {
|
|
245
288
|
try {
|
|
@@ -265,25 +308,31 @@ async function runNxMigration(root, collectionPath, collection, name, migrationV
|
|
|
265
308
|
else {
|
|
266
309
|
result = await fn(host, {});
|
|
267
310
|
}
|
|
268
|
-
const { nextSteps, agentContext } = parseMigrationReturn(result);
|
|
311
|
+
const { nextSteps, agentContext, skipAgentic } = parseMigrationReturn(result);
|
|
269
312
|
host.lock();
|
|
270
313
|
const changes = host.listChanges();
|
|
271
314
|
(0, tree_1.flushChanges)(root, changes);
|
|
272
|
-
return { changes, nextSteps, agentContext, logs };
|
|
315
|
+
return { changes, nextSteps, agentContext, skipAgentic, logs };
|
|
273
316
|
}
|
|
274
317
|
function parseMigrationReturn(value) {
|
|
275
318
|
if (Array.isArray(value)) {
|
|
276
|
-
return {
|
|
319
|
+
return {
|
|
320
|
+
nextSteps: filterStrings(value),
|
|
321
|
+
agentContext: [],
|
|
322
|
+
skipAgentic: false,
|
|
323
|
+
};
|
|
277
324
|
}
|
|
278
325
|
if (value && typeof value === 'object') {
|
|
279
326
|
const obj = value;
|
|
280
327
|
return {
|
|
281
328
|
nextSteps: filterStrings(obj.nextSteps),
|
|
282
329
|
agentContext: filterStrings(obj.agentContext),
|
|
330
|
+
// Strict, so a truthy non-boolean can't opt a migration out of its AI step.
|
|
331
|
+
skipAgentic: obj.skipAgentic === true,
|
|
283
332
|
};
|
|
284
333
|
}
|
|
285
334
|
// Catches `void`, mistakenly-returned generator callbacks, malformed values.
|
|
286
|
-
return { nextSteps: [], agentContext: [] };
|
|
335
|
+
return { nextSteps: [], agentContext: [], skipAgentic: false };
|
|
287
336
|
}
|
|
288
337
|
// Bucket-level tolerance: a single non-string entry shouldn't discard the
|
|
289
338
|
// whole `nextSteps` / `agentContext` array. Migration authors occasionally
|
|
@@ -303,6 +352,21 @@ function readMigrationCollection(packageName, root) {
|
|
|
303
352
|
collectionPath,
|
|
304
353
|
};
|
|
305
354
|
}
|
|
355
|
+
// Workspace-relative because the agent runs with cwd at the workspace root;
|
|
356
|
+
// absolute only for layouts that resolve outside it (hoisted/symlinked).
|
|
357
|
+
function resolveDocumentationFileToWorkspacePath(root, migrationsDir, documentation) {
|
|
358
|
+
let documentationFile;
|
|
359
|
+
try {
|
|
360
|
+
documentationFile = require.resolve(documentation, {
|
|
361
|
+
paths: [migrationsDir],
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
const relativePath = (0, path_1.relative)(root, documentationFile);
|
|
368
|
+
return relativePath.startsWith('..') ? documentationFile : relativePath;
|
|
369
|
+
}
|
|
306
370
|
function getImplementationPath(collection, collectionPath, name, migrationVersion) {
|
|
307
371
|
const g = collection.generators?.[name] || collection.schematics?.[name];
|
|
308
372
|
if (!g) {
|
|
@@ -67,5 +67,12 @@ export declare function reportMigrateRunError(opts: {
|
|
|
67
67
|
migrationCount?: number;
|
|
68
68
|
error?: unknown;
|
|
69
69
|
}): void;
|
|
70
|
+
/**
|
|
71
|
+
* Counts invocations, not completions: emitted as soon as the migration id
|
|
72
|
+
* resolves, while the worker can still stop before running anything.
|
|
73
|
+
*/
|
|
74
|
+
export declare function reportMigrateSingleMigrationInvocation(opts: {
|
|
75
|
+
migrationType: 'generator' | 'prompt' | 'hybrid';
|
|
76
|
+
}): void;
|
|
70
77
|
export declare function computeMajorsCrossed(installed: string | null | undefined, target: string | null | undefined): number | undefined;
|
|
71
78
|
export declare function safeReport(emit: () => void): void;
|
|
@@ -11,6 +11,7 @@ exports.reportMigrateRunStart = reportMigrateRunStart;
|
|
|
11
11
|
exports.hasMigrateRunStarted = hasMigrateRunStarted;
|
|
12
12
|
exports.reportMigrateRunComplete = reportMigrateRunComplete;
|
|
13
13
|
exports.reportMigrateRunError = reportMigrateRunError;
|
|
14
|
+
exports.reportMigrateSingleMigrationInvocation = reportMigrateSingleMigrationInvocation;
|
|
14
15
|
exports.computeMajorsCrossed = computeMajorsCrossed;
|
|
15
16
|
exports.safeReport = safeReport;
|
|
16
17
|
const semver_1 = require("semver");
|
|
@@ -180,6 +181,19 @@ function reportMigrateRunError(opts) {
|
|
|
180
181
|
});
|
|
181
182
|
});
|
|
182
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Counts invocations, not completions: emitted as soon as the migration id
|
|
186
|
+
* resolves, while the worker can still stop before running anything.
|
|
187
|
+
*/
|
|
188
|
+
function reportMigrateSingleMigrationInvocation(opts) {
|
|
189
|
+
safeReport(() => {
|
|
190
|
+
if (!analytics_1.customDimensions)
|
|
191
|
+
return;
|
|
192
|
+
(0, analytics_1.reportEvent)('migrate_single_migration_invocation', {
|
|
193
|
+
[analytics_1.customDimensions.promptChoice]: opts.migrationType,
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
}
|
|
183
197
|
// `_migrate` runs either from a temp install of the latest CLI or from the
|
|
184
198
|
// workspace-local installation; same signal as the run-phase re-dispatch
|
|
185
199
|
// check in migrate.ts.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ResolvedAgentic } from './agentic/types';
|
|
1
2
|
/**
|
|
2
3
|
* Discriminated result for `commitMigrationIfRequested`. Distinguishes the
|
|
3
4
|
* shapes the executor needs to react to:
|
|
@@ -23,21 +24,20 @@ export type CommitResult = {
|
|
|
23
24
|
status: 'disabled';
|
|
24
25
|
};
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
+
* `pendingMigrations` are listed in the commit body so a `git log -p` reader
|
|
28
|
+
* can see which earlier migrations' diffs this commit absorbed (their own
|
|
29
|
+
* commits failed and `git add -A` picked their working-tree state up too).
|
|
27
30
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* `git add -A` here captured their working-tree state too). Each entry is
|
|
32
|
-
* rendered as `<package>: <name>` for unambiguous attribution across
|
|
33
|
-
* packages.
|
|
31
|
+
* The default `failureGuidance` describes the classic loop's absorb-and-recap
|
|
32
|
+
* behavior; a caller with no later commit or recap to absorb the diff (the
|
|
33
|
+
* standalone single-migration worker) passes its own.
|
|
34
34
|
*/
|
|
35
35
|
export declare function commitMigrationIfRequested(root: string, migration: {
|
|
36
36
|
name: string;
|
|
37
37
|
}, shouldCreateCommits: boolean, commitPrefix: string, installDepsIfChanged: () => Promise<void>, pendingMigrations?: ReadonlyArray<{
|
|
38
38
|
package: string;
|
|
39
39
|
name: string;
|
|
40
|
-
}
|
|
40
|
+
}>, failureGuidance?: string): Promise<CommitResult>;
|
|
41
41
|
/**
|
|
42
42
|
* Commits any pre-existing working-tree state into a dedicated "checkpoint"
|
|
43
43
|
* commit before the first migration runs. Without this, the first migration's
|
|
@@ -48,3 +48,27 @@ export declare function commitMigrationIfRequested(root: string, migration: {
|
|
|
48
48
|
* the working tree is already clean.
|
|
49
49
|
*/
|
|
50
50
|
export declare function commitCheckpointBeforeMigrations(root: string, commitPrefix: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* `agenticHasDiffContext` gates the agent prompt: without per-migration commits
|
|
53
|
+
* to isolate a migration's diff, the prompt embeds a file list instead of
|
|
54
|
+
* pointing at git.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveCreateCommits(args: {
|
|
57
|
+
createCommits: boolean | undefined;
|
|
58
|
+
agenticKind: ResolvedAgentic['kind'];
|
|
59
|
+
isGitRepo: boolean;
|
|
60
|
+
commitPrefixIsCustom?: boolean;
|
|
61
|
+
}): {
|
|
62
|
+
effective: boolean;
|
|
63
|
+
agenticHasDiffContext: boolean;
|
|
64
|
+
warning?: string;
|
|
65
|
+
error?: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Callers gate this on commits being effective and on prompting being
|
|
69
|
+
* possible, so non-interactive runs (CI, `--no-interactive`) never reach here.
|
|
70
|
+
*/
|
|
71
|
+
export declare function confirmCommitsOnDefaultBranch(args: {
|
|
72
|
+
currentBranch: string | null;
|
|
73
|
+
defaultBranch: string | null;
|
|
74
|
+
}): Promise<boolean>;
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commitMigrationIfRequested = commitMigrationIfRequested;
|
|
4
4
|
exports.commitCheckpointBeforeMigrations = commitCheckpointBeforeMigrations;
|
|
5
|
+
exports.resolveCreateCommits = resolveCreateCommits;
|
|
6
|
+
exports.confirmCommitsOnDefaultBranch = confirmCommitsOnDefaultBranch;
|
|
5
7
|
const tslib_1 = require("tslib");
|
|
6
8
|
const pc = tslib_1.__importStar(require("picocolors"));
|
|
7
9
|
const git_utils_1 = require("../../utils/git-utils");
|
|
8
10
|
const logger_1 = require("../../utils/logger");
|
|
9
11
|
const output_1 = require("../../utils/output");
|
|
12
|
+
const safe_prompt_1 = require("./safe-prompt");
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
14
|
+
* `pendingMigrations` are listed in the commit body so a `git log -p` reader
|
|
15
|
+
* can see which earlier migrations' diffs this commit absorbed (their own
|
|
16
|
+
* commits failed and `git add -A` picked their working-tree state up too).
|
|
12
17
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `git add -A` here captured their working-tree state too). Each entry is
|
|
17
|
-
* rendered as `<package>: <name>` for unambiguous attribution across
|
|
18
|
-
* packages.
|
|
18
|
+
* The default `failureGuidance` describes the classic loop's absorb-and-recap
|
|
19
|
+
* behavior; a caller with no later commit or recap to absorb the diff (the
|
|
20
|
+
* standalone single-migration worker) passes its own.
|
|
19
21
|
*/
|
|
20
|
-
async function commitMigrationIfRequested(root, migration, shouldCreateCommits, commitPrefix, installDepsIfChanged, pendingMigrations = []) {
|
|
22
|
+
async function commitMigrationIfRequested(root, migration, shouldCreateCommits, commitPrefix, installDepsIfChanged, pendingMigrations = [], failureGuidance = 'The next successful commit will absorb it and reference this migration in its body; if no later commit lands, the end-of-run output will list this migration so you can commit or revert manually.') {
|
|
21
23
|
if (!shouldCreateCommits)
|
|
22
24
|
return { status: 'disabled' };
|
|
23
25
|
await installDepsIfChanged();
|
|
@@ -39,7 +41,7 @@ async function commitMigrationIfRequested(root, migration, shouldCreateCommits,
|
|
|
39
41
|
}
|
|
40
42
|
catch (err) {
|
|
41
43
|
const reason = err instanceof Error ? err.message : String(err);
|
|
42
|
-
logger_1.logger.info(pc.red(`Could not create a commit for ${migration.name}:\n${reason}\nThe migration's diff remains in the working tree; inspect with \`git status\` / \`git diff\` to review.
|
|
44
|
+
logger_1.logger.info(pc.red(`Could not create a commit for ${migration.name}:\n${reason}\nThe migration's diff remains in the working tree; inspect with \`git status\` / \`git diff\` to review. ${failureGuidance}`));
|
|
43
45
|
return { status: 'failed', reason };
|
|
44
46
|
}
|
|
45
47
|
}
|
|
@@ -100,3 +102,69 @@ function commitCheckpointBeforeMigrations(root, commitPrefix) {
|
|
|
100
102
|
});
|
|
101
103
|
}
|
|
102
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* `agenticHasDiffContext` gates the agent prompt: without per-migration commits
|
|
107
|
+
* to isolate a migration's diff, the prompt embeds a file list instead of
|
|
108
|
+
* pointing at git.
|
|
109
|
+
*/
|
|
110
|
+
function resolveCreateCommits(args) {
|
|
111
|
+
const { createCommits, agenticKind, isGitRepo, commitPrefixIsCustom } = args;
|
|
112
|
+
if (createCommits === true && !isGitRepo) {
|
|
113
|
+
return {
|
|
114
|
+
effective: false,
|
|
115
|
+
agenticHasDiffContext: false,
|
|
116
|
+
error: '`--create-commits` requires a git repository. Run `git init` first, or omit the flag.',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (agenticKind === 'enabled') {
|
|
120
|
+
if (createCommits === false) {
|
|
121
|
+
return {
|
|
122
|
+
effective: false,
|
|
123
|
+
agenticHasDiffContext: false,
|
|
124
|
+
warning: "--no-create-commits was passed alongside --agentic. Without per-migration commits, the agent can't isolate the current migration's changes from earlier migrations in this run. Drop --no-create-commits for accurate per-migration review." +
|
|
125
|
+
(commitPrefixIsCustom
|
|
126
|
+
? ' Note: the custom --commit-prefix value will have no effect because commits are disabled.'
|
|
127
|
+
: ''),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// Not an error like the explicit `--create-commits` branch above: the
|
|
131
|
+
// agentic default was never asked for, so degrade instead.
|
|
132
|
+
if (!isGitRepo) {
|
|
133
|
+
return {
|
|
134
|
+
effective: false,
|
|
135
|
+
agenticHasDiffContext: false,
|
|
136
|
+
warning: '`--agentic` enables per-migration commits by default, but the workspace is not a git repository. Continuing without commits, so the agent will not receive per-file diff context. Run `git init` to enable.' +
|
|
137
|
+
(commitPrefixIsCustom
|
|
138
|
+
? ' The custom --commit-prefix value will have no effect.'
|
|
139
|
+
: ''),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return { effective: true, agenticHasDiffContext: true };
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
effective: createCommits === true,
|
|
146
|
+
agenticHasDiffContext: false,
|
|
147
|
+
warning: commitPrefixIsCustom && createCommits !== true
|
|
148
|
+
? 'A custom migrate commit prefix is configured, but commits are not enabled for this run, so it has no effect. Set `migrate.createCommits` to `true` (or pass `--create-commits`) to create a commit per migration.'
|
|
149
|
+
: undefined,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Callers gate this on commits being effective and on prompting being
|
|
154
|
+
* possible, so non-interactive runs (CI, `--no-interactive`) never reach here.
|
|
155
|
+
*/
|
|
156
|
+
async function confirmCommitsOnDefaultBranch(args) {
|
|
157
|
+
const { currentBranch, defaultBranch } = args;
|
|
158
|
+
if (!currentBranch || !defaultBranch || currentBranch !== defaultBranch) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
const { proceed } = await (0, safe_prompt_1.migratePrompt)([
|
|
162
|
+
{
|
|
163
|
+
name: 'proceed',
|
|
164
|
+
type: 'confirm',
|
|
165
|
+
message: `You're on the default branch '${currentBranch}'. nx migrate will create a commit for each migration on this branch. Continue?`,
|
|
166
|
+
initial: false,
|
|
167
|
+
},
|
|
168
|
+
]);
|
|
169
|
+
return proceed;
|
|
170
|
+
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import type { NxMigrateConfiguration } from '../../config/nx-json';
|
|
2
2
|
import { type MigrateArgs } from './command-object';
|
|
3
3
|
/**
|
|
4
|
-
* Overlays `nx.json` `migrate` defaults onto the raw
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Overlays `nx.json` `migrate` defaults onto the raw CLI args: a CLI flag wins,
|
|
5
|
+
* then `nx.json`, then the built-in default. Returns a new args object; the
|
|
6
|
+
* input is not mutated.
|
|
7
7
|
*
|
|
8
|
-
* Phase-aware
|
|
9
|
-
*
|
|
10
|
-
* `
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* Phase-aware so each option is only filled where it is consumed, and so a
|
|
9
|
+
* config value never trips the mutually-exclusive-flag guards in
|
|
10
|
+
* `parseMigrationsOptions`: `include` and `multiMajorMode` in the generate
|
|
11
|
+
* phase only, `agentic` / `validate` / `createCommits` / `commitPrefix` when
|
|
12
|
+
* running the whole migrations file or a single migration.
|
|
13
13
|
*
|
|
14
|
-
* `include` is carried as `includeFromConfig`
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* unaffected.
|
|
14
|
+
* `include` is carried as `includeFromConfig` so it is never mistaken for an
|
|
15
|
+
* explicit `--include`: `resolveInclude` applies it only when the resolved
|
|
16
|
+
* target supports optional updates.
|
|
18
17
|
*/
|
|
19
18
|
export declare function applyNxJsonMigrateDefaults(args: MigrateArgs, migrateConfig: NxMigrateConfiguration | undefined, env?: NodeJS.ProcessEnv): MigrateArgs;
|
|
20
19
|
/**
|
|
@@ -6,20 +6,19 @@ const cli_args_1 = require("./agentic/cli-args");
|
|
|
6
6
|
const command_object_1 = require("./command-object");
|
|
7
7
|
const MULTI_MAJOR_MODE_ENV = 'NX_MULTI_MAJOR_MODE';
|
|
8
8
|
/**
|
|
9
|
-
* Overlays `nx.json` `migrate` defaults onto the raw
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Overlays `nx.json` `migrate` defaults onto the raw CLI args: a CLI flag wins,
|
|
10
|
+
* then `nx.json`, then the built-in default. Returns a new args object; the
|
|
11
|
+
* input is not mutated.
|
|
12
12
|
*
|
|
13
|
-
* Phase-aware
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Phase-aware so each option is only filled where it is consumed, and so a
|
|
14
|
+
* config value never trips the mutually-exclusive-flag guards in
|
|
15
|
+
* `parseMigrationsOptions`: `include` and `multiMajorMode` in the generate
|
|
16
|
+
* phase only, `agentic` / `validate` / `createCommits` / `commitPrefix` when
|
|
17
|
+
* running the whole migrations file or a single migration.
|
|
18
18
|
*
|
|
19
|
-
* `include` is carried as `includeFromConfig`
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* unaffected.
|
|
19
|
+
* `include` is carried as `includeFromConfig` so it is never mistaken for an
|
|
20
|
+
* explicit `--include`: `resolveInclude` applies it only when the resolved
|
|
21
|
+
* target supports optional updates.
|
|
23
22
|
*/
|
|
24
23
|
function applyNxJsonMigrateDefaults(args, migrateConfig, env = process.env) {
|
|
25
24
|
if (!migrateConfig) {
|
|
@@ -29,7 +28,8 @@ function applyNxJsonMigrateDefaults(args, migrateConfig, env = process.env) {
|
|
|
29
28
|
// `--run-migrations` with no value is normalized to '' by yargs, so a defined
|
|
30
29
|
// (even empty-string) value means we're in the run-migrations phase.
|
|
31
30
|
const isRunMigrations = merged.runMigrations !== undefined;
|
|
32
|
-
|
|
31
|
+
const isSingleMigration = merged.runMigration !== undefined;
|
|
32
|
+
if (isRunMigrations || isSingleMigration) {
|
|
33
33
|
if (merged.createCommits === undefined &&
|
|
34
34
|
migrateConfig.createCommits !== undefined) {
|
|
35
35
|
assertType(migrateConfig.createCommits, 'boolean', 'createCommits');
|
|
@@ -53,7 +53,7 @@ function applyNxJsonMigrateDefaults(args, migrateConfig, env = process.env) {
|
|
|
53
53
|
merged.validate = migrateConfig.validate;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
if (!isRunMigrations && !isSingleMigration) {
|
|
57
57
|
if (merged.include === undefined && migrateConfig.include !== undefined) {
|
|
58
58
|
assertOneOf(migrateConfig.include, command_object_1.MIGRATE_INCLUDE_VALUES, 'include');
|
|
59
59
|
merged.includeFromConfig = migrateConfig.include;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `→` start · `✓` success · `✗` failure · `↷` skipped · `ℹ` info · `─` boundary
|
|
2
|
+
* Pure presentation helpers for the migrate run phase (`--run-migrations` and
|
|
3
|
+
* the single-migration worker). Shared glyph vocabulary:
|
|
4
|
+
* `→` start, `✓` success, `✗` failure, `↷` skipped, `ℹ` info, `─` boundary
|
|
6
5
|
*
|
|
7
6
|
* Inputs are typed structurally (e.g. `{ name: string }[]`) so this module
|
|
8
|
-
* stays decoupled from
|
|
7
|
+
* stays decoupled from the migration executor in migrate.ts.
|
|
9
8
|
*/
|
|
10
9
|
/**
|
|
11
10
|
* Some agent TUIs (codex, opencode) don't fully reset their cursor / SGR state
|
|
@@ -24,6 +23,22 @@ export declare function logMigrationBoundary(index: number, total: number, pkg:
|
|
|
24
23
|
* ✓ <label>[ (<sha>)]: <summary>
|
|
25
24
|
*/
|
|
26
25
|
export declare function logAgenticSuccessOutcome(label: string, sha: string | null, summary: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Logs the skip line for a migration that waived its AI step through
|
|
28
|
+
* `skipAgentic`, plus a verbose note for any `agentContext` the waiver
|
|
29
|
+
* dropped. A hybrid waives its paired prompt; a generator-only migration
|
|
30
|
+
* waives the validation pass, so callers must reach here only once they know
|
|
31
|
+
* one was on the table. Under `inside-agent` only a hybrid can, so the
|
|
32
|
+
* hand-off dropped alongside is always a prompt's; a waived generator-only
|
|
33
|
+
* migration keeps its own. The note is author-facing, hence `--verbose`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function logWaivedAgenticStep(migration: {
|
|
36
|
+
package: string;
|
|
37
|
+
name: string;
|
|
38
|
+
prompt?: string;
|
|
39
|
+
implementation?: string;
|
|
40
|
+
factory?: string;
|
|
41
|
+
}, agentContext: string[]): void;
|
|
27
42
|
/**
|
|
28
43
|
* Per-migration outcome record consumed by the failure recap. One entry is
|
|
29
44
|
* appended per iteration that returned without throwing; the failing migration
|
|
@@ -80,6 +95,13 @@ export type CommitState = {
|
|
|
80
95
|
* means the migration threw before completing — the executor's catch block
|
|
81
96
|
* records it so the recap can list it under retained-state alongside any
|
|
82
97
|
* other migrations whose commits never landed.
|
|
98
|
+
*
|
|
99
|
+
* `waivedAgenticStep` is set when the migration returned `skipAgentic: true`
|
|
100
|
+
* and something was actually waived: a hybrid's prompt, which is owed in every
|
|
101
|
+
* agentic mode, or a generator-only migration's validation step, only when it
|
|
102
|
+
* would have run. Recorded here rather than counted in the executor so the
|
|
103
|
+
* success tally and the failure recap derive the same number from the same
|
|
104
|
+
* records instead of threading a counter through both.
|
|
83
105
|
*/
|
|
84
106
|
export type MigrationOutcome = {
|
|
85
107
|
migration: {
|
|
@@ -89,6 +111,7 @@ export type MigrationOutcome = {
|
|
|
89
111
|
status: 'completed';
|
|
90
112
|
kind: MigrationOutcomeKind;
|
|
91
113
|
commit: CommitState;
|
|
114
|
+
waivedAgenticStep?: boolean;
|
|
92
115
|
} | {
|
|
93
116
|
migration: {
|
|
94
117
|
package: string;
|
|
@@ -106,6 +129,18 @@ export type MigrationOutcome = {
|
|
|
106
129
|
* counted because the absorbing commit's record already contributes one.
|
|
107
130
|
*/
|
|
108
131
|
export declare function countLandedCommits(outcomes: ReadonlyArray<MigrationOutcome>): number;
|
|
132
|
+
/**
|
|
133
|
+
* Counts the migrations that waived the AI step they would otherwise have
|
|
134
|
+
* run. Shared by the success tally and the failure recap so the two can't
|
|
135
|
+
* report different numbers.
|
|
136
|
+
*/
|
|
137
|
+
export declare function countWaivedAgenticSteps(outcomes: ReadonlyArray<MigrationOutcome>): number;
|
|
138
|
+
/**
|
|
139
|
+
* The recap phrase for waived AI steps. "not needed" rather than
|
|
140
|
+
* "skipped"/"deferred", which both recaps reserve for work the user still
|
|
141
|
+
* owes.
|
|
142
|
+
*/
|
|
143
|
+
export declare function formatWaivedAgenticSteps(count: number): string;
|
|
109
144
|
/**
|
|
110
145
|
* Migrations whose own commit attempt failed and whose diff was never
|
|
111
146
|
* absorbed by a later commit. Surfaces what the user has to commit or
|
|
@@ -144,17 +179,20 @@ export declare function logFailureRecap(opts: {
|
|
|
144
179
|
* emitting a misleading `0 prompt migrations skipped.` line.
|
|
145
180
|
*
|
|
146
181
|
* Rule (kept coherent across every scenario):
|
|
147
|
-
* - When at least one migration was applied: `<N> migrations applied, <K> commits created[, <D> prompt migrations <skipped|deferred>]`.
|
|
182
|
+
* - When at least one migration was applied: `<N> migrations applied, <K> commits created[, <D> prompt migrations <skipped|deferred>][, <W> AI steps not needed]`.
|
|
148
183
|
* The `<K> commits created` part stays even at 0 — it tells the reader work
|
|
149
184
|
* was applied but not committed (the J4/J8 information made explicit).
|
|
150
185
|
* - When zero migrations were applied but some prompt halves were
|
|
151
|
-
* skipped/deferred: `<D> prompt migrations <skipped|deferred>` only.
|
|
186
|
+
* skipped/deferred: `<D> prompt migrations <skipped|deferred>` only. Waiving
|
|
187
|
+
* never adds to `skippedPromptsCount`, so `appliedCount` is non-zero whenever
|
|
188
|
+
* `waivedAgenticStepsCount` is, and this branch can't be reached with one.
|
|
152
189
|
* - When zero of either: no body line.
|
|
153
190
|
*/
|
|
154
191
|
export declare function buildTallyBodyLine(opts: {
|
|
155
192
|
appliedCount: number;
|
|
156
193
|
committedShasCount: number;
|
|
157
194
|
skippedPromptsCount: number;
|
|
195
|
+
waivedAgenticStepsCount: number;
|
|
158
196
|
insideAgent: boolean;
|
|
159
197
|
}): string | null;
|
|
160
198
|
/**
|