@prisma-next/cli 0.12.0-dev.76 → 0.12.0-dev.78

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/cli.mjs CHANGED
@@ -7,15 +7,15 @@ import { createDbSchemaCommand } from "./commands/db-schema.mjs";
7
7
  import { createDbSignCommand } from "./commands/db-sign.mjs";
8
8
  import { createDbUpdateCommand } from "./commands/db-update.mjs";
9
9
  import { t as createDbVerifyCommand } from "./db-verify-C24FKhb7.mjs";
10
- import { t as createMigrationListCommand } from "./migration-list-CihF6w5z.mjs";
10
+ import { t as createMigrationListCommand } from "./migration-list-DlJJ_38Z.mjs";
11
11
  import { createMigrateCommand } from "./commands/migrate.mjs";
12
12
  import { t as createMigrationCheckCommand } from "./migration-check-VwM8xCZV.mjs";
13
13
  import { createMigrationGraphCommand } from "./commands/migration-graph.mjs";
14
- import { t as createMigrationLogCommand } from "./migration-log-B75IArji.mjs";
14
+ import { t as createMigrationLogCommand } from "./migration-log-CG0qQAFm.mjs";
15
15
  import { createMigrationNewCommand } from "./commands/migration-new.mjs";
16
16
  import { t as createMigrationPlanCommand } from "./migration-plan-z5Ing-TD.mjs";
17
17
  import { createMigrationShowCommand } from "./commands/migration-show.mjs";
18
- import { r as createMigrationStatusCommand } from "./migration-status-CSVe6ZlD.mjs";
18
+ import { r as createMigrationStatusCommand } from "./migration-status-CD-LC2Ip.mjs";
19
19
  import { createRefCommand } from "./commands/ref.mjs";
20
20
  import { t as createTelemetryCommand } from "./telemetry-BIM4beEO.mjs";
21
21
  import { Command } from "commander";
@@ -24,7 +24,7 @@ import { ensureInstallationId, readUserConfig, resolveGating, runTelemetry, user
24
24
  import { distance } from "closest-match";
25
25
  import { fileURLToPath } from "node:url";
26
26
  //#region package.json
27
- var version = "0.12.0-dev.76";
27
+ var version = "0.12.0-dev.78";
28
28
  //#endregion
29
29
  //#region src/commands/init/templates/code-templates.ts
30
30
  function targetPackageName(target) {
@@ -5,8 +5,8 @@ import { n as planMemberPath, t as createControlClient } from "../client-CJzuo5w
5
5
  import { a as refuseContractSpaceIntegrity, i as loadContractSpaceAggregateForCli, n as buildReadAggregate } from "../contract-space-aggregate-loader-ClI1KN6d.mjs";
6
6
  import { i as readContractIR, r as executeRefAdvancement } from "../ref-advancement-BkXlikCA.mjs";
7
7
  import { t as mapContractAtError } from "../contract-at-errors-CFXsstzm.mjs";
8
- import { d as highlightFromEdgeAnnotations, f as indentMigrationGraphTreeBlock, h as buildGrid, i as formatOnPathMigrationRow, m as buildMigrationGraphRows, n as computeMaxDirNameWidth, r as renderMigrationGraphCommand, t as computeLabelColumn } from "../migration-graph-command-render-BAOzyYF6.mjs";
9
- import { r as listRefsByContractHash } from "../migration-list-CihF6w5z.mjs";
8
+ import { d as highlightFromEdgeAnnotations, f as indentMigrationGraphTreeBlock, h as buildGrid, i as formatOnPathMigrationRow, m as buildMigrationGraphRows, n as computeMaxDirNameWidth, r as renderMigrationGraphCommand, t as computeLabelColumn } from "../migration-graph-command-render-CEez7YUK.mjs";
9
+ import { r as listRefsByContractHash } from "../migration-list-DlJJ_38Z.mjs";
10
10
  import { Command } from "commander";
11
11
  import { ifDefined } from "@prisma-next/utils/defined";
12
12
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -1,8 +1,8 @@
1
1
  import { t as loadConfig } from "../config-loader-p9JMrekQ.mjs";
2
2
  import { A as formatStyledHeader, _ as createTerminalUI, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "../command-helpers-DGMvGBeX.mjs";
3
3
  import { n as buildReadAggregate } from "../contract-space-aggregate-loader-ClI1KN6d.mjs";
4
- import { a as renderMigrationGraphLegend, f as indentMigrationGraphTreeBlock, l as computeGlobalMaxDirNameWidth, p as renderMigrationGraphSpaceTree, u as computeGlobalMaxEdgeTreePrefixWidth } from "../migration-graph-command-render-BAOzyYF6.mjs";
5
- import { c as validateLegendOptions, i as migrationSpaceListEntriesFromAggregate, o as runMigrationList, r as listRefsByContractHash, s as shouldShowLegend } from "../migration-list-CihF6w5z.mjs";
4
+ import { a as renderMigrationGraphLegend, f as indentMigrationGraphTreeBlock, l as computeGlobalMaxDirNameWidth, p as renderMigrationGraphSpaceTree, u as computeGlobalMaxEdgeTreePrefixWidth } from "../migration-graph-command-render-CEez7YUK.mjs";
5
+ import { c as validateLegendOptions, i as migrationSpaceListEntriesFromAggregate, o as runMigrationList, r as listRefsByContractHash, s as shouldShowLegend } from "../migration-list-DlJJ_38Z.mjs";
6
6
  import { Command } from "commander";
7
7
  import { ifDefined } from "@prisma-next/utils/defined";
8
8
  import { ok } from "@prisma-next/utils/result";
@@ -1,2 +1,2 @@
1
- import { a as renderMigrationListHumanOutput, i as migrationSpaceListEntriesFromAggregate, n as executeMigrationListCommand, o as runMigrationList, r as listRefsByContractHash, t as createMigrationListCommand } from "../migration-list-CihF6w5z.mjs";
1
+ import { a as renderMigrationListHumanOutput, i as migrationSpaceListEntriesFromAggregate, n as executeMigrationListCommand, o as runMigrationList, r as listRefsByContractHash, t as createMigrationListCommand } from "../migration-list-DlJJ_38Z.mjs";
2
2
  export { createMigrationListCommand, executeMigrationListCommand, listRefsByContractHash, migrationSpaceListEntriesFromAggregate, renderMigrationListHumanOutput, runMigrationList };
@@ -1,2 +1,2 @@
1
- import { n as executeMigrationLogCommand, t as createMigrationLogCommand } from "../migration-log-B75IArji.mjs";
1
+ import { n as executeMigrationLogCommand, t as createMigrationLogCommand } from "../migration-log-CG0qQAFm.mjs";
2
2
  export { createMigrationLogCommand, executeMigrationLogCommand };
@@ -1,3 +1,3 @@
1
1
  import { n as migrationStatusJsonResultSchema } from "../schemas-KhXMzNA_.mjs";
2
- import { a as formatStatusHumanOutput, i as executeMigrationStatusCommand, n as buildStatusHeadline, o as formatStatusSummary, r as createMigrationStatusCommand, t as buildNoPathSummary } from "../migration-status-CSVe6ZlD.mjs";
2
+ import { a as formatStatusHumanOutput, i as executeMigrationStatusCommand, n as buildStatusHeadline, o as formatStatusSummary, r as createMigrationStatusCommand, t as buildNoPathSummary } from "../migration-status-CD-LC2Ip.mjs";
3
3
  export { buildNoPathSummary, buildStatusHeadline, createMigrationStatusCommand, executeMigrationStatusCommand, formatStatusHumanOutput, formatStatusSummary, migrationStatusJsonResultSchema };
@@ -96,9 +96,10 @@ function renderCell(cell, colorEnabled, alphabet) {
96
96
  * Render a single grid row to a coloured string. A completely empty row returns
97
97
  * the empty string (the row is NOT dropped) so callers that pair grid rows with
98
98
  * an external per-row label list keep a 1:1 index correspondence. `renderGrid`
99
- * itself drops empty rows for its standalone output.
99
+ * itself drops empty rows for its standalone output (but preserves separator rows).
100
100
  */
101
101
  function renderGridRow(row, opts = {}) {
102
+ if (row[0]?.separator === true) return "";
102
103
  let lastNonEmpty = -1;
103
104
  for (let i = row.length - 1; i >= 0; i--) {
104
105
  const cell = row[i];
@@ -143,8 +144,6 @@ function padFromHashColumn(text, width) {
143
144
  * inbound migration rows — in display order (tips first, then roots).
144
145
  */
145
146
  function buildLaneAssignment(nodes, edges) {
146
- const allNodes = /* @__PURE__ */ new Set();
147
- for (const n of nodes) if (n !== null) allNodes.add(n);
148
147
  const fwdEdges = edges.filter((e) => e.kind === "forward" && e.from !== e.to);
149
148
  const outbound = /* @__PURE__ */ new Map();
150
149
  const inbound = /* @__PURE__ */ new Map();
@@ -158,13 +157,22 @@ function buildLaneAssignment(nodes, edges) {
158
157
  }
159
158
  for (const list of outbound.values()) list.sort((a, b) => a.dirName.localeCompare(b.dirName));
160
159
  for (const list of inbound.values()) list.sort((a, b) => a.dirName.localeCompare(b.dirName));
160
+ const components = [];
161
+ let current = [];
162
+ for (const n of nodes) if (n === null) {
163
+ if (current.length > 0) components.push(current);
164
+ current = [];
165
+ } else current.push(n);
166
+ if (current.length > 0) components.push(current);
167
+ const allNodes = /* @__PURE__ */ new Set();
168
+ for (const n of nodes) if (n !== null) allNodes.add(n);
161
169
  const nodeRank = /* @__PURE__ */ new Map();
162
170
  for (const n of allNodes) nodeRank.set(n, 0);
163
171
  for (let pass = 0; pass < allNodes.size; pass++) {
164
172
  let changed = false;
165
- for (const [from, edges] of outbound) {
173
+ for (const [from, es] of outbound) {
166
174
  const base = nodeRank.get(from) ?? 0;
167
- for (const e of edges) {
175
+ for (const e of es) {
168
176
  const next = base + 1;
169
177
  if (next > (nodeRank.get(e.to) ?? 0)) {
170
178
  nodeRank.set(e.to, next);
@@ -175,60 +183,117 @@ function buildLaneAssignment(nodes, edges) {
175
183
  if (!changed) break;
176
184
  }
177
185
  const nodeLane = /* @__PURE__ */ new Map();
178
- let nextLane = 0;
179
- const roots = [];
180
- for (const n of allNodes) if ((inbound.get(n) ?? []).length === 0) roots.push(n);
181
- roots.sort((a, b) => {
182
- if (a === EMPTY_CONTRACT_HASH) return -1;
183
- if (b === EMPTY_CONTRACT_HASH) return 1;
184
- return a.localeCompare(b);
185
- });
186
- const bfsQueue = [];
187
- for (const root of roots) if (!nodeLane.has(root)) {
188
- nodeLane.set(root, nextLane++);
189
- bfsQueue.push({
190
- node: root,
191
- lane: nodeLane.get(root)
186
+ const edgeLane = /* @__PURE__ */ new Map();
187
+ let totalLanes = 0;
188
+ for (const componentNodes of components) {
189
+ const componentSet = new Set(componentNodes);
190
+ let nextLane = 0;
191
+ const roots = [];
192
+ for (const n of componentNodes) if ((inbound.get(n) ?? []).length === 0) roots.push(n);
193
+ roots.sort((a, b) => {
194
+ if (a === EMPTY_CONTRACT_HASH) return -1;
195
+ if (b === EMPTY_CONTRACT_HASH) return 1;
196
+ return a.localeCompare(b);
192
197
  });
193
- }
194
- let head = 0;
195
- while (head < bfsQueue.length) {
196
- const { node, lane } = bfsQueue[head++];
197
- const children = outbound.get(node) ?? [];
198
- let first = true;
199
- for (const childEdge of children) {
200
- const child = childEdge.to;
201
- if (!nodeLane.has(child)) {
202
- const childLane = first ? lane : nextLane++;
203
- nodeLane.set(child, childLane);
204
- bfsQueue.push({
205
- node: child,
206
- lane: childLane
207
- });
198
+ const bfsQueue = [];
199
+ for (const root of roots) if (!nodeLane.has(root)) {
200
+ nodeLane.set(root, nextLane++);
201
+ bfsQueue.push({
202
+ node: root,
203
+ lane: nodeLane.get(root)
204
+ });
205
+ }
206
+ let head = 0;
207
+ while (head < bfsQueue.length) {
208
+ const { node, lane } = bfsQueue[head++];
209
+ const children = outbound.get(node) ?? [];
210
+ let first = true;
211
+ for (const childEdge of children) {
212
+ const child = childEdge.to;
213
+ if (!componentSet.has(child)) continue;
214
+ if (!nodeLane.has(child)) {
215
+ const childLane = first ? lane : nextLane++;
216
+ nodeLane.set(child, childLane);
217
+ bfsQueue.push({
218
+ node: child,
219
+ lane: childLane
220
+ });
221
+ edgeLane.set(childEdge.migrationHash, childLane);
222
+ } else edgeLane.set(childEdge.migrationHash, Math.max(lane, nodeLane.get(child)));
223
+ first = false;
224
+ }
225
+ }
226
+ for (const n of componentNodes) if (!nodeLane.has(n)) nodeLane.set(n, nextLane++);
227
+ for (const n of componentNodes) {
228
+ const parents = inbound.get(n);
229
+ if (!parents || parents.length <= 1) continue;
230
+ let trunkParent = parents[0].from;
231
+ let trunkRank = nodeRank.get(trunkParent) ?? 0;
232
+ let trunkLane = nodeLane.get(trunkParent) ?? 0;
233
+ for (let i = 1; i < parents.length; i++) {
234
+ const parent = parents[i].from;
235
+ const rank = nodeRank.get(parent) ?? 0;
236
+ const lane = nodeLane.get(parent) ?? 0;
237
+ if (rank > trunkRank || rank === trunkRank && lane < trunkLane) {
238
+ trunkParent = parent;
239
+ trunkRank = rank;
240
+ trunkLane = lane;
241
+ }
242
+ }
243
+ const trunkParentLane = nodeLane.get(trunkParent) ?? 0;
244
+ const currentNodeLane = nodeLane.get(n) ?? 0;
245
+ if (currentNodeLane === trunkParentLane) continue;
246
+ nodeLane.set(n, trunkParentLane);
247
+ for (const parentEdge of parents) if (parentEdge.from === trunkParent) edgeLane.set(parentEdge.migrationHash, trunkParentLane);
248
+ const bfsDescendants = [n];
249
+ let descHead = 0;
250
+ while (descHead < bfsDescendants.length) {
251
+ const current = bfsDescendants[descHead++];
252
+ const children = outbound.get(current) ?? [];
253
+ for (const childEdge of children) {
254
+ const child = childEdge.to;
255
+ if (!componentSet.has(child)) continue;
256
+ if ((nodeLane.get(child) ?? 0) !== currentNodeLane) continue;
257
+ nodeLane.set(child, trunkParentLane);
258
+ const existingEdgeLane = edgeLane.get(childEdge.migrationHash);
259
+ if (existingEdgeLane !== void 0 && existingEdgeLane === currentNodeLane) edgeLane.set(childEdge.migrationHash, trunkParentLane);
260
+ bfsDescendants.push(child);
261
+ }
208
262
  }
209
- first = false;
210
263
  }
264
+ if (nextLane > totalLanes) totalLanes = nextLane;
211
265
  }
212
- for (const n of allNodes) if (!nodeLane.has(n)) nodeLane.set(n, nextLane++);
213
266
  return {
214
267
  nodeLane,
215
268
  nodeRank,
216
- numLanes: nextLane
269
+ edgeLane,
270
+ numLanes: totalLanes
217
271
  };
218
272
  }
219
273
  function computeDisplayOrder(nodes, nodeLane, nodeRank) {
220
274
  const seen = /* @__PURE__ */ new Set();
221
275
  const result = [];
276
+ let componentBuffer = [];
277
+ function flushComponent() {
278
+ componentBuffer.sort((a, b) => b.rank - a.rank || a.lane - b.lane);
279
+ for (const d of componentBuffer) result.push(d);
280
+ componentBuffer = [];
281
+ }
222
282
  for (const n of nodes) {
223
- if (n === null || seen.has(n)) continue;
283
+ if (n === null) {
284
+ flushComponent();
285
+ result.push(null);
286
+ continue;
287
+ }
288
+ if (seen.has(n)) continue;
224
289
  seen.add(n);
225
- result.push({
290
+ componentBuffer.push({
226
291
  hash: n,
227
292
  lane: nodeLane.get(n) ?? 0,
228
293
  rank: nodeRank.get(n) ?? 0
229
294
  });
230
295
  }
231
- result.sort((a, b) => b.rank - a.rank || a.lane - b.lane);
296
+ flushComponent();
232
297
  return result;
233
298
  }
234
299
  /** Create an empty cell. */
@@ -241,12 +306,11 @@ function buildGrid(rowModel, opts = {}, highlight = {
241
306
  }) {
242
307
  const colsPerLane = opts.colsPerLane ?? 2;
243
308
  const isFocus = highlight.mode === "focus";
244
- const { nodeLane, nodeRank, numLanes } = buildLaneAssignment(rowModel.nodes, rowModel.edges);
309
+ const { nodeLane, nodeRank, edgeLane, numLanes } = buildLaneAssignment(rowModel.nodes, rowModel.edges);
245
310
  const displayOrder = computeDisplayOrder(rowModel.nodes, nodeLane, nodeRank);
246
311
  const displayIndex = /* @__PURE__ */ new Map();
247
- displayOrder.forEach((d, i) => {
248
- displayIndex.set(d.hash, i);
249
- });
312
+ let nodeIdx = 0;
313
+ for (const d of displayOrder) if (d !== null) displayIndex.set(d.hash, nodeIdx++);
250
314
  const rollbackEdges = rowModel.edges.filter((e) => e.kind === "rollback" && e.from !== e.to);
251
315
  const adjacentRollbacks = [];
252
316
  const skippingRollbacks = [];
@@ -257,27 +321,86 @@ function buildGrid(rowModel, opts = {}, highlight = {
257
321
  if (ti === si + 1) adjacentRollbacks.push(e);
258
322
  else skippingRollbacks.push(e);
259
323
  }
260
- const colourLaneOf = /* @__PURE__ */ new Map();
261
- [...skippingRollbacks].sort((a, b) => a.dirName.localeCompare(b.dirName)).forEach((e, i) => {
262
- colourLaneOf.set(e.migrationHash, numLanes + i);
263
- });
264
- const geomOrder = [...skippingRollbacks].sort((a, b) => {
265
- const ta = displayIndex.get(a.to) ?? 0;
266
- const tb = displayIndex.get(b.to) ?? 0;
267
- if (ta !== tb) return tb - ta;
268
- return (displayIndex.get(a.from) ?? 0) - (displayIndex.get(b.from) ?? 0);
324
+ const targetGroups = /* @__PURE__ */ new Map();
325
+ for (const e of skippingRollbacks) {
326
+ const group = targetGroups.get(e.to);
327
+ if (group) group.push(e);
328
+ else targetGroups.set(e.to, [e]);
329
+ }
330
+ const sortedTargetKeys = [...targetGroups.keys()].sort((a, b) => {
331
+ const ta = displayIndex.get(a) ?? 0;
332
+ return (displayIndex.get(b) ?? 0) - ta;
269
333
  });
334
+ const numTargetGroups = sortedTargetKeys.length;
270
335
  const geomLaneOf = /* @__PURE__ */ new Map();
271
- const outermost = numLanes + skippingRollbacks.length - 1;
272
- geomOrder.forEach((e, i) => {
273
- geomLaneOf.set(e.migrationHash, outermost - i);
336
+ const outermostGroup = numLanes + numTargetGroups - 1;
337
+ sortedTargetKeys.forEach((targetHash, i) => {
338
+ const groupGeomLane = outermostGroup - i;
339
+ for (const e of targetGroups.get(targetHash)) geomLaneOf.set(e.migrationHash, groupGeomLane);
274
340
  });
341
+ const totalDisplayNodes = displayOrder.filter((d) => d !== null).length;
342
+ const planeLaneOf = /* @__PURE__ */ new Map();
343
+ for (const e of skippingRollbacks) {
344
+ const si = displayIndex.get(e.from) ?? 0;
345
+ planeLaneOf.set(e.migrationHash, totalDisplayNodes - si);
346
+ }
347
+ const PALETTE_SIZE = 6;
348
+ const GREEN_PALETTE_IDX = 5;
349
+ const arcSourceIndex = /* @__PURE__ */ new Map();
350
+ const arcTargetIndex = /* @__PURE__ */ new Map();
351
+ for (const e of skippingRollbacks) {
352
+ arcSourceIndex.set(e.migrationHash, displayIndex.get(e.from) ?? 0);
353
+ arcTargetIndex.set(e.migrationHash, displayIndex.get(e.to) ?? 0);
354
+ }
355
+ const arcsByTarget = /* @__PURE__ */ new Map();
356
+ const arcsBySource = /* @__PURE__ */ new Map();
357
+ for (const e of skippingRollbacks) {
358
+ const tb = arcsByTarget.get(e.to);
359
+ if (tb) tb.push(e);
360
+ else arcsByTarget.set(e.to, [e]);
361
+ const sb = arcsBySource.get(e.from);
362
+ if (sb) sb.push(e);
363
+ else arcsBySource.set(e.from, [e]);
364
+ }
365
+ const colourLaneOf = /* @__PURE__ */ new Map();
366
+ const activeArcColours = /* @__PURE__ */ new Map();
367
+ const activeFwdLaneColours = /* @__PURE__ */ new Set();
368
+ for (let i = displayOrder.length - 1; i >= 0; i--) {
369
+ const nd = displayOrder[i];
370
+ if (nd === null || nd === void 0) continue;
371
+ const { hash: nodeHash } = nd;
372
+ const nodeFwdLane = nodeLane.get(nodeHash) ?? 0;
373
+ activeFwdLaneColours.add(nodeFwdLane % PALETTE_SIZE);
374
+ const sortedIncoming = [...arcsByTarget.get(nodeHash) ?? []].sort((a, b) => a.dirName.localeCompare(b.dirName));
375
+ for (const arc of sortedIncoming) {
376
+ const originLaneColour = (nodeLane.get(arc.from) ?? 0) % PALETTE_SIZE;
377
+ const occupied = new Set(activeFwdLaneColours);
378
+ for (const c of activeArcColours.values()) occupied.add(c);
379
+ occupied.add(GREEN_PALETTE_IDX);
380
+ occupied.add(originLaneColour);
381
+ let chosen = -1;
382
+ for (let ci = 0; ci < PALETTE_SIZE; ci++) if (!occupied.has(ci)) {
383
+ chosen = ci;
384
+ break;
385
+ }
386
+ if (chosen === -1) {
387
+ for (let ci = 0; ci < PALETTE_SIZE; ci++) if (ci !== GREEN_PALETTE_IDX) {
388
+ chosen = ci;
389
+ break;
390
+ }
391
+ }
392
+ colourLaneOf.set(arc.migrationHash, chosen === -1 ? 0 : chosen);
393
+ activeArcColours.set(arc.migrationHash, chosen === -1 ? 0 : chosen);
394
+ }
395
+ for (const arc of arcsBySource.get(nodeHash) ?? []) activeArcColours.delete(arc.migrationHash);
396
+ }
275
397
  const routedBackArcs = skippingRollbacks.map((e) => ({
276
398
  edge: e,
277
399
  sourceIndex: displayIndex.get(e.from) ?? 0,
278
400
  targetIndex: displayIndex.get(e.to) ?? 0,
279
401
  geomLane: geomLaneOf.get(e.migrationHash) ?? numLanes,
280
- colourLane: colourLaneOf.get(e.migrationHash) ?? numLanes
402
+ colourLane: colourLaneOf.get(e.migrationHash) ?? 0,
403
+ planeLane: planeLaneOf.get(e.migrationHash) ?? numLanes
281
404
  }));
282
405
  const backArcsBySource = /* @__PURE__ */ new Map();
283
406
  const backArcsByTarget = /* @__PURE__ */ new Map();
@@ -300,7 +423,7 @@ function buildGrid(rowModel, opts = {}, highlight = {
300
423
  else adjacentByTarget.set(e.to, [e]);
301
424
  }
302
425
  for (const list of adjacentBySource.values()) list.sort((a, b) => a.dirName.localeCompare(b.dirName));
303
- const totalCols = (numLanes + skippingRollbacks.length) * colsPerLane;
426
+ const totalCols = (numLanes + numTargetGroups) * colsPerLane;
304
427
  const fwdEdges = rowModel.edges.filter((e) => e.kind === "forward" && e.from !== e.to);
305
428
  const selfEdges = rowModel.edges.filter((e) => e.kind === "self");
306
429
  const outboundFwd = /* @__PURE__ */ new Map();
@@ -412,8 +535,8 @@ function buildGrid(rowModel, opts = {}, highlight = {
412
535
  }
413
536
  function backArcPlane(arc) {
414
537
  const role = roleOf(arc.edge.migrationHash);
415
- if (!isFocus) return arc.colourLane;
416
- return role === "on-path" ? 0 : arc.colourLane + 1;
538
+ if (!isFocus) return arc.planeLane;
539
+ return role === "on-path" ? 0 : arc.planeLane + 1;
417
540
  }
418
541
  function composeLine(row, col, line, dirs, plane, extra) {
419
542
  const existing = row[col];
@@ -507,14 +630,24 @@ function buildGrid(rowModel, opts = {}, highlight = {
507
630
  return row;
508
631
  }
509
632
  for (const nodeDisplay of displayOrder) {
633
+ if (nodeDisplay === null) {
634
+ const sepRow = makeRow();
635
+ sepRow[0] = {
636
+ lines: [],
637
+ separator: true
638
+ };
639
+ grid.push(sepRow);
640
+ continue;
641
+ }
510
642
  const { hash: nodeHash } = nodeDisplay;
511
643
  const nodeLaneNum = nodeLane.get(nodeHash) ?? 0;
512
644
  activeLanes.add(nodeLaneNum);
513
645
  const outEdges = outboundFwd.get(nodeHash) ?? [];
514
646
  if (outEdges.length > 1) {
515
- const trunkChildLane = nodeLane.get(outEdges[0].to) ?? nodeLaneNum;
647
+ const trunkEdgeForFork = outEdges[0];
648
+ const trunkChildLane = edgeLane.get(trunkEdgeForFork.migrationHash) ?? nodeLane.get(trunkEdgeForFork.to) ?? nodeLaneNum;
516
649
  const branchEntries = outEdges.slice(1).map((e) => ({
517
- lane: nodeLane.get(e.to) ?? 0,
650
+ lane: edgeLane.get(e.migrationHash) ?? nodeLane.get(e.to) ?? 0,
518
651
  edge: e
519
652
  })).filter((b) => b.lane !== trunkChildLane && activeLanes.has(b.lane));
520
653
  if (branchEntries.length > 0) {
@@ -566,12 +699,19 @@ function buildGrid(rowModel, opts = {}, highlight = {
566
699
  edge: adj
567
700
  });
568
701
  }
569
- const inEdges = inboundFwd.get(nodeHash) ?? [];
570
- inEdges.sort((a, b) => a.dirName.localeCompare(b.dirName));
571
- for (const edge of inEdges) {
572
- const edgeLane = Math.max(nodeLane.get(edge.from) ?? 0, nodeLane.get(edge.to) ?? 0);
573
- laneCurrentEdge.set(edgeLane, edge);
702
+ function edgeLaneFor(edge) {
703
+ const override = edgeLane.get(edge.migrationHash);
704
+ if (override !== void 0) return override;
705
+ return Math.max(nodeLane.get(edge.from) ?? 0, nodeLane.get(edge.to) ?? 0);
574
706
  }
707
+ const inEdges = inboundFwd.get(nodeHash) ?? [];
708
+ inEdges.sort((a, b) => {
709
+ const aLane = edgeLaneFor(a);
710
+ const bLane = edgeLaneFor(b);
711
+ if (aLane !== bLane) return aLane - bLane;
712
+ return a.dirName.localeCompare(b.dirName);
713
+ });
714
+ for (const edge of inEdges) laneCurrentEdge.set(edgeLaneFor(edge), edge);
575
715
  {
576
716
  const teeArcs = backArcsBySource.get(nodeHash) ?? [];
577
717
  for (const arc of teeArcs) {
@@ -589,7 +729,7 @@ function buildGrid(rowModel, opts = {}, highlight = {
589
729
  }
590
730
  if (inEdges.length > 1) {
591
731
  const branchEntries = inEdges.slice(1).map((e) => ({
592
- lane: nodeLane.get(e.from) ?? 0,
732
+ lane: edgeLaneFor(e),
593
733
  edge: e
594
734
  }));
595
735
  const trunkEdge = inEdges[0];
@@ -599,16 +739,14 @@ function buildGrid(rowModel, opts = {}, highlight = {
599
739
  for (const b of branchEntries) activeLanes.add(b.lane);
600
740
  }
601
741
  for (const edge of inEdges) {
602
- const fromLane = nodeLane.get(edge.from) ?? 0;
603
- const toLane = nodeLane.get(edge.to) ?? 0;
604
- const edgeLane = Math.max(fromLane, toLane);
742
+ const eLane = edgeLaneFor(edge);
605
743
  const row = makeRow();
606
- const railCol = edgeLane * colsPerLane;
607
- const connCol = edgeLane * colsPerLane + 1;
608
- const line = lineRefFor(edge, edgeLane);
744
+ const railCol = eLane * colsPerLane;
745
+ const connCol = eLane * colsPerLane + 1;
746
+ const line = lineRefFor(edge, eLane);
609
747
  row[railCol] = vertCell(line);
610
748
  row[connCol] = dirCell(line, new Set(["up"]));
611
- placeVerticals(row, new Set([edgeLane]));
749
+ placeVerticals(row, new Set([eLane]));
612
750
  placeBackVerticals(row);
613
751
  grid.push(row);
614
752
  }
@@ -1439,7 +1577,7 @@ const DB_MARKER_NAME = "db";
1439
1577
  * environment (NO_COLOR, piped output). Used so on-path green / off-path dim are
1440
1578
  * deterministically emitted in tests that request colour while NO_COLOR is set.
1441
1579
  */
1442
- const { dim: forcedDim, bold: forcedBold } = createColors({ useColor: true });
1580
+ const { dim: forcedDim } = createColors({ useColor: true });
1443
1581
  const { greenBright: forcedGreen } = createColors({ useColor: true });
1444
1582
  /**
1445
1583
  * The two label styles used in `migrate --show` path-highlight mode.
@@ -1583,13 +1721,13 @@ function formatMigrationLabel(edge, dirNameWidth, opts, lane) {
1583
1721
  let dirNameStyler;
1584
1722
  let hashOverride;
1585
1723
  if (highlight === "on-path") {
1586
- dirNameStyler = (text) => bold(text);
1724
+ dirNameStyler = opts.colorize ? forcedGreen : (text) => text;
1587
1725
  hashOverride = void 0;
1588
1726
  } else if (highlight === "off-path") {
1589
1727
  dirNameStyler = opts.colorize ? forcedDim : style.dirName;
1590
1728
  hashOverride = opts.colorize ? forcedDim : void 0;
1591
1729
  } else if (opts.colorize && lane !== void 0) {
1592
- dirNameStyler = (text) => forcedBold(laneColorizer(lane)(text));
1730
+ dirNameStyler = (text) => laneColorizer(lane)(text);
1593
1731
  hashOverride = void 0;
1594
1732
  } else {
1595
1733
  dirNameStyler = style.dirName;
@@ -1819,4 +1957,4 @@ function renderMigrationGraphCommand(input) {
1819
1957
  //#endregion
1820
1958
  export { migrationListEmptySource as _, renderMigrationGraphLegend as a, renderMigrationListWithStyle as c, highlightFromEdgeAnnotations as d, indentMigrationGraphTreeBlock as f, abbreviateContractHash as g, buildGrid as h, formatOnPathMigrationRow as i, computeGlobalMaxDirNameWidth as l, buildMigrationGraphRows as m, computeMaxDirNameWidth as n, createAnsiMigrationListStyler as o, renderMigrationGraphSpaceTree as p, renderMigrationGraphCommand as r, IDENTITY_MIGRATION_LIST_STYLER as s, computeLabelColumn as t, computeGlobalMaxEdgeTreePrefixWidth as u, migrationListForwardArrow as v };
1821
1959
 
1822
- //# sourceMappingURL=migration-graph-command-render-BAOzyYF6.mjs.map
1960
+ //# sourceMappingURL=migration-graph-command-render-CEez7YUK.mjs.map