@prisma-next/cli 0.12.0-dev.51 → 0.12.0-dev.53

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 (65) hide show
  1. package/dist/cli.mjs +7 -7
  2. package/dist/{client-DC-UlBLy.mjs → client-DIcitJdy.mjs} +113 -49
  3. package/dist/client-DIcitJdy.mjs.map +1 -0
  4. package/dist/commands/contract-infer.mjs +1 -1
  5. package/dist/commands/db-init.mjs +2 -2
  6. package/dist/commands/db-schema.mjs +1 -1
  7. package/dist/commands/db-sign.mjs +1 -1
  8. package/dist/commands/db-update.mjs +2 -2
  9. package/dist/commands/db-verify.mjs +1 -1
  10. package/dist/commands/migrate.d.mts +35 -1
  11. package/dist/commands/migrate.d.mts.map +1 -1
  12. package/dist/commands/migrate.mjs +287 -6
  13. package/dist/commands/migrate.mjs.map +1 -1
  14. package/dist/commands/migration-check.mjs +2 -2
  15. package/dist/commands/migration-graph.d.mts.map +1 -1
  16. package/dist/commands/migration-graph.mjs +4 -2
  17. package/dist/commands/migration-graph.mjs.map +1 -1
  18. package/dist/commands/migration-list.d.mts +1 -0
  19. package/dist/commands/migration-list.d.mts.map +1 -1
  20. package/dist/commands/migration-list.mjs +1 -1
  21. package/dist/commands/migration-log.mjs +1 -1
  22. package/dist/commands/migration-show.mjs +2 -2
  23. package/dist/commands/migration-status.d.mts.map +1 -1
  24. package/dist/commands/migration-status.mjs +2 -2
  25. package/dist/{contract-infer-DpGN9SAj.mjs → contract-infer-BAdhYGQH.mjs} +2 -2
  26. package/dist/{contract-infer-DpGN9SAj.mjs.map → contract-infer-BAdhYGQH.mjs.map} +1 -1
  27. package/dist/{db-verify-Cq16Obsw.mjs → db-verify-CiUCDXnv.mjs} +2 -2
  28. package/dist/{db-verify-Cq16Obsw.mjs.map → db-verify-CiUCDXnv.mjs.map} +1 -1
  29. package/dist/exports/control-api.mjs +1 -1
  30. package/dist/{inspect-live-schema-CRDKTNcf.mjs → inspect-live-schema-DegaqKFT.mjs} +2 -2
  31. package/dist/{inspect-live-schema-CRDKTNcf.mjs.map → inspect-live-schema-DegaqKFT.mjs.map} +1 -1
  32. package/dist/{migration-check-BxWlQBOs.mjs → migration-check-B2ccCHe7.mjs} +3 -3
  33. package/dist/{migration-check-BxWlQBOs.mjs.map → migration-check-B2ccCHe7.mjs.map} +1 -1
  34. package/dist/{migration-command-scaffold-BDd9abqW.mjs → migration-command-scaffold-D6UeN71F.mjs} +2 -2
  35. package/dist/{migration-command-scaffold-BDd9abqW.mjs.map → migration-command-scaffold-D6UeN71F.mjs.map} +1 -1
  36. package/dist/{migration-graph-space-render-CeNXh_Wy.mjs → migration-graph-space-render-B0HkTNj3.mjs} +488 -84
  37. package/dist/migration-graph-space-render-B0HkTNj3.mjs.map +1 -0
  38. package/dist/{migration-list-vJWFuXca.mjs → migration-list-mYmj2j33.mjs} +6 -4
  39. package/dist/migration-list-mYmj2j33.mjs.map +1 -0
  40. package/dist/{migration-log-6rcHQSI4.mjs → migration-log-Dzs18GU7.mjs} +3 -3
  41. package/dist/{migration-log-6rcHQSI4.mjs.map → migration-log-Dzs18GU7.mjs.map} +1 -1
  42. package/dist/{migration-path-target-UkxkgXnv.mjs → migration-path-target-DK-B7POa.mjs} +1 -1
  43. package/dist/{migration-path-target-UkxkgXnv.mjs.map → migration-path-target-DK-B7POa.mjs.map} +1 -1
  44. package/dist/{migration-status-Bjv91dE7.mjs → migration-status-BT9eCQsf.mjs} +8 -5
  45. package/dist/migration-status-BT9eCQsf.mjs.map +1 -0
  46. package/dist/{schemas-DJY2O09F.mjs → schemas-B4xeMrNt.mjs} +1 -1
  47. package/dist/{schemas-DJY2O09F.mjs.map → schemas-B4xeMrNt.mjs.map} +1 -1
  48. package/dist/types-qV41eEXH.d.mts.map +1 -1
  49. package/package.json +18 -18
  50. package/src/commands/migrate.ts +512 -2
  51. package/src/commands/migration-graph.ts +2 -0
  52. package/src/commands/migration-list.ts +3 -0
  53. package/src/commands/migration-status.ts +4 -0
  54. package/src/control-api/operations/db-run.ts +14 -3
  55. package/src/control-api/operations/db-verify.ts +15 -5
  56. package/src/control-api/operations/migrate.ts +149 -56
  57. package/src/utils/formatters/migration-graph-layout.ts +187 -42
  58. package/src/utils/formatters/migration-graph-space-render.ts +11 -1
  59. package/src/utils/formatters/migration-graph-tree-render.ts +609 -59
  60. package/src/utils/formatters/migration-list-render.ts +12 -0
  61. package/src/utils/formatters/migration-list-styler.ts +5 -7
  62. package/dist/client-DC-UlBLy.mjs.map +0 -1
  63. package/dist/migration-graph-space-render-CeNXh_Wy.mjs.map +0 -1
  64. package/dist/migration-list-vJWFuXca.mjs.map +0 -1
  65. package/dist/migration-status-Bjv91dE7.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-graph-space-render-B0HkTNj3.mjs","names":["magenta","cyan","green","yellow","red"],"sources":["../src/utils/formatters/migration-graph-layout.ts","../src/utils/formatters/migration-list-graph-topology.ts","../src/utils/formatters/migration-graph-rows.ts","../src/utils/formatters/migration-graph-lane-colors.ts","../src/utils/formatters/migration-list-data-column.ts","../src/utils/formatters/migration-list-render.ts","../src/utils/formatters/migration-list-styler.ts","../src/utils/formatters/migration-graph-tree-render.ts","../src/utils/formatters/migration-graph-space-render.ts"],"sourcesContent":["import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport type { ClassifiedEdge, MigrationGraphRowModel } from './migration-graph-rows';\nimport type { MigrationEdgeKind } from './migration-list-graph-topology';\n\nexport type EdgeAdjacency = 'adjacent' | 'node-skipping-forward' | 'node-skipping-rollback';\n\nexport type StructuralCell =\n | { readonly kind: 'empty' }\n | {\n readonly kind: 'node';\n readonly contractHash: string;\n readonly arcTee?: boolean;\n readonly arcLand?: boolean;\n }\n | { readonly kind: 'vertical-pass'; readonly migrationHash?: string }\n | { readonly kind: 'horizontal-pass'; readonly migrationHash?: string }\n | { readonly kind: 'branch-tee'; readonly migrationHash?: string }\n | { readonly kind: 'branch-corner'; readonly migrationHash?: string }\n | { readonly kind: 'merge-tee'; readonly migrationHash?: string }\n | { readonly kind: 'merge-corner'; readonly migrationHash?: string }\n | { readonly kind: 'arc-branch-corner'; readonly migrationHash?: string }\n | { readonly kind: 'arc-branch-tee'; readonly migrationHash?: string }\n | { readonly kind: 'arc-land-corner'; readonly migrationHash?: string }\n | { readonly kind: 'arc-land-tee'; readonly migrationHash?: string }\n | {\n readonly kind: 'arc-crossing';\n /** Hash of the edge whose vertical lane passes through this cell. */\n readonly migrationHash?: string;\n /** Hash of the arc edge that crosses over the vertical lane. */\n readonly arcMigrationHash?: string;\n }\n | { readonly kind: 'arc-land-bridge'; readonly migrationHash?: string }\n | {\n readonly kind: 'edge-lane';\n readonly migrationHash: string;\n readonly edgeKind: MigrationEdgeKind;\n readonly ownsLabel: boolean;\n readonly adjacency: EdgeAdjacency;\n };\n\nexport type GridRowKind =\n | 'node'\n | 'edge'\n | 'branch-connector'\n | 'merge-connector'\n | 'component-separator';\n\nexport interface MigrationGraphGridRow {\n readonly kind: GridRowKind;\n readonly contractHash?: string;\n readonly edge?: ClassifiedEdge;\n readonly laneIndex?: number;\n readonly passThroughLanes?: readonly number[];\n readonly startLane?: number;\n readonly endLane?: number;\n readonly branchCount?: number;\n readonly convergenceProducer?: boolean;\n readonly cells: readonly StructuralCell[];\n}\n\nexport interface MigrationGraphGridModel {\n readonly rows: readonly MigrationGraphGridRow[];\n readonly nodeColumn: ReadonlyMap<string, number>;\n readonly edgeColumn: ReadonlyMap<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Edge bucketing helpers\n// ---------------------------------------------------------------------------\n\nfunction forwardEdges(edges: readonly ClassifiedEdge[]): ClassifiedEdge[] {\n return edges.filter((e) => e.kind === 'forward');\n}\n\nfunction buildForwardProducersByTo(\n edges: readonly ClassifiedEdge[],\n): Map<string, ClassifiedEdge[]> {\n const byTo = new Map<string, ClassifiedEdge[]>();\n for (const edge of edges) {\n if (edge.kind !== 'forward') continue;\n const bucket = byTo.get(edge.to);\n if (bucket) bucket.push(edge);\n else byTo.set(edge.to, [edge]);\n }\n return byTo;\n}\n\nfunction buildForwardOutDegree(edges: readonly ClassifiedEdge[]): Map<string, number> {\n const out = new Map<string, number>();\n for (const edge of edges) {\n if (edge.kind !== 'forward' || edge.from === edge.to) continue;\n out.set(edge.from, (out.get(edge.from) ?? 0) + 1);\n }\n return out;\n}\n\nfunction buildForwardInDegree(edges: readonly ClassifiedEdge[]): Map<string, number> {\n const indeg = new Map<string, number>();\n for (const edge of forwardEdges(edges)) {\n if (edge.from === edge.to) continue;\n indeg.set(edge.to, (indeg.get(edge.to) ?? 0) + 1);\n }\n return indeg;\n}\n\n/**\n * Distinct source contracts among a contract's forward producers. A contract is\n * a *convergence* when this count is >= 2. Multiple migrations sharing one\n * source (a multi-edge) count once — they stack in a single lane rather than\n * fanning into a convergence.\n */\nfunction buildDistinctSourceCountByTo(edges: readonly ClassifiedEdge[]): Map<string, number> {\n const sources = new Map<string, Set<string>>();\n for (const edge of edges) {\n if (edge.kind !== 'forward' || edge.from === edge.to) continue;\n const set = sources.get(edge.to);\n if (set) set.add(edge.from);\n else sources.set(edge.to, new Set([edge.from]));\n }\n const counts = new Map<string, number>();\n for (const [to, set] of sources) counts.set(to, set.size);\n return counts;\n}\n\nfunction splitComponents(nodes: readonly (string | null)[]): readonly (readonly string[])[] {\n const components: string[][] = [];\n let current: string[] = [];\n for (const node of nodes) {\n if (node === null) {\n if (current.length > 0) {\n components.push(current);\n current = [];\n }\n continue;\n }\n current.push(node);\n }\n if (current.length > 0) components.push(current);\n return components;\n}\n\n// ---------------------------------------------------------------------------\n// Adjacency refinement (operates on the emitted rows)\n// ---------------------------------------------------------------------------\n\nfunction classifyForwardShortConvergenceAdjacency(\n rows: readonly MigrationGraphGridRow[],\n edgeRowIndex: number,\n edge: ClassifiedEdge,\n laneIndex: number,\n): EdgeAdjacency {\n for (let index = edgeRowIndex + 1; index < rows.length; index++) {\n const row = rows[index];\n if (row === undefined) break;\n if (row.kind === 'component-separator' || row.kind === 'branch-connector') continue;\n if (row.kind === 'merge-connector') continue;\n if (row.kind === 'edge') {\n if (row.laneIndex === laneIndex) return 'node-skipping-forward';\n continue;\n }\n if (row.kind === 'node' && row.contractHash === edge.from) {\n return 'adjacent';\n }\n }\n return 'node-skipping-forward';\n}\n\nfunction convergenceProducerUsesShortAdjacency(\n edge: ClassifiedEdge,\n laneIndex: number,\n forwardProducersByTo: ReadonlyMap<string, readonly ClassifiedEdge[]>,\n producerLaneByHash: ReadonlyMap<string, number>,\n): boolean {\n const producers = (forwardProducersByTo.get(edge.to) ?? []).filter(\n (candidate) => candidate.kind === 'forward',\n );\n if (producers.length < 2) return false;\n\n const fanLanes = [\n ...new Set(\n producers\n .map((producer) => producerLaneByHash.get(producer.migrationHash))\n .filter((candidate): candidate is number => candidate !== undefined),\n ),\n ].sort((a, b) => a - b);\n const fanStart = fanLanes[0];\n if (fanStart === undefined) return false;\n\n return laneIndex === fanStart;\n}\n\nfunction classifyForwardLayoutAdjacency(\n rows: readonly MigrationGraphGridRow[],\n edgeRowIndex: number,\n edge: ClassifiedEdge,\n laneIndex: number,\n passThroughLanes: readonly number[],\n nodeColumn: ReadonlyMap<string, number>,\n convergenceProducer: boolean,\n divergenceBranchEdge: boolean,\n): EdgeAdjacency {\n let sawObstruction = false;\n const passThroughLaneSet = new Set(passThroughLanes);\n\n for (let index = edgeRowIndex + 1; index < rows.length; index++) {\n const row = rows[index];\n if (row === undefined) break;\n if (row.kind === 'component-separator') continue;\n if (row.kind === 'merge-connector') {\n if (convergenceProducer) {\n if (row.contractHash === edge.from) sawObstruction = true;\n } else if (!divergenceBranchEdge && row.contractHash !== edge.from) {\n sawObstruction = true;\n }\n continue;\n }\n if (row.kind === 'branch-connector') continue;\n if (row.kind === 'edge') {\n if (row.laneIndex === laneIndex) return 'node-skipping-forward';\n if (!divergenceBranchEdge && row.edge !== undefined && row.edge.to !== edge.to) {\n sawObstruction = true;\n }\n continue;\n }\n if (row.kind === 'node' && row.contractHash !== undefined) {\n if (row.contractHash === edge.from) {\n return sawObstruction ? 'node-skipping-forward' : 'adjacent';\n }\n const nodeCol = nodeColumn.get(row.contractHash) ?? 0;\n // A divergence-branch lane runs unobstructed to its convergence point;\n // sibling-branch nodes sit in parallel lanes and never block it.\n if (!divergenceBranchEdge && !passThroughLaneSet.has(nodeCol)) {\n sawObstruction = true;\n }\n }\n }\n\n return 'node-skipping-forward';\n}\n\nfunction classifyLayoutAdjacency(\n rows: readonly MigrationGraphGridRow[],\n edgeRowIndex: number,\n edge: ClassifiedEdge,\n laneIndex: number,\n passThroughLanes: readonly number[],\n nodeColumn: ReadonlyMap<string, number>,\n position: ReadonlyMap<string, number>,\n forwardInDegree: ReadonlyMap<string, number>,\n convergenceProducer: boolean,\n divergenceBranchEdge: boolean,\n): EdgeAdjacency {\n if (edge.kind === 'self') return 'adjacent';\n\n const fromPos = position.get(edge.from);\n const toPos = position.get(edge.to);\n\n if (edge.kind === 'forward') {\n const inDegree = forwardInDegree.get(edge.to) ?? 0;\n if (inDegree <= 1 && fromPos !== undefined && toPos !== undefined && fromPos === toPos + 1) {\n return 'adjacent';\n }\n return classifyForwardLayoutAdjacency(\n rows,\n edgeRowIndex,\n edge,\n laneIndex,\n passThroughLanes,\n nodeColumn,\n convergenceProducer,\n divergenceBranchEdge,\n );\n }\n\n if (fromPos !== undefined && toPos !== undefined && toPos === fromPos + 1) {\n return 'adjacent';\n }\n\n for (let index = edgeRowIndex + 1; index < rows.length; index++) {\n const row = rows[index];\n if (row === undefined) break;\n if (\n row.kind === 'component-separator' ||\n row.kind === 'branch-connector' ||\n row.kind === 'merge-connector'\n ) {\n continue;\n }\n if (row.kind === 'edge') continue;\n if (row.kind === 'node') {\n return row.contractHash === edge.to ? 'adjacent' : 'node-skipping-rollback';\n }\n }\n return 'node-skipping-rollback';\n}\n\nfunction refineAdjacency(\n rows: readonly MigrationGraphGridRow[],\n nodeColumn: ReadonlyMap<string, number>,\n position: ReadonlyMap<string, number>,\n forwardInDegree: ReadonlyMap<string, number>,\n forwardOutDegree: ReadonlyMap<string, number>,\n edges: readonly ClassifiedEdge[],\n producerLaneByHash: ReadonlyMap<string, number>,\n): MigrationGraphGridRow[] {\n const forwardProducersByTo = buildForwardProducersByTo(edges);\n function branchLaneForEdge(producer: ClassifiedEdge): number | undefined {\n const children = edges.filter(\n (edge) => edge.from === producer.from && edge.kind === 'forward' && edge.from !== edge.to,\n );\n if (children.length < 2) return undefined;\n const index = children.findIndex((child) => child.migrationHash === producer.migrationHash);\n return index >= 0 ? index : undefined;\n }\n\n return rows.map((row, rowIndex) => {\n if (row.kind !== 'edge' || row.edge === undefined || row.laneIndex === undefined) {\n return row;\n }\n const divergenceBranchEdge =\n row.edge.kind === 'forward' &&\n !(row.convergenceProducer ?? false) &&\n (forwardOutDegree.get(row.edge.from) ?? 0) >= 2 &&\n branchLaneForEdge(row.edge) !== undefined;\n const adjacency =\n row.convergenceProducer === true &&\n convergenceProducerUsesShortAdjacency(\n row.edge,\n row.laneIndex,\n forwardProducersByTo,\n producerLaneByHash,\n )\n ? classifyForwardShortConvergenceAdjacency(rows, rowIndex, row.edge, row.laneIndex)\n : classifyLayoutAdjacency(\n rows,\n rowIndex,\n row.edge,\n row.laneIndex,\n row.passThroughLanes ?? [],\n nodeColumn,\n position,\n forwardInDegree,\n row.convergenceProducer ?? false,\n divergenceBranchEdge,\n );\n // Reconstruct lane owners from the existing cells so the refined row\n // preserves per-cell identity on its pass-through vertical-pass cells.\n const existingLaneEdge = new Map<number, string>();\n for (const lane of row.passThroughLanes ?? []) {\n const cell = row.cells[lane];\n if (cell !== undefined && 'migrationHash' in cell && cell.migrationHash !== undefined) {\n existingLaneEdge.set(lane, cell.migrationHash);\n }\n }\n return {\n ...row,\n cells: buildEdgeCells(\n row.edge,\n row.laneIndex,\n row.passThroughLanes ?? [],\n adjacency,\n row.cells.length,\n existingLaneEdge,\n ),\n };\n });\n}\n\nfunction classifyEdgeAdjacency(\n edge: ClassifiedEdge,\n position: ReadonlyMap<string, number>,\n): EdgeAdjacency {\n if (edge.kind === 'self') return 'adjacent';\n\n const fromPos = position.get(edge.from);\n const toPos = position.get(edge.to);\n if (fromPos === undefined || toPos === undefined) return 'adjacent';\n\n if (edge.kind === 'forward') {\n if (toPos >= fromPos) return 'adjacent';\n return fromPos === toPos + 1 ? 'adjacent' : 'node-skipping-forward';\n }\n\n if (toPos <= fromPos) return 'adjacent';\n return toPos === fromPos + 1 ? 'adjacent' : 'node-skipping-rollback';\n}\n\n// ---------------------------------------------------------------------------\n// Cell builders\n// ---------------------------------------------------------------------------\n\nfunction emptyCells(width: number): StructuralCell[] {\n return Array.from({ length: width }, () => ({ kind: 'empty' as const }));\n}\n\n/** Returns `{ migrationHash: hash }` when hash is defined, otherwise `{}`. */\nfunction hashProp(hash: string | undefined): { readonly migrationHash: string } | object {\n return hash !== undefined ? { migrationHash: hash } : {};\n}\n\n/** Returns `{ arcMigrationHash: hash }` when hash is defined, otherwise `{}`. */\nfunction arcHashProp(hash: string | undefined): { readonly arcMigrationHash: string } | object {\n return hash !== undefined ? { arcMigrationHash: hash } : {};\n}\n\nfunction buildBranchConnectorCells(\n startLane: number,\n endLane: number,\n fanTargetLanes: ReadonlySet<number>,\n activeLanes: ReadonlySet<number>,\n gridWidth: number,\n /** Hash of the edge whose lane is at startLane (the source/trunk edge). */\n trunkEdgeHash: string | undefined,\n /** Hash of the fan edge for each fan-target lane. */\n fanEdgeHashByLane: ReadonlyMap<number, string>,\n /** Hash of the edge occupying each active pass-through lane. */\n laneEdgeByIndex: ReadonlyMap<number, string>,\n): StructuralCell[] {\n const cells = emptyCells(gridWidth);\n for (let lane = 0; lane < gridWidth; lane++) {\n if (activeLanes.has(lane) && (lane < startLane || lane > endLane)) {\n cells[lane] = { kind: 'vertical-pass', ...hashProp(laneEdgeByIndex.get(lane)) };\n continue;\n }\n if (lane === startLane) {\n cells[lane] = { kind: 'branch-tee', ...hashProp(trunkEdgeHash) };\n } else if (lane === endLane) {\n cells[lane] = { kind: 'branch-corner', ...hashProp(fanEdgeHashByLane.get(lane)) };\n } else if (lane > startLane && lane < endLane) {\n if (fanTargetLanes.has(lane)) {\n cells[lane] = { kind: 'branch-tee', ...hashProp(fanEdgeHashByLane.get(lane)) };\n } else if (activeLanes.has(lane)) {\n cells[lane] = {\n kind: 'arc-crossing',\n ...hashProp(laneEdgeByIndex.get(lane)),\n ...arcHashProp(fanEdgeHashByLane.get(endLane)),\n };\n } else {\n cells[lane] = { kind: 'branch-tee', ...hashProp(fanEdgeHashByLane.get(lane)) };\n }\n }\n }\n return cells;\n}\n\nfunction buildMergeConnectorCells(\n startLane: number,\n endLane: number,\n fanTargetLanes: ReadonlySet<number>,\n activeLanes: ReadonlySet<number>,\n gridWidth: number,\n /** Hash of the edge occupying each active lane (fan lanes + pass-throughs). */\n laneEdgeByIndex: ReadonlyMap<number, string>,\n): StructuralCell[] {\n const cells = emptyCells(gridWidth);\n for (let lane = 0; lane < gridWidth; lane++) {\n if (activeLanes.has(lane) && (lane < startLane || lane > endLane)) {\n cells[lane] = { kind: 'vertical-pass', ...hashProp(laneEdgeByIndex.get(lane)) };\n continue;\n }\n if (lane === startLane) {\n cells[lane] = { kind: 'merge-tee', ...hashProp(laneEdgeByIndex.get(lane)) };\n } else if (lane === endLane) {\n cells[lane] = { kind: 'merge-corner', ...hashProp(laneEdgeByIndex.get(lane)) };\n } else if (lane > startLane && lane < endLane) {\n if (fanTargetLanes.has(lane)) {\n cells[lane] = { kind: 'merge-tee', ...hashProp(laneEdgeByIndex.get(lane)) };\n } else if (activeLanes.has(lane)) {\n cells[lane] = {\n kind: 'arc-crossing',\n ...hashProp(laneEdgeByIndex.get(lane)),\n ...arcHashProp(laneEdgeByIndex.get(endLane)),\n };\n } else {\n cells[lane] = { kind: 'horizontal-pass', ...hashProp(laneEdgeByIndex.get(startLane)) };\n }\n }\n }\n return cells;\n}\n\nfunction buildNodeCells(\n contractHash: string,\n nodeColumn: number,\n activeLanes: readonly number[],\n gridWidth: number,\n /** Hash of the edge occupying each active pass-through lane. */\n laneEdgeByIndex: ReadonlyMap<number, string>,\n): StructuralCell[] {\n const cells = emptyCells(gridWidth);\n for (const lane of activeLanes) {\n if (lane !== nodeColumn && lane < gridWidth) {\n cells[lane] = { kind: 'vertical-pass', ...hashProp(laneEdgeByIndex.get(lane)) };\n }\n }\n if (nodeColumn < gridWidth) {\n cells[nodeColumn] = { kind: 'node', contractHash };\n }\n return cells;\n}\n\nfunction buildEdgeCells(\n edge: ClassifiedEdge,\n laneIndex: number,\n passThroughLanes: readonly number[],\n adjacency: EdgeAdjacency,\n gridWidth: number,\n /** Hash of the edge occupying each active pass-through lane. */\n laneEdgeByIndex: ReadonlyMap<number, string>,\n): StructuralCell[] {\n const cells = emptyCells(gridWidth);\n for (const lane of passThroughLanes) {\n if (lane < gridWidth) {\n cells[lane] = { kind: 'vertical-pass', ...hashProp(laneEdgeByIndex.get(lane)) };\n }\n }\n if (laneIndex < gridWidth) {\n cells[laneIndex] = {\n kind: 'edge-lane',\n migrationHash: edge.migrationHash,\n edgeKind: edge.kind,\n ownsLabel: true,\n adjacency,\n };\n }\n return cells;\n}\n\n// ---------------------------------------------------------------------------\n// Vertical ordering: tips-first DFS post-order over forward edges\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the vertical node order for a component: tips at the top (index 0),\n * roots at the bottom. This is a DFS post-order over forward edges starting\n * from forward roots, visiting children in their input (insertion) order. A\n * node is emitted only after all of its forward children, so convergence nodes\n * sit below every branch that feeds them and the longest contiguous chain reads\n * top-to-bottom without braiding.\n */\nfunction computeVerticalOrder(\n componentNodes: readonly string[],\n forwardChildren: ReadonlyMap<string, readonly ClassifiedEdge[]>,\n forwardInDegree: ReadonlyMap<string, number>,\n): string[] {\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const node of componentNodes) color.set(node, WHITE);\n\n const sortRoots = (roots: readonly string[]): string[] =>\n [...roots].sort((a, b) => {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n });\n\n let roots = sortRoots(componentNodes.filter((n) => (forwardInDegree.get(n) ?? 0) === 0));\n if (roots.length === 0) roots = sortRoots(componentNodes);\n\n const result: string[] = [];\n\n interface Frame {\n node: string;\n children: readonly ClassifiedEdge[];\n index: number;\n }\n\n function runDfs(root: string): void {\n if (color.get(root) !== WHITE) return;\n const stack: Frame[] = [{ node: root, children: forwardChildren.get(root) ?? [], index: 0 }];\n color.set(root, GRAY);\n\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame === undefined) break;\n if (frame.index >= frame.children.length) {\n color.set(frame.node, BLACK);\n result.push(frame.node);\n stack.pop();\n continue;\n }\n const child = frame.children[frame.index];\n frame.index += 1;\n if (child === undefined) continue;\n if (color.get(child.to) === WHITE) {\n color.set(child.to, GRAY);\n stack.push({ node: child.to, children: forwardChildren.get(child.to) ?? [], index: 0 });\n }\n }\n }\n\n for (const root of roots) runDfs(root);\n // Nodes unreachable via forward edges (e.g. rollback-only sources) follow in\n // component order.\n for (const node of componentNodes) {\n if (color.get(node) === WHITE) runDfs(node);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Routed back-arcs for node-skipping rollbacks\n// ---------------------------------------------------------------------------\n\ninterface SkipRollbackRoute {\n readonly edge: ClassifiedEdge;\n readonly backLane: number;\n}\n\nfunction rollbackSpan(\n edge: ClassifiedEdge,\n position: ReadonlyMap<string, number>,\n): { readonly top: number; readonly bottom: number } {\n const top = position.get(edge.from) ?? 0;\n const bottom = position.get(edge.to) ?? top;\n return { top, bottom };\n}\n\nfunction spansOverlap(\n a: { readonly top: number; readonly bottom: number },\n b: { readonly top: number; readonly bottom: number },\n): boolean {\n return a.top <= b.bottom && b.top <= a.bottom;\n}\n\nfunction forwardMaxLane(\n rows: readonly MigrationGraphGridRow[],\n skipMigrationHashes: ReadonlySet<string>,\n): number {\n let max = 0;\n for (const row of rows) {\n if (\n row.kind === 'edge' &&\n row.edge !== undefined &&\n skipMigrationHashes.has(row.edge.migrationHash)\n ) {\n continue;\n }\n max = Math.max(max, row.laneIndex ?? 0);\n for (const lane of row.passThroughLanes ?? []) {\n max = Math.max(max, lane);\n }\n if (row.startLane !== undefined) {\n max = Math.max(max, row.startLane, row.endLane ?? row.startLane);\n }\n }\n return max;\n}\n\nfunction allocateSkipRollbackBackLanes(\n skipRollbacks: readonly ClassifiedEdge[],\n position: ReadonlyMap<string, number>,\n forwardMax: number,\n): Map<string, number> {\n const sorted = [...skipRollbacks].sort((a, b) => {\n const aTop = position.get(a.from) ?? 0;\n const bTop = position.get(b.from) ?? 0;\n if (aTop !== bTop) return aTop - bTop;\n return b.dirName.localeCompare(a.dirName);\n });\n\n const occupied: { readonly top: number; readonly bottom: number; readonly lane: number }[] = [];\n const lanes = new Map<string, number>();\n let nextLane = forwardMax + 1;\n\n for (const edge of sorted) {\n const span = rollbackSpan(edge, position);\n let lane = nextLane;\n while (occupied.some((entry) => entry.lane === lane && spansOverlap(entry, span))) {\n lane += 1;\n }\n occupied.push({ ...span, lane });\n lanes.set(edge.migrationHash, lane);\n nextLane = Math.max(nextLane, lane + 1);\n }\n\n return lanes;\n}\n\nfunction findNodeRowIndex(rows: readonly MigrationGraphGridRow[], contractHash: string): number {\n return rows.findIndex((row) => row.kind === 'node' && row.contractHash === contractHash);\n}\n\nfunction findEdgeRowIndex(rows: readonly MigrationGraphGridRow[], migrationHash: string): number {\n return rows.findIndex((row) => row.kind === 'edge' && row.edge?.migrationHash === migrationHash);\n}\n\n// A grid row with a mutable `cells` array. The routing pass clones the\n// immutable rows into this shape so it can paint arc cells in place without\n// stripping `readonly` with a cast.\ntype MutableGridRow = Omit<MigrationGraphGridRow, 'cells'> & { cells: StructuralCell[] };\n\nfunction ensureCellWidth(cells: StructuralCell[], width: number): void {\n while (cells.length < width) {\n cells.push({ kind: 'empty' });\n }\n}\n\nfunction cloneRow(row: MigrationGraphGridRow): MutableGridRow {\n return { ...row, cells: [...row.cells] };\n}\n\nfunction routeCrossesRow(\n route: SkipRollbackRoute,\n rowIndex: number,\n rows: readonly MigrationGraphGridRow[],\n): boolean {\n const sourceRow = findNodeRowIndex(rows, route.edge.from);\n const targetRow = findNodeRowIndex(rows, route.edge.to);\n if (sourceRow < 0 || targetRow < 0) return false;\n return rowIndex > sourceRow && rowIndex <= targetRow;\n}\n\nfunction applySkipRollbackRouting(\n rows: readonly MigrationGraphGridRow[],\n skipRollbacks: readonly ClassifiedEdge[],\n position: ReadonlyMap<string, number>,\n nodeColumn: ReadonlyMap<string, number>,\n edgeColumn: Map<string, number>,\n): MigrationGraphGridRow[] {\n if (skipRollbacks.length === 0) return [...rows];\n\n const skipHashes = new Set(skipRollbacks.map((edge) => edge.migrationHash));\n const forwardMax = forwardMaxLane(rows, skipHashes);\n const backLaneByHash = allocateSkipRollbackBackLanes(skipRollbacks, position, forwardMax);\n const routes: SkipRollbackRoute[] = skipRollbacks.map((edge) => ({\n edge,\n backLane: backLaneByHash.get(edge.migrationHash) ?? forwardMax + 1,\n }));\n\n const result = rows.map(cloneRow);\n\n for (const route of routes) {\n const { edge, backLane } = route;\n const nodeCol = nodeColumn.get(edge.from) ?? 0;\n const targetCol = nodeColumn.get(edge.to) ?? 0;\n const sourceRowIndex = findNodeRowIndex(result, edge.from);\n const targetRowIndex = findNodeRowIndex(result, edge.to);\n const edgeRowIndex = findEdgeRowIndex(result, edge.migrationHash);\n if (sourceRowIndex < 0 || targetRowIndex < 0 || edgeRowIndex < 0) continue;\n\n edgeColumn.set(edge.migrationHash, backLane);\n\n // Back-lanes of arcs that tee off this same source node. They share the\n // node's tee row, so each inner lane reads as a `┬` junction and only the\n // outermost gets the closing `╮`.\n const coSourcedLanes = routes\n .filter((other) => other.edge.from === edge.from)\n .map((other) => other.backLane);\n const maxCoSourcedLane = Math.max(...coSourcedLanes);\n\n // Back-lanes of arcs that converge on this same target node. They share the\n // node's landing row, so each inner lane reads as a `┴` junction (the outer\n // arcs' horizontal bridge passes through it on the way to the node) and only\n // the outermost closes the corner with `╯`.\n const coLandingLanes = routes\n .filter((other) => other.edge.to === edge.to)\n .map((other) => other.backLane);\n const maxCoLandingLane = Math.max(...coLandingLanes);\n\n const { migrationHash: arcHash } = edge;\n\n const sourceRow = result[sourceRowIndex];\n if (sourceRow !== undefined) {\n const cells = sourceRow.cells;\n ensureCellWidth(cells, backLane + 1);\n const contractHash = sourceRow.contractHash ?? EMPTY_CONTRACT_HASH;\n cells[nodeCol] = { kind: 'node', contractHash, arcTee: true };\n for (let lane = nodeCol + 1; lane < backLane; lane += 1) {\n if (coSourcedLanes.includes(lane)) {\n // A co-sourced arc tees off at this lane; tag it with that arc's hash.\n const coSourcedArc = routes.find((r) => r.backLane === lane && r.edge.from === edge.from);\n cells[lane] = {\n kind: 'arc-branch-tee',\n ...hashProp(coSourcedArc?.edge.migrationHash),\n };\n continue;\n }\n const existing = cells[lane];\n const occupied =\n existing !== undefined &&\n existing.kind !== 'empty' &&\n existing.kind !== 'horizontal-pass' &&\n existing.kind !== 'arc-land-bridge';\n const crossed =\n occupied ||\n routes.some(\n (other) =>\n other.edge.migrationHash !== arcHash &&\n other.backLane === lane &&\n routeCrossesRow(other, sourceRowIndex, result),\n );\n if (crossed) {\n // The vertical lane was already occupied; tag the crossing with the\n // existing vertical owner's hash and the arc that crosses over it.\n const verticalHash =\n existing !== undefined && 'migrationHash' in existing\n ? existing.migrationHash\n : undefined;\n cells[lane] = {\n kind: 'arc-crossing',\n ...hashProp(verticalHash),\n arcMigrationHash: arcHash,\n };\n } else {\n cells[lane] = { kind: 'horizontal-pass', migrationHash: arcHash };\n }\n }\n cells[backLane] =\n backLane < maxCoSourcedLane\n ? { kind: 'arc-branch-tee', migrationHash: arcHash }\n : { kind: 'arc-branch-corner', migrationHash: arcHash };\n }\n\n const edgeRow = result[edgeRowIndex];\n if (edgeRow !== undefined) {\n // Mutate in place rather than rebuild from empty: a co-sourced arc's body\n // lane may already cross this row, and rebuilding would clobber it.\n const cells = edgeRow.cells;\n ensureCellWidth(cells, backLane + 1);\n // The forward lane at nodeCol is now interrupted by this rollback; tag the\n // vertical-pass with the edge that owns that forward lane.\n const forwardLaneCell = cells[nodeCol];\n const forwardLaneHash =\n forwardLaneCell !== undefined && 'migrationHash' in forwardLaneCell\n ? forwardLaneCell.migrationHash\n : undefined;\n cells[nodeCol] = { kind: 'vertical-pass', ...hashProp(forwardLaneHash) };\n cells[backLane] = {\n kind: 'edge-lane',\n migrationHash: arcHash,\n edgeKind: edge.kind,\n ownsLabel: true,\n adjacency: 'node-skipping-rollback',\n };\n result[edgeRowIndex] = { ...edgeRow, laneIndex: backLane, passThroughLanes: [nodeCol] };\n }\n\n // Fill the arc body vertically from just below the source tee down to the\n // row above the landing, skipping the rollback's own labelled edge row.\n // Starting below the source (rather than below the edge row) keeps a\n // co-sourced arc's lane connected across an earlier co-sourced edge row.\n for (let index = sourceRowIndex + 1; index < targetRowIndex; index += 1) {\n if (index === edgeRowIndex) continue;\n const row = result[index];\n if (row === undefined) continue;\n const cells = row.cells;\n ensureCellWidth(cells, backLane + 1);\n const existing = cells[backLane];\n if (\n existing?.kind !== 'arc-land-corner' &&\n existing?.kind !== 'arc-land-tee' &&\n existing?.kind !== 'arc-land-bridge' &&\n existing?.kind !== 'arc-branch-corner' &&\n existing?.kind !== 'arc-branch-tee' &&\n existing?.kind !== 'arc-crossing'\n ) {\n cells[backLane] = { kind: 'vertical-pass', migrationHash: arcHash };\n }\n }\n\n const targetRow = result[targetRowIndex];\n if (targetRow !== undefined) {\n const cells = targetRow.cells;\n ensureCellWidth(cells, backLane + 1);\n const contractHash = targetRow.contractHash ?? EMPTY_CONTRACT_HASH;\n cells[targetCol] = { kind: 'node', contractHash, arcLand: true };\n for (let lane = targetCol + 1; lane < backLane; lane += 1) {\n // An inner converging arc's own landing junction: the outer arcs' bridge\n // passes through it (`┴`) while its own vertical run closes here.\n if (coLandingLanes.includes(lane)) {\n // Tag the landing tee with the inner arc that closes here.\n const innerArc = routes.find((r) => r.backLane === lane && r.edge.to === edge.to);\n cells[lane] = { kind: 'arc-land-tee', ...hashProp(innerArc?.edge.migrationHash) };\n continue;\n }\n // A bridged lane that carries another arc OR a forward vertical still\n // active at this row must cross over it (`┼`) rather than overwrite it\n // with a bare bridge (`──`).\n const existing = cells[lane];\n const occupied =\n existing !== undefined &&\n existing.kind !== 'empty' &&\n existing.kind !== 'horizontal-pass' &&\n existing.kind !== 'arc-land-bridge' &&\n existing.kind !== 'arc-land-tee';\n const crossed =\n occupied ||\n routes.some(\n (other) =>\n other.edge.migrationHash !== arcHash &&\n other.backLane === lane &&\n routeCrossesRow(other, targetRowIndex, result),\n );\n if (crossed) {\n const verticalHash =\n existing !== undefined && 'migrationHash' in existing\n ? existing.migrationHash\n : undefined;\n cells[lane] = {\n kind: 'arc-crossing',\n ...hashProp(verticalHash),\n arcMigrationHash: arcHash,\n };\n } else {\n cells[lane] = { kind: 'arc-land-bridge', migrationHash: arcHash };\n }\n }\n // Inner converging arcs close as a landing tee so the outermost arc's\n // bridge reads through to the node; only the outermost arc draws `╯`.\n cells[backLane] =\n backLane < maxCoLandingLane\n ? { kind: 'arc-land-tee', migrationHash: arcHash }\n : { kind: 'arc-land-corner', migrationHash: arcHash };\n for (const other of routes) {\n if (other.backLane <= backLane) continue;\n if (!routeCrossesRow(other, targetRowIndex, result)) continue;\n ensureCellWidth(cells, other.backLane + 1);\n const existing = cells[other.backLane];\n if (\n existing?.kind !== 'arc-land-corner' &&\n existing?.kind !== 'arc-land-tee' &&\n existing?.kind !== 'arc-land-bridge' &&\n existing?.kind !== 'node'\n ) {\n // This is a pass-through from another arc still in flight; tag with\n // that arc's hash.\n cells[other.backLane] = {\n kind: 'vertical-pass',\n migrationHash: other.edge.migrationHash,\n };\n }\n }\n }\n }\n\n return result;\n}\n\nfunction collectNodeSkippingRollbacks(\n edges: readonly ClassifiedEdge[],\n position: ReadonlyMap<string, number>,\n): ClassifiedEdge[] {\n return edges.filter(\n (edge) =>\n edge.kind === 'rollback' &&\n classifyEdgeAdjacency(edge, position) === 'node-skipping-rollback',\n );\n}\n\n// ---------------------------------------------------------------------------\n// Lane allocation: one rule for all topologies\n// ---------------------------------------------------------------------------\n\ninterface DownwardGroup {\n readonly target: string;\n readonly edges: ClassifiedEdge[];\n}\n\nfunction layoutComponent(\n componentNodes: readonly string[],\n allEdges: readonly ClassifiedEdge[],\n): {\n rows: MigrationGraphGridRow[];\n nodeColumn: Map<string, number>;\n edgeColumn: Map<string, number>;\n} {\n const componentSet = new Set(componentNodes);\n const edges = allEdges.filter((e) => componentSet.has(e.from) && componentSet.has(e.to));\n\n const forwardChildren = new Map<string, ClassifiedEdge[]>();\n const producersByTo = new Map<string, ClassifiedEdge[]>();\n const rollbacksByFrom = new Map<string, ClassifiedEdge[]>();\n const selfByFrom = new Map<string, ClassifiedEdge[]>();\n for (const edge of edges) {\n if (edge.kind === 'self' || edge.from === edge.to) {\n const bucket = selfByFrom.get(edge.from);\n if (bucket) bucket.push(edge);\n else selfByFrom.set(edge.from, [edge]);\n continue;\n }\n if (edge.kind === 'forward') {\n const children = forwardChildren.get(edge.from);\n if (children) children.push(edge);\n else forwardChildren.set(edge.from, [edge]);\n const producers = producersByTo.get(edge.to);\n if (producers) producers.push(edge);\n else producersByTo.set(edge.to, [edge]);\n continue;\n }\n // rollback\n const bucket = rollbacksByFrom.get(edge.from);\n if (bucket) bucket.push(edge);\n else rollbacksByFrom.set(edge.from, [edge]);\n }\n\n const forwardInDegree = buildForwardInDegree(edges);\n const forwardOutDegree = buildForwardOutDegree(edges);\n const distinctSourceCountByTo = buildDistinctSourceCountByTo(edges);\n\n const order = computeVerticalOrder(componentNodes, forwardChildren, forwardInDegree);\n const position = new Map<string, number>();\n for (let index = 0; index < order.length; index++) {\n const node = order[index];\n if (node !== undefined) position.set(node, index);\n }\n\n const lanes: (string | null)[] = [];\n const rows: MigrationGraphGridRow[] = [];\n const nodeColumn = new Map<string, number>();\n const edgeColumn = new Map<string, number>();\n const producerLaneByHash = new Map<string, number>();\n // Tracks which edge's migrationHash last occupied each lane, so pass-through\n // cells on node/edge/connector rows can carry per-cell identity.\n const laneEdgeByIndex = new Map<number, string>();\n let gridWidth = 1;\n\n function ensureGridWidth(minWidth: number): void {\n if (minWidth > gridWidth) gridWidth = minWidth;\n }\n\n function setLane(index: number, want: string | null): void {\n while (lanes.length <= index) lanes.push(null);\n lanes[index] = want;\n if (want !== null) ensureGridWidth(index + 1);\n }\n\n function activeLaneIndices(): number[] {\n const indices: number[] = [];\n for (let index = 0; index < lanes.length; index++) {\n if (lanes[index] !== null) indices.push(index);\n }\n return indices;\n }\n\n function passThroughExcept(lane: number): number[] {\n return activeLaneIndices().filter((index) => index !== lane);\n }\n\n function leftmostFreeLane(): number {\n for (let index = 0; index < lanes.length; index++) {\n if (lanes[index] === null) return index;\n }\n return lanes.length;\n }\n\n function lanesWanting(contract: string): number[] {\n const indices: number[] = [];\n for (let index = 0; index < lanes.length; index++) {\n if (lanes[index] === contract) indices.push(index);\n }\n return indices;\n }\n\n function emitMergeConnector(contractHash: string, laneIndices: readonly number[]): number {\n const startLane = Math.min(...laneIndices);\n const endLane = Math.max(...laneIndices);\n ensureGridWidth(endLane + 1);\n const activeLanes = new Set(activeLaneIndices());\n const fanTargetLanes = new Set(laneIndices);\n rows.push({\n kind: 'merge-connector',\n contractHash,\n startLane,\n endLane,\n branchCount: laneIndices.length,\n cells: buildMergeConnectorCells(\n startLane,\n endLane,\n fanTargetLanes,\n activeLanes,\n gridWidth,\n laneEdgeByIndex,\n ),\n });\n for (const index of laneIndices) {\n if (index !== startLane) setLane(index, null);\n }\n return startLane;\n }\n\n function emitBranchConnector(\n contractHash: string,\n startLane: number,\n endLane: number,\n branchCount: number,\n fanTargetLanes: readonly number[],\n /** Hash of the first/representative edge for each fan lane (keyed by lane index). */\n fanEdgeHashByLane: ReadonlyMap<number, string>,\n ): void {\n ensureGridWidth(endLane + 1);\n const activeLanes = new Set(activeLaneIndices());\n // Prefer the fanEdgeHashByLane entry for startLane (the downward fanout edge\n // leaving this node) over laneEdgeByIndex, which may still hold the hash of\n // the last skip-rollback emitted into that lane before the branch-connector.\n const trunkEdgeHash = fanEdgeHashByLane.get(startLane) ?? laneEdgeByIndex.get(startLane);\n rows.push({\n kind: 'branch-connector',\n contractHash,\n startLane,\n endLane,\n branchCount,\n cells: buildBranchConnectorCells(\n startLane,\n endLane,\n new Set(fanTargetLanes),\n activeLanes,\n gridWidth,\n trunkEdgeHash,\n fanEdgeHashByLane,\n laneEdgeByIndex,\n ),\n });\n }\n\n function emitEdgeRow(edge: ClassifiedEdge, lane: number, convergenceProducer: boolean): void {\n const passThrough = passThroughExcept(lane);\n const adjacency = classifyEdgeAdjacency(edge, position);\n ensureGridWidth(Math.max(lane, ...passThrough, 0) + 1);\n const row: MigrationGraphGridRow = {\n kind: 'edge',\n edge,\n laneIndex: lane,\n passThroughLanes: passThrough,\n cells: buildEdgeCells(edge, lane, passThrough, adjacency, gridWidth, laneEdgeByIndex),\n };\n rows.push(convergenceProducer ? { ...row, convergenceProducer: true } : row);\n edgeColumn.set(edge.migrationHash, lane);\n if (convergenceProducer) producerLaneByHash.set(edge.migrationHash, lane);\n // Record this edge as the current occupant of its lane so subsequent rows\n // can tag their pass-through cells with the correct owner.\n laneEdgeByIndex.set(lane, edge.migrationHash);\n }\n\n function emitNodeRow(contractHash: string, column: number): void {\n ensureGridWidth(column + 1);\n const passThrough = activeLaneIndices().filter((index) => index !== column);\n rows.push({\n kind: 'node',\n contractHash,\n cells: buildNodeCells(contractHash, column, passThrough, gridWidth, laneEdgeByIndex),\n });\n nodeColumn.set(contractHash, column);\n }\n\n function producerGroups(node: string): DownwardGroup[] {\n const byTarget = new Map<string, DownwardGroup>();\n for (const producer of producersByTo.get(node) ?? []) {\n const group = byTarget.get(producer.from);\n if (group) group.edges.push(producer);\n else byTarget.set(producer.from, { target: producer.from, edges: [producer] });\n }\n const groups = [...byTarget.values()];\n // Lanes are ordered by where their target node lands vertically (soonest →\n // leftmost), which keeps lanes from crossing.\n groups.sort((a, b) => (position.get(a.target) ?? 0) - (position.get(b.target) ?? 0));\n for (const group of groups) {\n group.edges.sort((a, b) => b.dirName.localeCompare(a.dirName));\n }\n return groups;\n }\n\n function processNode(node: string): void {\n const wanting = lanesWanting(node);\n let column: number;\n if (wanting.length >= 2) {\n column = emitMergeConnector(node, wanting);\n } else if (wanting.length === 1) {\n column = wanting[0] ?? 0;\n } else {\n column = leftmostFreeLane();\n }\n\n // Self-edges sit immediately above their node, in its column.\n const selfEdges = [...(selfByFrom.get(node) ?? [])].sort((a, b) =>\n b.dirName.localeCompare(a.dirName),\n );\n for (const selfEdge of selfEdges) emitEdgeRow(selfEdge, column, false);\n\n emitNodeRow(node, column);\n\n const rollbacks = [...(rollbacksByFrom.get(node) ?? [])].sort((a, b) =>\n b.dirName.localeCompare(a.dirName),\n );\n const skipRollbacks: ClassifiedEdge[] = [];\n const adjacentRollbacks: ClassifiedEdge[] = [];\n for (const rollback of rollbacks) {\n if (classifyEdgeAdjacency(rollback, position) === 'node-skipping-rollback') {\n skipRollbacks.push(rollback);\n } else {\n adjacentRollbacks.push(rollback);\n }\n }\n for (const rollback of skipRollbacks) {\n emitEdgeRow(rollback, column, false);\n }\n\n const groups = producerGroups(node);\n const isConvergence = (distinctSourceCountByTo.get(node) ?? 0) >= 2;\n const laneForGroup: number[] = [];\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex];\n if (group === undefined) continue;\n const lane = groupIndex === 0 ? column : leftmostFreeLane();\n laneForGroup[groupIndex] = lane;\n setLane(lane, group.target);\n }\n\n if (groups.length >= 2) {\n const endLane = Math.max(...laneForGroup);\n // Map each fan lane to the representative edge (first in the group) so\n // the branch-connector cells can carry per-cell identity.\n const fanEdgeHashByLane = new Map<number, string>();\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex];\n const lane = laneForGroup[groupIndex];\n if (group === undefined || lane === undefined) continue;\n const firstEdge = group.edges[0];\n if (firstEdge !== undefined) fanEdgeHashByLane.set(lane, firstEdge.migrationHash);\n }\n emitBranchConnector(node, column, endLane, groups.length, laneForGroup, fanEdgeHashByLane);\n\n // Pre-populate laneEdgeByIndex for every fan lane (including lane 0 / trunk) with the\n // representative edge hash BEFORE emitting any edge rows. Without this, when groupIndex=0's\n // edge rows are emitted first, the pass-through cells for groupIndex≥1 lanes carry no hash\n // (laneEdgeByIndex has no entry yet for those lanes) and fall through to whatever annotation\n // the row's default override is — often the wrong colour.\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const fanLane = laneForGroup[groupIndex];\n if (fanLane === undefined) continue;\n const fanHash = fanEdgeHashByLane.get(fanLane);\n if (fanHash !== undefined) {\n laneEdgeByIndex.set(fanLane, fanHash);\n }\n }\n }\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex];\n const lane = laneForGroup[groupIndex];\n if (group === undefined || lane === undefined) continue;\n for (const edge of group.edges) {\n emitEdgeRow(edge, lane, isConvergence);\n }\n }\n\n for (const rollback of adjacentRollbacks) {\n emitEdgeRow(rollback, column, false);\n }\n\n if (groups.length === 0) {\n // A root / leaf: its column lane terminates here.\n setLane(column, null);\n }\n }\n\n for (const node of order) processNode(node);\n\n const refined = refineAdjacency(\n rows,\n nodeColumn,\n position,\n forwardInDegree,\n forwardOutDegree,\n edges,\n producerLaneByHash,\n );\n const skipRollbacks = collectNodeSkippingRollbacks(edges, position);\n const routed = applySkipRollbackRouting(refined, skipRollbacks, position, nodeColumn, edgeColumn);\n\n return {\n rows: routed,\n nodeColumn,\n edgeColumn,\n };\n}\n\nexport function buildMigrationGraphLayout(\n rowModel: MigrationGraphRowModel,\n): MigrationGraphGridModel {\n if (rowModel.nodes.length === 0) {\n return { rows: [], nodeColumn: new Map(), edgeColumn: new Map() };\n }\n\n const components = splitComponents(rowModel.nodes);\n const allRows: MigrationGraphGridRow[] = [];\n const nodeColumn = new Map<string, number>();\n const edgeColumn = new Map<string, number>();\n\n for (let componentIndex = 0; componentIndex < components.length; componentIndex++) {\n if (componentIndex > 0) {\n allRows.push({ kind: 'component-separator', cells: [] });\n }\n\n const component = components[componentIndex];\n if (component === undefined || component.length === 0) continue;\n\n const result = layoutComponent(component, rowModel.edges);\n allRows.push(...result.rows);\n for (const [hash, column] of result.nodeColumn) nodeColumn.set(hash, column);\n for (const [hash, column] of result.edgeColumn) edgeColumn.set(hash, column);\n }\n\n return { rows: allRows, nodeColumn, edgeColumn };\n}\n","import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport type { MigrationListEntry } from './migration-list-types';\n\nexport type MigrationEdgeKind = 'forward' | 'rollback' | 'self';\n\nexport interface MigrationListGraphTopology {\n readonly kindByMigrationHash: ReadonlyMap<string, MigrationEdgeKind>;\n readonly forwardInDegree: ReadonlyMap<string, number>;\n readonly forwardOutDegree: ReadonlyMap<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Shared classifier — operates on a normalized edge shape for MigrationGraph.\n// ---------------------------------------------------------------------------\n\ninterface NormalizedEdge {\n readonly hash: string;\n readonly from: string;\n readonly to: string;\n readonly dirName: string;\n}\n\nfunction compareDirNameDesc(a: NormalizedEdge, b: NormalizedEdge): number {\n return b.dirName.localeCompare(a.dirName);\n}\n\nfunction bumpDegree(map: Map<string, number>, key: string): void {\n map.set(key, (map.get(key) ?? 0) + 1);\n}\n\nfunction compareNodesRootFirst(a: string, b: string): number {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n}\n\n/**\n * Shortest-path distance of each node from the forward roots, over the given\n * candidate edges. Roots are the in-degree-0 nodes (baseline first, then lex);\n * a rooted component therefore distances every node by how many forward steps\n * it sits from a root. A component with no root (a pure cycle) is seeded from\n * its single lexically-smallest node so the cycle still gets a stable layering.\n *\n * Crucially this is *shortest* path, not longest: a backward (rollback) edge\n * `deep → shallow` never offers a shorter route to the already-shallower\n * target, so it is inert here. Distances are thus stable whether or not the\n * rollbacks are still in the candidate set — which is what lets the peel below\n * tell a genuine back-edge (target strictly shallower than source) apart from a\n * forward edge that merely happens to share the back-edge's cycle.\n */\nfunction forwardDistances(\n nodes: ReadonlySet<string>,\n candidates: readonly NormalizedEdge[],\n): Map<string, number> {\n const inDegree = new Map<string, number>();\n for (const node of nodes) {\n inDegree.set(node, 0);\n }\n for (const edge of candidates) {\n bumpDegree(inDegree, edge.to);\n }\n\n const roots = [...nodes].filter((node) => (inDegree.get(node) ?? 0) === 0);\n roots.sort(compareNodesRootFirst);\n const seeds = roots.length > 0 ? roots : [...nodes].sort(compareNodesRootFirst).slice(0, 1);\n\n const dist = new Map<string, number>();\n for (const seed of seeds) {\n dist.set(seed, 0);\n }\n\n const maxPasses = nodes.size;\n for (let pass = 0; pass < maxPasses; pass++) {\n let changed = false;\n for (const edge of candidates) {\n const base = dist.get(edge.from);\n if (base === undefined) continue;\n const next = base + 1;\n if (next < (dist.get(edge.to) ?? Number.POSITIVE_INFINITY)) {\n dist.set(edge.to, next);\n changed = true;\n }\n }\n if (!changed) break;\n }\n\n for (const node of nodes) {\n if (!dist.has(node)) {\n dist.set(node, 0);\n }\n }\n\n return dist;\n}\n\nfunction canReachForward(\n start: string,\n goal: string,\n candidates: readonly NormalizedEdge[],\n): boolean {\n if (start === goal) return true;\n\n const outgoing = new Map<string, string[]>();\n for (const edge of candidates) {\n const bucket = outgoing.get(edge.from);\n if (bucket) bucket.push(edge.to);\n else outgoing.set(edge.from, [edge.to]);\n }\n\n const visited = new Set<string>([start]);\n const queue = [start];\n while (queue.length > 0) {\n const node = queue.shift();\n if (node === undefined) continue;\n for (const next of outgoing.get(node) ?? []) {\n if (next === goal) return true;\n if (!visited.has(next)) {\n visited.add(next);\n queue.push(next);\n }\n }\n }\n\n return false;\n}\n\n/**\n * Demote node-skipping rollbacks left forward by the DFS. An edge `from → to`\n * is a rollback exactly when both hold:\n * 1. `to` is a forward-ancestor of `from` — `to` can still reach `from` over\n * the other forward edges, so the edge closes a cycle; and\n * 2. `to` is strictly shallower than `from` (smaller forward distance) — the\n * edge points back toward the root rather than advancing history.\n *\n * Condition 2 is the discriminator: in a cycle created by a rollback every edge\n * satisfies condition 1, but only the rollback itself runs deep → shallow. The\n * forward chain edges run shallow → deep and are never peeled, however many\n * rollbacks converge on the same target. Tight back-edges whose source and\n * target sit at the same distance (mutual two-node cycles) are already resolved\n * by the DFS immediate-parent rule, so they never reach this pass. One edge is\n * peeled per iteration (dirName-descending tie-break) and distances/reachability\n * are recomputed, making the outcome independent of edge input order.\n */\nfunction peelNodeSkippingRollbacks(\n nodes: ReadonlySet<string>,\n kindByMigrationHash: Map<string, MigrationEdgeKind>,\n nonSelf: readonly NormalizedEdge[],\n): void {\n let candidates = nonSelf.filter((edge) => kindByMigrationHash.get(edge.hash) === 'forward');\n\n while (candidates.length > 0) {\n const dist = forwardDistances(nodes, candidates);\n const backEdges = candidates.filter((edge) => {\n const toDist = dist.get(edge.to) ?? 0;\n const fromDist = dist.get(edge.from) ?? 0;\n if (toDist >= fromDist) return false;\n const without = candidates.filter((candidate) => candidate !== edge);\n return canReachForward(edge.to, edge.from, without);\n });\n if (backEdges.length === 0) break;\n\n backEdges.sort(compareDirNameDesc);\n const rollback = backEdges[0];\n if (rollback === undefined) break;\n\n kindByMigrationHash.set(rollback.hash, 'rollback');\n candidates = candidates.filter((edge) => edge !== rollback);\n }\n}\n\n/**\n * DFS with dirName-descending traversal. A GRAY target is a rollback only when it\n * is the immediate DFS parent of the source — cross-links to other GRAY nodes\n * stay forward. A follow-up peel pass demotes node-skipping rollbacks (target is\n * a forward-ancestor of the source and sits strictly shallower than it).\n */\nfunction classifyNormalizedEdges(edges: readonly NormalizedEdge[]): MigrationListGraphTopology {\n const nodes = new Set<string>();\n const kindByMigrationHash = new Map<string, MigrationEdgeKind>();\n const outgoingByFrom = new Map<string, NormalizedEdge[]>();\n const nonSelf: NormalizedEdge[] = [];\n\n for (const edge of edges) {\n nodes.add(edge.from);\n nodes.add(edge.to);\n\n if (edge.from === edge.to) {\n kindByMigrationHash.set(edge.hash, 'self');\n continue;\n }\n\n nonSelf.push(edge);\n const bucket = outgoingByFrom.get(edge.from);\n if (bucket) bucket.push(edge);\n else outgoingByFrom.set(edge.from, [edge]);\n }\n\n for (const bucket of outgoingByFrom.values()) {\n bucket.sort(compareDirNameDesc);\n }\n\n const nonSelfInDegree = new Map<string, number>();\n for (const node of nodes) {\n nonSelfInDegree.set(node, 0);\n }\n for (const bucket of outgoingByFrom.values()) {\n for (const edge of bucket) {\n bumpDegree(nonSelfInDegree, edge.to);\n }\n }\n\n const dfsRoots: string[] = [];\n for (const node of nodes) {\n if ((nonSelfInDegree.get(node) ?? 0) === 0) {\n dfsRoots.push(node);\n }\n }\n dfsRoots.sort((a, b) => {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n });\n if (dfsRoots.length === 0) {\n dfsRoots.push(...[...nodes].sort((a, b) => a.localeCompare(b)));\n }\n\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n const dfsParent = new Map<string, string | undefined>();\n for (const node of nodes) {\n color.set(node, WHITE);\n }\n\n interface Frame {\n node: string;\n outgoing: readonly NormalizedEdge[];\n index: number;\n }\n const stack: Frame[] = [];\n\n function isImmediateDfsParent(ancestor: string, node: string): boolean {\n return dfsParent.get(node) === ancestor;\n }\n\n function pushFrame(node: string, parent: string | undefined): void {\n color.set(node, GRAY);\n dfsParent.set(node, parent);\n stack.push({ node, outgoing: outgoingByFrom.get(node) ?? [], index: 0 });\n }\n\n function runDfsFrom(root: string): void {\n if (color.get(root) !== WHITE) return;\n pushFrame(root, undefined);\n\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n if (frame === undefined) break;\n if (frame.index >= frame.outgoing.length) {\n color.set(frame.node, BLACK);\n stack.pop();\n continue;\n }\n\n const edge = frame.outgoing[frame.index];\n frame.index += 1;\n if (edge === undefined) continue;\n\n const v = edge.to;\n const vColor = color.get(v);\n if (vColor === GRAY && isImmediateDfsParent(v, frame.node)) {\n kindByMigrationHash.set(edge.hash, 'rollback');\n } else {\n kindByMigrationHash.set(edge.hash, 'forward');\n if (vColor === WHITE) {\n pushFrame(v, frame.node);\n }\n }\n }\n }\n\n for (const root of dfsRoots) {\n runDfsFrom(root);\n }\n const remainingWhite = [...nodes].filter((node) => color.get(node) === WHITE);\n remainingWhite.sort((a, b) => a.localeCompare(b));\n for (const root of remainingWhite) {\n runDfsFrom(root);\n }\n\n peelNodeSkippingRollbacks(nodes, kindByMigrationHash, nonSelf);\n\n const forwardInDegree = new Map<string, number>();\n const forwardOutDegree = new Map<string, number>();\n\n for (const edge of edges) {\n if (kindByMigrationHash.get(edge.hash) !== 'forward') continue;\n bumpDegree(forwardOutDegree, edge.from);\n bumpDegree(forwardInDegree, edge.to);\n }\n\n return {\n kindByMigrationHash,\n forwardInDegree,\n forwardOutDegree,\n };\n}\n\nfunction canonicalFrom(from: string | null): string {\n return from ?? EMPTY_CONTRACT_HASH;\n}\n\n/**\n * Classify forward/rollback/self for a Tier-2 `MigrationListEntry[]` edge set.\n */\nexport function classifyMigrationListGraphTopology(\n entries: readonly MigrationListEntry[],\n): MigrationListGraphTopology {\n const normalized: NormalizedEdge[] = entries.map((entry) => ({\n hash: entry.hash,\n from: canonicalFrom(entry.fromContract),\n to: entry.toContract,\n dirName: entry.name,\n }));\n return classifyNormalizedEdges(normalized);\n}\n\n/**\n * Classify forward/rollback/self for a `MigrationGraph` edge set (Tier-3).\n */\nexport function classifyMigrationGraphTopology(graph: MigrationGraph): MigrationListGraphTopology {\n const normalized: NormalizedEdge[] = [];\n for (const edges of graph.forwardChain.values()) {\n for (const edge of edges) {\n normalized.push({\n hash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n dirName: edge.dirName,\n });\n }\n }\n return classifyNormalizedEdges(normalized);\n}\n","import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport {\n classifyMigrationGraphTopology,\n type MigrationEdgeKind,\n type MigrationListGraphTopology,\n} from './migration-list-graph-topology';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * A migration edge with its forward/rollback/self classification resolved.\n * `from` and `to` are contract hashes (EMPTY_CONTRACT_HASH for the baseline).\n */\nexport interface ClassifiedEdge {\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly dirName: string;\n readonly kind: MigrationEdgeKind;\n}\n\n/**\n * The pure-data output of the row-model stage.\n *\n * `nodes` is the vertical ordering of contract nodes: index 0 is the topmost\n * row (the tip), the last non-null entry is the bottommost root. `null`\n * sentinels separate disjoint components (the blank row in the rendered\n * output). Ordering within each component is deterministic: longest forward-\n * path rank from forward roots (tips at rank max, roots at 0), with lex-\n * ascending tie-break among same-rank siblings.\n *\n * `edges` carries every classified migration. `edgesByFrom` and `edgesByTo`\n * are pre-built lookup maps for the column allocator.\n */\nexport interface MigrationGraphRowModel {\n readonly nodes: readonly (string | null)[];\n readonly edges: readonly ClassifiedEdge[];\n readonly edgesByFrom: ReadonlyMap<string, readonly ClassifiedEdge[]>;\n readonly edgesByTo: ReadonlyMap<string, readonly ClassifiedEdge[]>;\n}\n\nexport interface BuildMigrationGraphRowsOptions {\n readonly contractHash?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Weak connectivity — identify disjoint components\n// ---------------------------------------------------------------------------\n\n/**\n * Return the weakly-connected components of `graph` as an array of node sets,\n * ordered so the component containing EMPTY_CONTRACT_HASH comes first (if\n * present), with remaining components sorted by their lex-smallest node hash.\n */\nfunction weaklyConnectedComponents(graph: MigrationGraph): readonly ReadonlySet<string>[] {\n const visited = new Set<string>();\n const adjacency = new Map<string, string[]>();\n\n function addAdjacent(a: string, b: string): void {\n const aList = adjacency.get(a);\n if (aList) aList.push(b);\n else adjacency.set(a, [b]);\n const bList = adjacency.get(b);\n if (bList) bList.push(a);\n else adjacency.set(b, [a]);\n }\n\n for (const edges of graph.forwardChain.values()) {\n for (const edge of edges) {\n if (edge.from !== edge.to) {\n addAdjacent(edge.from, edge.to);\n }\n }\n }\n\n // Ensure all nodes (including isolated self-loops) are reachable\n for (const node of graph.nodes) {\n if (!adjacency.has(node)) {\n adjacency.set(node, []);\n }\n }\n\n const components: Set<string>[] = [];\n\n function bfsComponent(start: string): Set<string> {\n const component = new Set<string>();\n const queue = [start];\n while (queue.length > 0) {\n const node = queue.shift();\n if (node === undefined || visited.has(node)) continue;\n visited.add(node);\n component.add(node);\n for (const neighbor of adjacency.get(node) ?? []) {\n if (!visited.has(neighbor)) {\n queue.push(neighbor);\n }\n }\n }\n return component;\n }\n\n // Deterministic: visit nodes in a fixed order (EMPTY first, then lex)\n const allNodes = [...graph.nodes].sort((a, b) => {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n });\n\n for (const node of allNodes) {\n if (!visited.has(node)) {\n components.push(bfsComponent(node));\n }\n }\n\n // Order: EMPTY component first, others by lex-smallest node hash\n components.sort((a, b) => {\n const aHasEmpty = a.has(EMPTY_CONTRACT_HASH);\n const bHasEmpty = b.has(EMPTY_CONTRACT_HASH);\n if (aHasEmpty && !bHasEmpty) return -1;\n if (!aHasEmpty && bHasEmpty) return 1;\n const aMin = [...a].sort((x, y) => x.localeCompare(y))[0] ?? '';\n const bMin = [...b].sort((x, y) => x.localeCompare(y))[0] ?? '';\n return aMin.localeCompare(bMin);\n });\n\n return components;\n}\n\n// ---------------------------------------------------------------------------\n// Longest forward-path node ordering within a component\n// ---------------------------------------------------------------------------\n\nfunction forwardRootsInComponent(\n componentNodes: ReadonlySet<string>,\n topology: MigrationListGraphTopology,\n): readonly string[] {\n const roots: string[] = [];\n for (const node of componentNodes) {\n if ((topology.forwardInDegree.get(node) ?? 0) === 0) {\n roots.push(node);\n }\n }\n roots.sort((a, b) => {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n });\n if (roots.length > 0) return roots;\n\n return [...componentNodes].sort((a, b) => {\n if (a === EMPTY_CONTRACT_HASH) return -1;\n if (b === EMPTY_CONTRACT_HASH) return 1;\n return a.localeCompare(b);\n });\n}\n\nfunction compareNodesTipsFirst(a: string, b: string, rank: ReadonlyMap<string, number>): number {\n const rankA = rank.get(a) ?? 0;\n const rankB = rank.get(b) ?? 0;\n if (rankA !== rankB) return rankB - rankA;\n if (a === EMPTY_CONTRACT_HASH) return 1;\n if (b === EMPTY_CONTRACT_HASH) return -1;\n return a.localeCompare(b);\n}\n\n/**\n * Layer nodes by longest forward-path rank from forward roots within the\n * component. Rank 0 is the root (bottom row); the maximum rank is the tip\n * (top row). Emits rank-descending with lex-ascending tie-break among siblings\n * at the same rank — stable across edge-insertion order and correct under\n * diamonds, cross-links, and rollbacks.\n */\nfunction maxRank(rank: ReadonlyMap<string, number>): number {\n let max = 0;\n for (const value of rank.values()) {\n if (value > max) max = value;\n }\n return max;\n}\n\nfunction layerNodesByLongestForwardPath(\n componentNodes: ReadonlySet<string>,\n topology: MigrationListGraphTopology,\n graph: MigrationGraph,\n contractHash: string | undefined,\n): readonly string[] {\n const forwardOut = new Map<string, string[]>();\n\n for (const node of componentNodes) {\n forwardOut.set(node, []);\n }\n\n for (const edges of graph.forwardChain.values()) {\n for (const edge of edges) {\n if (!componentNodes.has(edge.from) || !componentNodes.has(edge.to)) continue;\n if (edge.from === edge.to) continue;\n if (topology.kindByMigrationHash.get(edge.migrationHash) !== 'forward') continue;\n const bucket = forwardOut.get(edge.from);\n if (bucket) bucket.push(edge.to);\n }\n }\n\n const roots = forwardRootsInComponent(componentNodes, topology);\n const rank = new Map<string, number>();\n for (const root of roots) {\n rank.set(root, 0);\n }\n\n const maxPasses = componentNodes.size;\n for (let pass = 0; pass < maxPasses; pass++) {\n let changed = false;\n for (const node of componentNodes) {\n const base = rank.get(node);\n if (base === undefined) continue;\n for (const to of forwardOut.get(node) ?? []) {\n const next = base + 1;\n const prev = rank.get(to) ?? -1;\n if (next > prev) {\n rank.set(to, next);\n changed = true;\n }\n }\n }\n if (!changed) break;\n }\n\n for (const node of componentNodes) {\n if (!rank.has(node)) {\n rank.set(node, 0);\n }\n }\n\n if (\n contractHash !== undefined &&\n contractHash !== EMPTY_CONTRACT_HASH &&\n componentNodes.has(contractHash) &&\n (forwardOut.get(contractHash) ?? []).length === 0\n ) {\n rank.set(contractHash, maxRank(rank) + 1);\n }\n\n return [...componentNodes].sort((a, b) => compareNodesTipsFirst(a, b, rank));\n}\n\n// ---------------------------------------------------------------------------\n// Public builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build the row model from a tolerant `MigrationGraph`.\n *\n * The row model is the first pure-data stage of the `migration graph` render\n * pipeline. It:\n * - classifies every edge as `forward`, `rollback`, or `self`;\n * - produces a deterministic vertical node ordering (tips at index 0, roots\n * at the end) within each weakly-connected component;\n * - separates disjoint components with `null` sentinels;\n * - optionally prepends a detached current contract as its own single-node\n * component when `contractHash` is not already in the graph.\n *\n * No columns, no lane allocation, no glyphs, no rendering.\n */\n/**\n * Resolve the detached current contract, if any: a real contract (not the\n * empty baseline) that no migration on disk produces, so it is absent from\n * the graph. Such a contract renders as a floating node rather than\n * decorating an existing one. Returns the hash when detached, else undefined.\n */\nfunction detachedContractHash(\n graph: MigrationGraph,\n contractHash: string | undefined,\n): string | undefined {\n return contractHash !== undefined &&\n contractHash !== EMPTY_CONTRACT_HASH &&\n !graph.nodes.has(contractHash)\n ? contractHash\n : undefined;\n}\n\nfunction isForwardLeaf(node: string, edges: readonly ClassifiedEdge[]): boolean {\n return !edges.some((e) => e.kind === 'forward' && e.from === node && e.from !== e.to);\n}\n\nfunction forwardReachableFrom(\n start: string,\n forwardTo: ReadonlyMap<string, readonly string[]>,\n): ReadonlySet<string> {\n const reachable = new Set<string>([start]);\n const queue = [start];\n while (queue.length > 0) {\n const node = queue.shift();\n if (node === undefined) continue;\n for (const next of forwardTo.get(node) ?? []) {\n if (!reachable.has(next)) {\n reachable.add(next);\n queue.push(next);\n }\n }\n }\n return reachable;\n}\n\nfunction buildForwardToMap(edges: readonly ClassifiedEdge[]): Map<string, string[]> {\n const forwardTo = new Map<string, string[]>();\n for (const edge of edges) {\n if (edge.kind !== 'forward' || edge.from === edge.to) continue;\n const bucket = forwardTo.get(edge.from);\n if (bucket) bucket.push(edge.to);\n else forwardTo.set(edge.from, [edge.to]);\n }\n return forwardTo;\n}\n\nfunction sortEdgesForContractHashTrunk(\n edges: ClassifiedEdge[],\n contractHash: string | undefined,\n): ClassifiedEdge[] {\n if (\n contractHash === undefined ||\n contractHash === EMPTY_CONTRACT_HASH ||\n !isForwardLeaf(contractHash, edges)\n ) {\n return edges;\n }\n\n const preferredLeaf = contractHash;\n const forwardTo = buildForwardToMap(edges);\n const reachability = new Map<string, ReadonlySet<string>>();\n function canReachContractHash(from: string): boolean {\n let cached = reachability.get(from);\n if (cached === undefined) {\n cached = forwardReachableFrom(from, forwardTo);\n reachability.set(from, cached);\n }\n return cached.has(preferredLeaf);\n }\n\n function trunkBias(edge: ClassifiedEdge): number {\n if (edge.kind !== 'forward' || edge.from === edge.to) return 0;\n if (edge.to === preferredLeaf) return 2;\n if (canReachContractHash(edge.to)) return 1;\n return 0;\n }\n\n return edges\n .map((edge, index) => ({ edge, index, bias: trunkBias(edge) }))\n .sort((a, b) => {\n if (a.edge.from !== b.edge.from) return a.index - b.index;\n if (a.bias !== b.bias) return b.bias - a.bias;\n return a.index - b.index;\n })\n .map(({ edge }) => edge);\n}\n\nfunction rebuildEdgeLookupMaps(edges: readonly ClassifiedEdge[]): {\n edgesByFrom: Map<string, ClassifiedEdge[]>;\n edgesByTo: Map<string, ClassifiedEdge[]>;\n} {\n const edgesByFrom = new Map<string, ClassifiedEdge[]>();\n const edgesByTo = new Map<string, ClassifiedEdge[]>();\n for (const classified of edges) {\n const fromBucket = edgesByFrom.get(classified.from);\n if (fromBucket) fromBucket.push(classified);\n else edgesByFrom.set(classified.from, [classified]);\n\n const toBucket = edgesByTo.get(classified.to);\n if (toBucket) toBucket.push(classified);\n else edgesByTo.set(classified.to, [classified]);\n }\n return { edgesByFrom, edgesByTo };\n}\n\nexport function buildMigrationGraphRows(\n graph: MigrationGraph,\n options: BuildMigrationGraphRowsOptions = {},\n): MigrationGraphRowModel {\n const emptyModel: MigrationGraphRowModel = {\n nodes: [],\n edges: [],\n edgesByFrom: new Map(),\n edgesByTo: new Map(),\n };\n\n if (graph.nodes.size === 0) {\n const detached = detachedContractHash(graph, options.contractHash);\n return detached !== undefined ? { ...emptyModel, nodes: [detached] } : emptyModel;\n }\n\n // 1. Classify all edges (shared classifier: DFS plus a peel pass that demotes\n // node-skipping rollbacks, so the forward subgraph is acyclic)\n const topology = classifyMigrationGraphTopology(graph);\n\n // 2. Build classified edge list\n const edges: ClassifiedEdge[] = [];\n\n for (const edgeList of graph.forwardChain.values()) {\n for (const edge of edgeList) {\n const kind = topology.kindByMigrationHash.get(edge.migrationHash) ?? 'forward';\n edges.push({\n migrationHash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n dirName: edge.dirName,\n kind,\n });\n }\n }\n\n const sortedEdges = sortEdgesForContractHashTrunk(edges, options.contractHash);\n const { edgesByFrom, edgesByTo } = rebuildEdgeLookupMaps(sortedEdges);\n\n // 3. Find weakly-connected components (ordered: EMPTY first, then lex)\n const components = weaklyConnectedComponents(graph);\n\n // 4. Layer nodes by longest forward path per component, separate with null\n const nodes: (string | null)[] = [];\n for (let i = 0; i < components.length; i++) {\n if (i > 0) nodes.push(null);\n const component = components[i];\n if (component === undefined) continue;\n const ordered = layerNodesByLongestForwardPath(\n component,\n topology,\n graph,\n options.contractHash,\n );\n for (const node of ordered) {\n nodes.push(node);\n }\n }\n\n const detached = detachedContractHash(graph, options.contractHash);\n if (detached !== undefined) {\n if (nodes.length > 0) {\n nodes.unshift(null);\n }\n nodes.unshift(detached);\n }\n\n return {\n nodes,\n edges: sortedEdges,\n edgesByFrom,\n edgesByTo,\n };\n}\n","import { createColors } from 'colorette';\nimport type { StructuralCell } from './migration-graph-layout';\n\nexport type LaneColorizer = (text: string) => string;\n\nconst { magenta, cyan, green, yellow, blueBright, red } = createColors({ useColor: true });\n\nexport const LANE_COLOR_CYCLE: readonly LaneColorizer[] = [\n magenta,\n cyan,\n green,\n yellow,\n blueBright,\n red,\n];\n\n/**\n * The leftmost lane (column 0) renders neutral — no palette hue. Columns ≥ 1\n * rotate through {@link LANE_COLOR_CYCLE}.\n */\nexport const NEUTRAL_LANE_COLUMN = 0;\n\n/**\n * The hue for a gutter column. The leftmost lane (column 0) is **neutral** — it\n * has nothing to be told apart from in the common single-lane linear case, so\n * the renderer dims it rather than tinting it; the rotating palette is reserved\n * for columns ≥ 1 (where a second lane exists to distinguish). Callers must dim\n * column 0 themselves; this returns identity for it as a guard. A lane freed and\n * reused by a later branch keeps its column's hue — coloring is by position, not\n * branch identity, exactly like `git log --graph`.\n */\nexport function laneColorForColumn(column: number): LaneColorizer {\n if (column <= NEUTRAL_LANE_COLUMN) {\n return (text) => text;\n }\n const colorizer = LANE_COLOR_CYCLE[(column - 1) % LANE_COLOR_CYCLE.length];\n return colorizer ?? ((text) => text);\n}\n\n/**\n * Style a structural glyph by its resolved colour column. Column 0 and the\n * neutral sentinel render dim (`dimLane`); columns ≥ 1 take a palette hue.\n */\nexport function stylerForLaneColumn(\n colorColumn: number,\n colorize: boolean,\n dimLane: (text: string) => string,\n): LaneColorizer {\n if (!colorize || colorColumn <= NEUTRAL_LANE_COLUMN) {\n return dimLane;\n }\n return laneColorForColumn(colorColumn);\n}\n\n/**\n * The colour-source column for each cell of a row, resolved together because a\n * routed back-arc spans columns and must read as **one hue** rather than a\n * per-column \"rainbow\".\n */\nexport interface RowArcLaneColors {\n /** Colour column for a cell's structural glyph (lane / spine / arc body). */\n readonly lane: readonly number[];\n /** Colour column for a node arc-pair's connector half (`◂` / `─`). */\n readonly connector: readonly number[];\n /**\n * Colour column for the trailing `─` of a landing tee (`┴─`). The junction\n * (`lane`) keeps its own column; the dash leads into the next converging arc.\n */\n readonly dash: readonly number[];\n}\n\n/**\n * Resolve per-cell colour columns for a node/arc row. Scanning right-to-left\n * lets each arc segment inherit the hue of the arc it leads into.\n */\nexport function resolveRowArcLaneColors(cells: readonly StructuralCell[]): RowArcLaneColors {\n const lane = new Array<number>(cells.length);\n const connector = new Array<number>(cells.length);\n const dash = new Array<number>(cells.length);\n let arcCorner = NEUTRAL_LANE_COLUMN;\n let landingAnchor = NEUTRAL_LANE_COLUMN;\n for (let column = cells.length - 1; column >= 0; column--) {\n const cell = cells[column];\n connector[column] = landingAnchor !== NEUTRAL_LANE_COLUMN ? landingAnchor : arcCorner;\n switch (cell?.kind) {\n case 'arc-branch-corner':\n arcCorner = column;\n lane[column] = column;\n dash[column] = column;\n break;\n case 'arc-land-corner':\n arcCorner = column;\n landingAnchor = column;\n lane[column] = column;\n dash[column] = column;\n break;\n case 'arc-branch-tee':\n lane[column] = column;\n dash[column] = column;\n break;\n case 'arc-land-tee':\n lane[column] = column;\n dash[column] = landingAnchor === NEUTRAL_LANE_COLUMN ? column : landingAnchor;\n landingAnchor = column;\n break;\n case 'arc-crossing':\n case 'arc-land-bridge': {\n const served = landingAnchor !== NEUTRAL_LANE_COLUMN ? landingAnchor : arcCorner;\n lane[column] = served;\n dash[column] = served;\n break;\n }\n case 'horizontal-pass':\n lane[column] = arcCorner === NEUTRAL_LANE_COLUMN ? column : arcCorner;\n dash[column] = lane[column] ?? column;\n break;\n case 'node':\n lane[column] = column;\n dash[column] = column;\n arcCorner = NEUTRAL_LANE_COLUMN;\n landingAnchor = NEUTRAL_LANE_COLUMN;\n break;\n default:\n lane[column] = column;\n dash[column] = column;\n arcCorner = NEUTRAL_LANE_COLUMN;\n landingAnchor = NEUTRAL_LANE_COLUMN;\n }\n }\n return { lane, connector, dash };\n}\n\n/**\n * Per-cell colour for a forward branch/merge connector row, split into the\n * cell's junction `glyph` and its trailing `dash`.\n */\nexport interface ConnectorLaneColors {\n /** Colour column for a cell's junction glyph (`├` / `┬` / `┴` / `╮` / `╯`). */\n readonly glyph: readonly number[];\n /** Colour column for a tee's trailing `─` — the branch it leads into. */\n readonly dash: readonly number[];\n}\n\n/**\n * Resolve per-cell connector colours. Scanning right-to-left, a corner or an\n * intermediate tee anchors its own lane, but a tee's trailing dash leads into\n * the branch on its right.\n */\nexport function resolveConnectorLaneColors(\n cells: readonly StructuralCell[],\n startLane: number,\n): ConnectorLaneColors {\n const glyph = new Array<number>(cells.length);\n const dash = new Array<number>(cells.length);\n let owner = NEUTRAL_LANE_COLUMN;\n for (let column = cells.length - 1; column >= 0; column--) {\n const cell = cells[column];\n switch (cell?.kind) {\n case 'branch-corner':\n case 'merge-corner':\n owner = column;\n glyph[column] = column;\n dash[column] = column;\n break;\n case 'branch-tee':\n case 'merge-tee':\n if (column === startLane) {\n const served = owner === NEUTRAL_LANE_COLUMN ? column : owner;\n glyph[column] = column;\n dash[column] = served;\n } else {\n dash[column] = owner === NEUTRAL_LANE_COLUMN ? column : owner;\n glyph[column] = column;\n owner = column;\n }\n break;\n case 'arc-crossing':\n glyph[column] = column;\n dash[column] = owner === NEUTRAL_LANE_COLUMN ? column : owner;\n owner = column;\n break;\n case 'horizontal-pass': {\n const served = owner === NEUTRAL_LANE_COLUMN ? column : owner;\n glyph[column] = served;\n dash[column] = served;\n break;\n }\n default:\n glyph[column] = column;\n dash[column] = column;\n }\n }\n return { glyph, dash };\n}\n","import stringWidth from 'string-width';\nimport type { GlyphMode } from '../glyph-mode';\n\nexport const MIGRATION_LIST_HASH_WIDTH = 7;\nexport const MIGRATION_LIST_EMPTY_SOURCE = '∅';\nexport const MIGRATION_LIST_ASCII_EMPTY_SOURCE = '-';\nexport const MIGRATION_LIST_FORWARD_EDGE_GLYPH = '→';\nexport const MIGRATION_LIST_ASCII_FORWARD_EDGE_GLYPH = '->';\n\nexport function migrationListForwardArrow(glyphMode: GlyphMode): string {\n return glyphMode === 'ascii'\n ? MIGRATION_LIST_ASCII_FORWARD_EDGE_GLYPH\n : MIGRATION_LIST_FORWARD_EDGE_GLYPH;\n}\n\nexport function migrationListEmptySource(glyphMode: GlyphMode): string {\n return glyphMode === 'ascii' ? MIGRATION_LIST_ASCII_EMPTY_SOURCE : MIGRATION_LIST_EMPTY_SOURCE;\n}\n\nexport function abbreviateContractHash(hash: string): string {\n const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;\n return stripped.slice(0, MIGRATION_LIST_HASH_WIDTH);\n}\n\nexport function padFromHashColumn(text: string, width: number): string {\n const padding = Math.max(0, width - stringWidth(text));\n return `${' '.repeat(padding)}${text}`;\n}\n","import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport type { GlyphMode } from '../glyph-mode';\nimport {\n computeGlobalMaxDirNameWidth,\n computeGlobalMaxEdgeTreePrefixWidth,\n indentMigrationGraphTreeBlock,\n renderMigrationGraphSpaceTree,\n} from './migration-graph-space-render';\nimport type { MigrationEdgeAnnotation } from './migration-graph-tree-render';\nimport type { MigrationListEntry, MigrationListResult } from './migration-list-types';\n\nexport type { GlyphMode } from '../glyph-mode';\nexport type { MigrationEdgeKind } from './migration-list-graph-topology';\nexport type {\n MigrationListEntry,\n MigrationListResult,\n MigrationSpaceListEntry,\n} from './migration-list-types';\n\n/**\n * Semantic styler for `migration list` output tokens. Token-typed so\n * the renderer composes presentation-neutral fragments and the styler\n * decides how each token kind is decorated (ANSI codes, plain text,\n * etc.). The renderer pads with raw spaces *outside* styled tokens so\n * visible column widths stay stable regardless of what the styler\n * emits — adding ANSI escape sequences never disturbs alignment.\n *\n * `invariants` and `refs` receive the underlying string arrays rather\n * than a pre-joined string so per-element styling (e.g. distinguishing\n * the live-DB `db` marker from user-named refs) is possible without\n * having to re-parse a joined block.\n */\nexport interface MigrationListStyler {\n kind(text: string): string;\n dirName(text: string): string;\n sourceHash(text: string): string;\n destHash(text: string): string;\n glyph(text: string): string;\n lane(text: string): string;\n invariants(ids: readonly string[]): string;\n refs(names: readonly string[]): string;\n spaceHeading(text: string): string;\n summary(text: string): string;\n emptyState(text: string): string;\n}\n\nexport const IDENTITY_MIGRATION_LIST_STYLER: MigrationListStyler = {\n kind: (text) => text,\n dirName: (text) => text,\n sourceHash: (text) => text,\n destHash: (text) => text,\n glyph: (text) => text,\n lane: (text) => text,\n invariants: (ids) => `{${ids.join(', ')}}`,\n refs: (names) => `(${names.join(', ')})`,\n spaceHeading: (text) => text,\n summary: (text) => text,\n emptyState: (text) => text,\n};\n\nfunction canonicalFrom(from: string | null): string {\n return from ?? EMPTY_CONTRACT_HASH;\n}\n\nexport function migrationGraphFromListEntries(\n entries: readonly MigrationListEntry[],\n): MigrationGraph {\n const nodes = new Set<string>();\n const forwardChain = new Map<string, MigrationEdge[]>();\n const reverseChain = new Map<string, MigrationEdge[]>();\n const migrationByHash = new Map<string, MigrationEdge>();\n\n for (const entry of entries) {\n const from = canonicalFrom(entry.fromContract);\n const edge: MigrationEdge = {\n from,\n to: entry.toContract,\n migrationHash: entry.hash,\n dirName: entry.name,\n createdAt: entry.createdAt,\n invariants: entry.providedInvariants,\n };\n nodes.add(from);\n nodes.add(entry.toContract);\n const forward = forwardChain.get(from);\n if (forward) forward.push(edge);\n else forwardChain.set(from, [edge]);\n const reverse = reverseChain.get(entry.toContract);\n if (reverse) reverse.push(edge);\n else reverseChain.set(entry.toContract, [edge]);\n migrationByHash.set(entry.hash, edge);\n }\n\n return { nodes, forwardChain, reverseChain, migrationByHash };\n}\n\nexport function buildEdgeAnnotationsByHashFromListEntries(\n entries: readonly MigrationListEntry[],\n): ReadonlyMap<string, MigrationEdgeAnnotation> {\n const annotations = new Map<string, MigrationEdgeAnnotation>();\n for (const entry of entries) {\n annotations.set(entry.hash, {\n operationCount: entry.operationCount,\n invariants: entry.providedInvariants,\n });\n }\n return annotations;\n}\n\nexport function buildRefsByHashFromListEntries(\n entries: readonly MigrationListEntry[],\n): ReadonlyMap<string, readonly string[]> {\n const refsByHash = new Map<string, readonly string[]>();\n for (const entry of entries) {\n if (entry.refs.length > 0) {\n refsByHash.set(entry.toContract, entry.refs);\n }\n }\n return refsByHash;\n}\n\nfunction formatEmptyStateLine(spaceId: string, style: MigrationListStyler): string {\n return style.emptyState(`There are no migrations in migrations/${spaceId}/ yet`);\n}\n\nfunction renderSpaceTreeBlock(\n spaceId: string,\n migrations: readonly MigrationListEntry[],\n multiSpace: boolean,\n glyphMode: GlyphMode,\n style: MigrationListStyler,\n colorize: boolean,\n liveContractHash: string,\n graphForSpace: (spaceId: string) => MigrationGraph | undefined,\n appSpaceId: string | undefined,\n globalMaxEdgeTreePrefixWidth?: number,\n globalMaxDirNameWidth?: number,\n): readonly string[] {\n if (migrations.length === 0) {\n const emptyLine = formatEmptyStateLine(spaceId, style);\n if (!multiSpace) {\n return [emptyLine];\n }\n return [style.spaceHeading(`${spaceId}:`), ` ${emptyLine}`];\n }\n\n const graph = graphForSpace(spaceId) ?? migrationGraphFromListEntries(migrations);\n const isAppSpace = appSpaceId === undefined ? undefined : spaceId === appSpaceId;\n const treeOutput = renderMigrationGraphSpaceTree({\n graph,\n migrations,\n liveContractHash,\n glyphMode,\n colorize,\n refsByHash: buildRefsByHashFromListEntries(migrations),\n styler: style,\n ...(isAppSpace !== undefined ? { isAppSpace } : {}),\n ...(globalMaxEdgeTreePrefixWidth !== undefined ? { globalMaxEdgeTreePrefixWidth } : {}),\n ...(globalMaxDirNameWidth !== undefined ? { globalMaxDirNameWidth } : {}),\n });\n\n if (!multiSpace) {\n return treeOutput.length === 0 ? [] : [treeOutput];\n }\n\n const indented = indentMigrationGraphTreeBlock(treeOutput, ' ');\n return [style.spaceHeading(`${spaceId}:`), indented];\n}\n\nexport interface RenderMigrationListWithStyleOptions {\n readonly colorize?: boolean;\n readonly liveContractHash?: string;\n readonly graphForSpace?: (spaceId: string) => MigrationGraph | undefined;\n /**\n * The space ID that is the app contract space. When provided, `@contract`\n * and the floating working-contract node are shown only for this space.\n * When absent, the renderer falls back to the default (`isAppSpace: true`\n * for every space), which is safe for single-space callers.\n */\n readonly appSpaceId?: string;\n}\n\n/**\n * Compose the styled `migration list` human output via the shared tree\n * renderer. Each on-disk migration is one edge row with package-fact\n * annotations; refs decorate destination contract nodes.\n *\n * `options.colorize` must match whether `style` emits ANSI (e.g. both true for\n * `createAnsiMigrationListStyler({ useColor: true })`).\n */\nexport function renderMigrationListWithStyle(\n result: MigrationListResult,\n style: MigrationListStyler,\n glyphMode: GlyphMode = 'unicode',\n options: RenderMigrationListWithStyleOptions = {},\n): string {\n const multiSpace = result.spaces.length > 1;\n const colorize = options.colorize ?? false;\n const liveContractHash = options.liveContractHash ?? EMPTY_CONTRACT_HASH;\n const graphForSpace = options.graphForSpace ?? (() => undefined);\n const appSpaceId = options.appSpaceId;\n const globalLayoutInputs = multiSpace\n ? result.spaces\n .filter((space) => space.migrations.length > 0)\n .map((space) => ({\n graph: graphForSpace(space.space) ?? migrationGraphFromListEntries(space.migrations),\n liveContractHash,\n }))\n : [];\n const globalMaxEdgeTreePrefixWidth =\n globalLayoutInputs.length > 0\n ? computeGlobalMaxEdgeTreePrefixWidth(globalLayoutInputs)\n : undefined;\n const globalMaxDirNameWidth =\n globalLayoutInputs.length > 0 ? computeGlobalMaxDirNameWidth(globalLayoutInputs) : undefined;\n const lines: string[] = [];\n\n for (let index = 0; index < result.spaces.length; index++) {\n const space = result.spaces[index]!;\n if (index > 0) {\n lines.push('');\n }\n lines.push(\n ...renderSpaceTreeBlock(\n space.space,\n space.migrations,\n multiSpace,\n glyphMode,\n style,\n colorize,\n liveContractHash,\n graphForSpace,\n appSpaceId,\n globalMaxEdgeTreePrefixWidth,\n globalMaxDirNameWidth,\n ),\n );\n }\n\n const totalMigrations = result.spaces.reduce(\n (count, space) => count + space.migrations.length,\n 0,\n );\n if (totalMigrations > 0) {\n lines.push('');\n lines.push(style.summary(result.summary));\n }\n\n return lines.join('\\n');\n}\n\nexport function renderMigrationList(result: MigrationListResult): string {\n return renderMigrationListWithStyle(result, IDENTITY_MIGRATION_LIST_STYLER);\n}\n","import { bold, cyan, cyanBright, dim, green, yellow } from 'colorette';\nimport { IDENTITY_MIGRATION_LIST_STYLER, type MigrationListStyler } from './migration-list-render';\n\nexport type MigrationListStylerWithMarkers = MigrationListStyler & {\n markers(names: readonly string[]): string;\n};\n\nfunction hasMarkersFormatter(\n styler: MigrationListStyler,\n): styler is MigrationListStylerWithMarkers {\n return 'markers' in styler && typeof styler.markers === 'function';\n}\n\nfunction styleMarkerName(name: string): string {\n return name === CONTRACT_MARKER_NAME ? bold(green(name)) : green(name);\n}\n\nfunction plainMarkers(names: readonly string[]): string {\n return names.map((name) => `@${name}`).join(' ');\n}\n\nexport function formatContractNodeOverlays(\n styler: MigrationListStyler,\n markers: readonly string[],\n refs: readonly string[],\n): string {\n const parts: string[] = [];\n if (markers.length > 0) {\n parts.push(hasMarkersFormatter(styler) ? styler.markers(markers) : plainMarkers(markers));\n }\n if (refs.length > 0) {\n parts.push(styler.refs(refs));\n }\n return parts.join(' ');\n}\n\n/**\n * The current contract overlay marker. Unlike user refs, this names the user's\n * declared desired state — the implicit base/target for `plan` / `migrate` —\n * not a stored label. It is emphasized (bold) so it stands out from plain refs\n * (including the live-database `db` marker, which is just another ref).\n */\nexport const CONTRACT_MARKER_NAME = 'contract';\n\nfunction styleRefName(name: string): string {\n return green(name);\n}\n\n/**\n * Build a {@link MigrationListStyler} that decorates `migration list`\n * tokens with ANSI SGR codes. When `useColor` is `false` (non-TTY,\n * `--no-color`, `NO_COLOR=1`, piped output) the function returns the\n * shared identity styler so callers get plain text with zero ANSI\n * bytes — pipe-friendly by construction.\n *\n * Palette:\n *\n * - `dirName`: bold\n * - `sourceHash`: dim cyan\n * - `destHash`: bright cyan\n * - `kind` (`*` / `↩` / `⟲`): bright — the signal; lanes and arrows dim\n * - `glyph` (`→` / `⟲` / `∅`): dim\n * - `lane` (graph gutter lines `│` and fan/join connectors `├─┐` / `├─┘`): dim\n * - `invariants` (`{...}`): yellow\n * - `markers` (`@contract @db`): green; the `contract` desired-state marker is\n * green-bold (`db` is plain green); the `@` sigil is applied to each name\n * - `refs` (`(...)`): green (the active ref is bolded separately by the tree styler)\n * - `spaceHeading` (`<spaceId>:`): bold\n * - `summary`: dim\n * - `emptyState`: dim\n */\nexport function createAnsiMigrationListStyler(opts: {\n readonly useColor: boolean;\n}): MigrationListStylerWithMarkers {\n if (!opts.useColor) {\n return {\n ...IDENTITY_MIGRATION_LIST_STYLER,\n markers: plainMarkers,\n };\n }\n return {\n // Kind glyphs stay bright in both flat and graph views; lanes carry the dim gutter.\n kind: (text) => text,\n dirName: (text) => bold(text),\n sourceHash: (text) => dim(cyan(text)),\n destHash: (text) => cyanBright(text),\n glyph: (text) => dim(text),\n lane: (text) => dim(text),\n invariants: (ids) => yellow(`{${ids.join(', ')}}`),\n markers: (names) => {\n const sigil = green('@');\n return names.map((name) => sigil + styleMarkerName(name)).join(' ');\n },\n refs: (names) => {\n const open = green('(');\n const close = green(')');\n const separator = green(', ');\n return open + names.map(styleRefName).join(separator) + close;\n },\n spaceHeading: (text) => bold(text),\n summary: (text) => dim(text),\n emptyState: (text) => dim(text),\n };\n}\n","import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { bold, createColors, green, yellow } from 'colorette';\nimport stringWidth from 'string-width';\nimport type { GlyphMode } from '../glyph-mode';\nimport {\n laneColorForColumn,\n NEUTRAL_LANE_COLUMN,\n type RowArcLaneColors,\n resolveConnectorLaneColors,\n resolveRowArcLaneColors,\n stylerForLaneColumn,\n} from './migration-graph-lane-colors';\n\nexport { resolveConnectorLaneColors } from './migration-graph-lane-colors';\n\nimport type {\n MigrationGraphGridModel,\n MigrationGraphGridRow,\n StructuralCell,\n} from './migration-graph-layout';\nimport type { ClassifiedEdge } from './migration-graph-rows';\nimport {\n MIGRATION_LIST_HASH_WIDTH,\n migrationListEmptySource,\n migrationListForwardArrow,\n padFromHashColumn,\n} from './migration-list-data-column';\nimport type { MigrationEdgeKind } from './migration-list-graph-topology';\nimport type { MigrationListStyler } from './migration-list-render';\nimport {\n CONTRACT_MARKER_NAME,\n createAnsiMigrationListStyler,\n formatContractNodeOverlays,\n} from './migration-list-styler';\n\nconst LABEL_GAP = 2;\n\n/**\n * The live-database overlay marker. Just another ref as far as styling goes —\n * the only emphasized markers are the active ref and the `contract`\n * desired-state marker (see {@link CONTRACT_MARKER_NAME}).\n */\nconst DB_MARKER_NAME = 'db';\n\nexport interface MigrationEdgeAnnotation {\n readonly status?: 'applied' | 'pending';\n readonly operationCount?: number;\n readonly invariants?: readonly string[];\n /**\n * Path-highlight annotation for `migrate --show` preview.\n * - `'on-path'`: migration is on the chosen path; rendered in bright green (nodes, hashes, names, lane lines).\n * - `'off-path'`: migration is off the chosen path; fully drawn but in uniform dim grey.\n */\n readonly pathHighlight?: 'on-path' | 'off-path';\n}\n\nexport interface RenderMigrationGraphTreeOptions {\n readonly refsByHash?: ReadonlyMap<string, readonly string[]>;\n readonly edgeAnnotationsByHash?: ReadonlyMap<string, MigrationEdgeAnnotation>;\n readonly dbHash?: string;\n readonly contractHash?: string;\n /**\n * Whether this render is for the app space. When false, the `@contract`\n * marker is suppressed — `@contract` is an app-space concept and must not\n * appear in extension spaces (e.g. `pgvector:`). Defaults to `true` so\n * single-space callers that do not pass this option are unaffected.\n */\n readonly isAppSpace?: boolean;\n readonly activeRefName?: string;\n readonly hashLength?: number;\n readonly globalMaxEdgeTreePrefixWidth?: number;\n readonly globalMaxDirNameWidth?: number;\n readonly colorize: boolean;\n readonly glyphMode?: GlyphMode;\n readonly styler?: MigrationListStyler;\n}\n\ninterface MigrationGraphTreeGlyphPalette {\n readonly node: string;\n readonly arcLand: string;\n readonly arcTee: string;\n readonly verticalPass: string;\n readonly branchTee: string;\n readonly mergeTee: string;\n readonly branchCorner: string;\n readonly mergeCorner: string;\n readonly arcBranchCorner: string;\n readonly arcBranchTee: string;\n readonly arcLandCorner: string;\n readonly arcLandTee: string;\n readonly arcCrossing: string;\n readonly arcLandBridge: string;\n readonly horizontalPass: string;\n readonly connectorBranchTee: string;\n readonly connectorBranchTeeCo: string;\n readonly connectorMergeTeeCo: string;\n readonly edgeArrow: Readonly<Record<MigrationEdgeKind, string>>;\n readonly forwardArrow: string;\n readonly emptySource: string;\n}\n\nconst UNICODE_PALETTE: MigrationGraphTreeGlyphPalette = {\n node: '○ ',\n arcLand: '○◂',\n arcTee: '○─',\n verticalPass: '│ ',\n branchTee: '├─',\n mergeTee: '├─',\n branchCorner: '╮ ',\n mergeCorner: '╯ ',\n arcBranchCorner: '╮ ',\n arcBranchTee: '┬─',\n arcLandCorner: '╯ ',\n arcLandTee: '┴─',\n arcCrossing: '┼─',\n arcLandBridge: '──',\n horizontalPass: '──',\n connectorBranchTee: '├─',\n connectorBranchTeeCo: '┬─',\n connectorMergeTeeCo: '┴─',\n edgeArrow: { forward: '↑', rollback: '↓', self: '⟲' },\n forwardArrow: migrationListForwardArrow('unicode'),\n emptySource: migrationListEmptySource('unicode'),\n};\n\nconst ASCII_PALETTE: MigrationGraphTreeGlyphPalette = {\n node: '* ',\n arcLand: '*<',\n arcTee: '*-',\n verticalPass: '| ',\n branchTee: '+-',\n mergeTee: '+-',\n branchCorner: '\\\\ ',\n mergeCorner: '/ ',\n arcBranchCorner: '\\\\ ',\n arcBranchTee: '+-',\n arcLandCorner: '/ ',\n arcLandTee: '+-',\n arcCrossing: '+-',\n arcLandBridge: '--',\n horizontalPass: '--',\n connectorBranchTee: '+-',\n connectorBranchTeeCo: '+-',\n connectorMergeTeeCo: '+-',\n edgeArrow: { forward: '^', rollback: 'v', self: '@' },\n forwardArrow: migrationListForwardArrow('ascii'),\n emptySource: migrationListEmptySource('ascii'),\n};\n\nfunction paletteFor(mode: GlyphMode): MigrationGraphTreeGlyphPalette {\n return mode === 'ascii' ? ASCII_PALETTE : UNICODE_PALETTE;\n}\n\nfunction overlayStatusGlyphs(mode: GlyphMode): {\n readonly applied: string;\n readonly pending: string;\n} {\n return mode === 'ascii' ? { applied: '+', pending: '>' } : { applied: '✓', pending: '⧗' };\n}\n\nfunction arrowForEdgeKind(\n kind: MigrationEdgeKind,\n palette: MigrationGraphTreeGlyphPalette,\n): string {\n return palette.edgeArrow[kind];\n}\n\n/**\n * Forced-color functions that always emit ANSI regardless of the ambient TTY\n * environment (NO_COLOR, piped output). Used for:\n *\n * - `forcedBold`: branch-coloured migration names pair their lane hue with bold;\n * both must emit so the name is deterministically bold + hue.\n * - `forcedDim`: off-path path-highlight override (migrate --show).\n * The renderer gates this behind `opts.colorize`; the forced variant ensures\n * ANSI is emitted in controlled environments (e.g. tests with `NO_COLOR=1`)\n * when the caller explicitly requests colour. Without forcing, `dim()` from\n * the ambient module-level import no-ops under NO_COLOR, making the\n * path-highlight unreachable in tests.\n */\nconst {\n bold: forcedBold,\n dim: forcedDim,\n greenBright: forcedGreen,\n} = createColors({ useColor: true });\n\n/**\n * The two styles used in `migrate --show` path-highlight mode.\n *\n * In path-highlight mode the normal by-branch rotating-colour logic\n * (`LANE_COLOR_CYCLE` / `laneStylerForColumn`) is suppressed entirely.\n * Every glyph, name, and hash is styled by its on-path / off-path role,\n * never by lane column index.\n *\n * - `onPath`: neutral single-path style — exactly how a linear (no-branch)\n * section renders today. Lane glyphs are dim, names are bold, hashes use\n * the default `sourceHash`/`destHash` colours. No rotation hue is applied.\n * This is identical to how the pgvector single-path section renders.\n * - `offPath`: uniform dim grey on every cell (name, hashes, lane glyphs,\n * direction arrows).\n *\n * To change the on-path or off-path colour in future, edit this object only.\n */\nexport const PATH_HIGHLIGHT_STYLES = {\n /**\n * Lane/glyph/arrow stylers for on-path cells.\n *\n * - lane: `forcedGreen` when colour is on — bright green so the on-path\n * branch glyphs (`│ ├ ╯ ↑`) and node markers (`○`/`∅`) are visually\n * distinct from off-path (dim grey). Uses forced ANSI so it survives\n * NO_COLOR in tests. Identity when `colorize` is false.\n * - arrow: identity (plain, no colouring)\n * - dirName: `bold` (ambient bold — name stays white/bold, not green)\n * - hashOverride: undefined — `style.sourceHash`/`style.destHash` apply\n * normally (cyan) so hashes keep their existing neutral colour.\n *\n * `style` is the same `MigrationListStyler` the tree renderer uses.\n * Rotation (`LANE_COLOR_CYCLE`) is never applied to on-path cells.\n */\n onPath: (_style: MigrationListStyler, colorize: boolean) => ({\n lane: colorize ? forcedGreen : (text: string) => text,\n arrow: (text: string) => text,\n dirName: (text: string) => bold(text),\n hashOverride: undefined,\n }),\n /**\n * Lane/glyph/arrow/hash stylers for off-path cells.\n * Uniform dim grey on everything — uses `forcedDim` so ANSI is emitted even\n * under NO_COLOR (test environments use `colorize:true` + NO_COLOR=1 to verify dim).\n * Returns identity functions when colour is off (`colorize: false`).\n */\n offPath: (colorize: boolean) => ({\n lane: colorize ? forcedDim : (text: string) => text,\n arrow: colorize ? forcedDim : (text: string) => text,\n dirName: colorize ? forcedDim : (text: string) => text,\n hashOverride: colorize ? forcedDim : undefined,\n }),\n} as const;\n\nfunction laneStylerForColumn(\n colorColumn: number,\n colorize: boolean,\n style: MigrationListStyler,\n): (text: string) => string {\n return stylerForLaneColumn(colorColumn, colorize, style.lane);\n}\n\n/**\n * Tint a branch-owned token (direction arrow, migration name) by its edge's\n * lane so the whole branch row reads in one colour. Column 0 has nothing to be\n * told apart from in the common linear chain, so it keeps the token's existing\n * default styling (`fallback`) rather than a palette hue; only lanes ≥ 1 take a\n * colour. With colour off, the fallback (also colourless) is used unchanged.\n */\nfunction branchStylerOrDefault(\n column: number,\n colorize: boolean,\n fallback: (text: string) => string,\n): (text: string) => string {\n if (!colorize || column <= NEUTRAL_LANE_COLUMN) {\n return fallback;\n }\n return laneColorForColumn(column);\n}\n\n/**\n * Render a crossing tee (`┼─`): the junction stays dim/neutral so neither arc\n * steals the cell; the trailing dash takes the served lane hue.\n */\nfunction renderArcCrossing(\n pair: string,\n dashColumn: number,\n colorize: boolean,\n style: MigrationListStyler,\n): string {\n const junction = colorize ? style.lane : (text: string) => text;\n const dash = laneStylerForColumn(dashColumn, colorize, style);\n return junction(pair.slice(0, 1)) + dash(pair.slice(1));\n}\n\n/**\n * Render a connector tee (`├─` / `┬─` / `┴─`) with its junction glyph and its\n * trailing dash coloured independently: the junction anchors its own lane while\n * the dash leads into the branch on its right.\n */\nfunction renderConnectorTee(\n pair: string,\n glyphColumn: number,\n dashColumn: number,\n colorize: boolean,\n style: MigrationListStyler,\n): string {\n const glyph = laneStylerForColumn(glyphColumn, colorize, style);\n if (glyphColumn === dashColumn) {\n return glyph(pair);\n }\n return glyph(pair.slice(0, 1)) + laneStylerForColumn(dashColumn, colorize, style)(pair.slice(1));\n}\n\n/**\n * A node-marker glyph pair (`○◂`, `○─`, `*<`, `*-`) is the contract node\n * marker (`○` / `*`) followed by an arc connector (`◂` / `─` / `<` / `-`). The\n * marker takes its own lane's hue (so each node visibly belongs to its branch);\n * the connector follows the arc it belongs to (its owning back-lane hue).\n * Direction arrows are handled elsewhere — they take their edge's lane hue too.\n *\n * When `laneOverride` is provided (for path-highlight rows), it replaces the\n * marker styler. `arcLaneOverride` (if provided) replaces the connector styler\n * independently — this matters when the node is on-path but the arc belongs to\n * an off-path rollback edge, which must render dim rather than green.\n */\nfunction renderNodeMarkerPair(\n pair: string,\n nodeColumn: number,\n arcColumn: number,\n colorize: boolean,\n style: MigrationListStyler,\n laneOverride?: (text: string) => string,\n arcLaneOverride?: (text: string) => string,\n): string {\n const marker = laneOverride ?? laneStylerForColumn(nodeColumn, colorize, style);\n const connector =\n arcLaneOverride ?? laneOverride ?? laneStylerForColumn(arcColumn, colorize, style);\n return marker(pair.slice(0, 1)) + connector(pair.slice(1));\n}\n\nfunction renderCellPair(\n cell: StructuralCell,\n column: number,\n colors: RowArcLaneColors,\n colorize: boolean,\n style: MigrationListStyler,\n palette: MigrationGraphTreeGlyphPalette,\n laneOverride?: (text: string) => string,\n arrowOverride?: (text: string) => string,\n arcLaneOverride?: (text: string) => string,\n): string {\n const laneColumn = colors.lane[column] ?? column;\n // In path-highlight mode (`laneOverride` present), the rotating lane colour is\n // bypassed entirely — the override applies to every structural glyph. Without an\n // override (normal graph/status/list mode), the existing rotation logic applies.\n const lane = laneOverride ?? laneStylerForColumn(laneColumn, colorize, style);\n // `arrowOverride` is used only for the direction arrow on edge-lane cells.\n // When absent, the normal `branchStylerOrDefault` logic applies (rotation for lanes ≥ 1).\n // In path-highlight mode it is always set alongside `laneOverride`.\n const arrow =\n arrowOverride ?? ((text: string) => branchStylerOrDefault(column, colorize, style.kind)(text));\n switch (cell.kind) {\n case 'node': {\n const arcColumn = colors.connector[column] ?? NEUTRAL_LANE_COLUMN;\n if (cell.arcLand === true) {\n return renderNodeMarkerPair(\n palette.arcLand,\n column,\n arcColumn,\n colorize,\n style,\n laneOverride,\n arcLaneOverride,\n );\n }\n if (cell.arcTee === true) {\n return renderNodeMarkerPair(\n palette.arcTee,\n column,\n arcColumn,\n colorize,\n style,\n laneOverride,\n arcLaneOverride,\n );\n }\n return lane(palette.node);\n }\n case 'vertical-pass':\n return lane(palette.verticalPass);\n case 'edge-lane':\n return cell.ownsLabel\n ? lane(palette.verticalPass.trimEnd()) + arrow(arrowForEdgeKind(cell.edgeKind, palette))\n : lane(palette.verticalPass);\n case 'branch-tee':\n return lane(palette.branchTee);\n case 'merge-tee':\n return lane(palette.mergeTee);\n case 'branch-corner':\n return lane(palette.branchCorner);\n case 'merge-corner':\n return lane(palette.mergeCorner);\n case 'arc-branch-corner':\n return lane(palette.arcBranchCorner);\n case 'arc-branch-tee':\n return lane(palette.arcBranchTee);\n case 'arc-land-corner':\n return lane(palette.arcLandCorner);\n case 'arc-land-tee':\n // When a lane override is active, apply it uniformly to both glyph and dash parts\n // so neither part emits a rotation hue.\n return laneOverride !== undefined\n ? laneOverride(palette.arcLandTee)\n : renderConnectorTee(\n palette.arcLandTee,\n laneColumn,\n colors.dash[column] ?? laneColumn,\n colorize,\n style,\n );\n case 'arc-crossing':\n return lane(palette.arcLandBridge);\n case 'arc-land-bridge':\n return lane(palette.arcLandBridge);\n case 'horizontal-pass':\n return lane(palette.horizontalPass);\n case 'empty':\n return ' ';\n }\n}\n\n/**\n * Render a branch-connector or merge-connector row.\n *\n * `columnLaneOverride` is an optional per-column map populated when path-highlight\n * annotations are active (`migrate --show`). For each column in the connector's\n * lane range, the map supplies the override styler (dim for off-path) that should\n * replace the normal rotating-lane colour for that column. Columns absent from the\n * map (on-path or unannotated) use the standard `laneStylerForColumn` logic unchanged.\n * This ensures off-path branch connectors appear dim rather than in their rotation\n * colour (e.g. magenta).\n */\nfunction renderConnectorRow(\n row: MigrationGraphGridRow,\n gridWidth: number,\n colorize: boolean,\n style: MigrationListStyler,\n palette: MigrationGraphTreeGlyphPalette,\n columnLaneOverride?: ReadonlyMap<number, (text: string) => string>,\n): string {\n const resolvedLane = (column: number): ((text: string) => string) =>\n columnLaneOverride?.get(column) ?? laneStylerForColumn(column, colorize, style);\n\n const isMerge = row.kind === 'merge-connector';\n if (row.cells.length > 0) {\n const colors = resolveConnectorLaneColors(row.cells, row.startLane ?? 0);\n let seenTee = false;\n let out = '';\n for (let column = 0; column < row.cells.length; column++) {\n const cell = row.cells[column];\n if (cell === undefined) continue;\n const glyphColumn = colors.glyph[column] ?? column;\n const dashColumn = colors.dash[column] ?? glyphColumn;\n const override = columnLaneOverride?.get(glyphColumn);\n // In path-highlight mode, the dash column's override is used for the trailing dash\n // even when the glyph column has no override. This handles branch-tee cells whose\n // migrationHash is undefined (no previous edge occupied that lane) — the tee's dash\n // belongs to the connector run and should follow the corner's annotation.\n const dashOverrideForPathHighlight = columnLaneOverride?.get(dashColumn) ?? override;\n if (\n override !== undefined ||\n (columnLaneOverride !== undefined && dashOverrideForPathHighlight !== undefined)\n ) {\n // When an override is active for this column (or when a dash override is available\n // via the connected corner), apply the glyph column's override to the junction glyph\n // (├/┬/┴), and the dash column's override to the trailing dash.\n // This matters for merge/branch connectors: the on-path trunk's tee (├) is green\n // while the dash (─) and corner (╯) bridging to an OFF-path column are dim.\n // For non-tee cells (corner, pass, crossing), the single-column override is fine.\n const effectiveOverride = override ?? dashOverrideForPathHighlight;\n if (effectiveOverride === undefined) {\n out += ' ';\n continue;\n }\n switch (cell.kind) {\n case 'branch-tee':\n case 'merge-tee': {\n const pair = seenTee ? palette.connectorBranchTeeCo : palette.connectorBranchTee;\n // Both the junction glyph and its trailing dash belong to this tee cell's\n // own edge — use effectiveOverride for both so an off-path tee's dash is dim\n // even when the next column (dashColumn) belongs to an on-path edge.\n out += effectiveOverride(pair.slice(0, 1)) + effectiveOverride(pair.slice(1));\n seenTee = true;\n break;\n }\n case 'branch-corner':\n out += effectiveOverride(palette.branchCorner);\n break;\n case 'merge-corner':\n out += effectiveOverride(palette.mergeCorner);\n break;\n case 'vertical-pass':\n out += effectiveOverride(palette.verticalPass);\n break;\n case 'horizontal-pass':\n out += effectiveOverride(palette.horizontalPass);\n break;\n case 'arc-crossing': {\n // The junction glyph (┼) belongs to the vertical lane (effectiveOverride).\n // The trailing dash (─) runs horizontally into the next column — it belongs\n // to that column's owner (dashColumn). Use the dash column's override so an\n // off-path horizontal continuation is dim even when the crossing is on-path.\n const arcCrossingDashOverride =\n columnLaneOverride?.get(dashColumn) ?? effectiveOverride;\n out +=\n effectiveOverride(palette.arcCrossing.slice(0, 1)) +\n arcCrossingDashOverride(palette.arcCrossing.slice(1));\n break;\n }\n default:\n out += ' ';\n }\n continue;\n }\n const lane = laneStylerForColumn(glyphColumn, colorize, style);\n switch (cell.kind) {\n case 'branch-tee':\n out += renderConnectorTee(\n seenTee ? palette.connectorBranchTeeCo : palette.connectorBranchTee,\n glyphColumn,\n dashColumn,\n colorize,\n style,\n );\n seenTee = true;\n break;\n case 'merge-tee':\n out += renderConnectorTee(\n seenTee ? palette.connectorMergeTeeCo : palette.connectorBranchTee,\n glyphColumn,\n dashColumn,\n colorize,\n style,\n );\n seenTee = true;\n break;\n case 'branch-corner':\n out += lane(palette.branchCorner);\n break;\n case 'merge-corner':\n out += lane(palette.mergeCorner);\n break;\n case 'vertical-pass':\n out += lane(palette.verticalPass);\n break;\n case 'horizontal-pass':\n out += lane(palette.horizontalPass);\n break;\n case 'arc-crossing':\n out += renderArcCrossing(palette.arcCrossing, dashColumn, colorize, style);\n break;\n default:\n out += ' ';\n }\n }\n // The cells array is sized to the grid width at emit time; a back-arc lane\n // allocated by a later row can push the grid wider afterwards, so pad any\n // trailing columns rather than dropping the lanes that pass through here.\n for (let column = row.cells.length; column < gridWidth; column++) {\n out += ' ';\n }\n return out;\n }\n\n const start = row.startLane ?? 0;\n const end = row.endLane ?? start;\n // The whole fork/merge run reads as one line in the served lane's hue (the\n // corner it reaches); pass-through columns outside the run keep their own.\n const runLane = resolvedLane(end);\n let out = '';\n for (let column = 0; column < gridWidth; column++) {\n if (column < start || column > end) out += ' ';\n else if (column === start) out += runLane(palette.connectorBranchTee);\n else if (column === end) out += runLane(isMerge ? palette.mergeCorner : palette.branchCorner);\n else out += runLane(isMerge ? palette.connectorMergeTeeCo : palette.connectorBranchTeeCo);\n }\n return out;\n}\n\nfunction abbreviateHash(hash: string, hashLength: number, emptySource: string): string {\n if (hash === EMPTY_CONTRACT_HASH) {\n return emptySource;\n }\n const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;\n return stripped.slice(0, hashLength);\n}\n\nconst MIN_HASH_DATA_COLUMN = 25;\n\ninterface ContractOverlayNames {\n readonly markers: readonly string[];\n readonly refs: readonly string[];\n}\n\nfunction overlayNamesForContract(\n contractHash: string,\n opts: RenderMigrationGraphTreeOptions,\n): ContractOverlayNames {\n const markers: string[] = [];\n const refs: string[] = [];\n const userRefs = opts.refsByHash?.get(contractHash);\n if (userRefs) {\n refs.push(...[...userRefs].sort((a, b) => a.localeCompare(b)));\n }\n if (\n opts.isAppSpace !== false &&\n opts.contractHash === contractHash &&\n contractHash !== EMPTY_CONTRACT_HASH\n ) {\n markers.push(CONTRACT_MARKER_NAME);\n }\n if (opts.dbHash === contractHash) {\n markers.push(DB_MARKER_NAME);\n }\n markers.sort((a, b) => {\n if (a === CONTRACT_MARKER_NAME) {\n return -1;\n }\n if (b === CONTRACT_MARKER_NAME) {\n return 1;\n }\n return a.localeCompare(b);\n });\n return { markers, refs };\n}\n\nfunction createTreeStyler(opts: RenderMigrationGraphTreeOptions): MigrationListStyler {\n const base = opts.styler ?? createAnsiMigrationListStyler({ useColor: opts.colorize });\n const activeRefName = opts.activeRefName;\n if (!opts.colorize || activeRefName === undefined) {\n return base;\n }\n return {\n ...base,\n refs: (names) => {\n const styledNames = names.map((name) => (name === activeRefName ? bold(name) : name));\n return base.refs(styledNames);\n },\n };\n}\n\nfunction formatEdgeAnnotationSuffix(\n migrationHash: string,\n opts: RenderMigrationGraphTreeOptions,\n style: MigrationListStyler,\n): string {\n const annotation = opts.edgeAnnotationsByHash?.get(migrationHash);\n if (annotation === undefined) {\n return '';\n }\n const isOffPath = annotation.pathHighlight === 'off-path';\n const segments: string[] = [];\n if (annotation.operationCount !== undefined) {\n segments.push(`${annotation.operationCount} ops`);\n }\n if (annotation.invariants !== undefined && annotation.invariants.length > 0) {\n segments.push(style.invariants(annotation.invariants));\n }\n const status = annotation.status;\n if (status !== undefined) {\n const glyphs = overlayStatusGlyphs(opts.glyphMode ?? 'unicode');\n const glyph = status === 'applied' ? glyphs.applied : glyphs.pending;\n const label = status === 'applied' ? 'applied' : 'pending';\n if (!opts.colorize) {\n segments.push(`${glyph} ${label}`);\n } else {\n const styler = status === 'applied' ? green : yellow;\n segments.push(styler(`${glyph} ${label}`));\n }\n }\n if (annotation.pathHighlight === 'on-path') {\n const glyph = opts.glyphMode === 'ascii' ? '>' : '↑';\n segments.push(`${glyph} will run`);\n }\n if (segments.length === 0) {\n return '';\n }\n const suffix = ` ${segments.join(' ')}`;\n return opts.colorize && isOffPath ? forcedDim(suffix) : suffix;\n}\n\n/**\n * Format the `from → to` hash data column for an edge row.\n *\n * When `hashOverride` is provided (off-path → `dim`), it replaces ALL sub-stylers\n * (`sourceHash`, `destHash`, arrow `glyph`) so dim reaches every character without\n * inner ANSI codes (e.g. the dim+cyan of `sourceHash`) overriding it. On-path edges\n * carry no override. Without an override, the normal `style` sub-stylers apply.\n */\nfunction formatEdgeHashColumn(\n edge: ClassifiedEdge,\n style: MigrationListStyler,\n hashLength: number,\n palette: MigrationGraphTreeGlyphPalette,\n hashOverride?: (text: string) => string,\n): string {\n const src = hashOverride ?? style.sourceHash;\n const dst = hashOverride ?? style.destHash;\n const glyph = hashOverride ?? style.glyph;\n if (edge.kind === 'self') {\n const hash = abbreviateHash(edge.from, hashLength, palette.emptySource);\n const source = padFromHashColumn(src(hash), hashLength);\n return `${source} ${glyph(palette.forwardArrow)} ${dst(hash)}`;\n }\n const source =\n edge.from === EMPTY_CONTRACT_HASH\n ? padFromHashColumn(glyph(palette.emptySource), hashLength)\n : padFromHashColumn(\n src(abbreviateHash(edge.from, hashLength, palette.emptySource)),\n hashLength,\n );\n const arrow = glyph(palette.forwardArrow);\n const dest = dst(abbreviateHash(edge.to, hashLength, palette.emptySource));\n return `${source} ${arrow} ${dest}`;\n}\n\nfunction padVisible(text: string, targetWidth: number): string {\n const padding = Math.max(0, targetWidth - stringWidth(text));\n return text + ' '.repeat(padding);\n}\n\nconst ANSI_ESCAPE = '\\x1b';\n\nfunction trimTrailingWhitespace(line: string): string {\n const trailingSpaceBeforeReset = new RegExp(`[\\\\t ]+((?:${ANSI_ESCAPE}\\\\[[0-9;]*m)+)$`);\n return line.replace(trailingSpaceBeforeReset, '$1').replace(/\\s+$/, '');\n}\n\nfunction gridWidthForModel(rows: readonly MigrationGraphGridRow[]): number {\n return rows.reduce(\n (max, row) =>\n row.kind === 'node' || row.kind === 'edge' ? Math.max(max, row.cells.length) : max,\n 1,\n );\n}\n\nfunction maxDirNameLength(edges: readonly ClassifiedEdge[]): number {\n if (edges.length === 0) return 0;\n return Math.max(...edges.map((edge) => edge.dirName.length));\n}\n\nfunction rowDirNameWidth(labelColumn: number, maxDirNameLen: number, dirNameGap: number): number {\n return Math.max(maxDirNameLen + dirNameGap, MIN_HASH_DATA_COLUMN - labelColumn);\n}\n\nfunction gridUsesSkipRollbackArcs(rows: readonly MigrationGraphGridRow[]): boolean {\n return rows.some((row) =>\n row.cells.some(\n (cell) => cell.kind === 'edge-lane' && cell.adjacency === 'node-skipping-rollback',\n ),\n );\n}\n\nfunction edgeLabelColumn(row: MigrationGraphGridRow, wideLabelColumn: number | undefined): number {\n if (wideLabelColumn !== undefined) {\n return wideLabelColumn;\n }\n const laneIndex = row.laneIndex ?? 0;\n if (row.edge?.from === EMPTY_CONTRACT_HASH && laneIndex === 0) {\n return (laneIndex + 1) * 2 + LABEL_GAP;\n }\n const usesFullRowGutter = row.cells.some(\n (cell, index) => index > laneIndex && cell.kind === 'vertical-pass',\n );\n return usesFullRowGutter ? row.cells.length * 2 + LABEL_GAP : (laneIndex + 1) * 2 + LABEL_GAP;\n}\n\nfunction maxEdgeTreePrefixWidth(\n rows: readonly MigrationGraphGridRow[],\n wideLabelColumn: number | undefined,\n): number {\n let max = 0;\n for (const row of rows) {\n if (row.kind !== 'edge' || row.edge === undefined) continue;\n max = Math.max(max, edgeLabelColumn(row, wideLabelColumn));\n }\n return max;\n}\n\nexport function computeMaxEdgeTreePrefixWidthForLayout(model: MigrationGraphGridModel): number {\n const wideLabelColumn = gridUsesSkipRollbackArcs(model.rows)\n ? gridWidthForModel(model.rows) * 2 + 4\n : undefined;\n return maxEdgeTreePrefixWidth(model.rows, wideLabelColumn);\n}\n\nexport function computeMaxDirNameLengthForLayout(model: MigrationGraphGridModel): number {\n const allEdges = model.rows\n .filter(\n (row): row is MigrationGraphGridRow & { edge: ClassifiedEdge } =>\n row.kind === 'edge' && row.edge !== undefined,\n )\n .map((row) => row.edge);\n return maxDirNameLength(allEdges);\n}\n\nfunction nodeHasArcDecoration(row: MigrationGraphGridRow): boolean {\n return row.cells.some(\n (cell) => cell.kind === 'node' && (cell.arcTee === true || cell.arcLand === true),\n );\n}\n\nexport function renderMigrationGraphTree(\n model: MigrationGraphGridModel,\n opts: RenderMigrationGraphTreeOptions,\n): string {\n const glyphMode = opts.glyphMode ?? 'unicode';\n const palette = paletteFor(glyphMode);\n const style = createTreeStyler(opts);\n const hashLength = opts.hashLength ?? MIGRATION_LIST_HASH_WIDTH;\n const gridWidth = gridWidthForModel(model.rows);\n const wideLabelColumn = gridUsesSkipRollbackArcs(model.rows) ? gridWidth * 2 + 4 : undefined;\n const dirNameGap = wideLabelColumn !== undefined ? 3 : LABEL_GAP;\n const allEdges = model.rows\n .filter(\n (row): row is MigrationGraphGridRow & { edge: ClassifiedEdge } =>\n row.kind === 'edge' && row.edge !== undefined,\n )\n .map((row) => row.edge);\n const maxDirNameLen = maxDirNameLength(allEdges);\n const effectiveMaxDirNameLen = opts.globalMaxDirNameWidth ?? maxDirNameLen;\n const maxEdgePrefixWidth =\n opts.globalMaxEdgeTreePrefixWidth ?? maxEdgeTreePrefixWidth(model.rows, wideLabelColumn);\n const edgeDirNameWidth = rowDirNameWidth(maxEdgePrefixWidth, effectiveMaxDirNameLen, dirNameGap);\n\n // Build a contract-hash → path-highlight map so node rows can be coloured correctly.\n // On-path wins: if a contract is both `from` of an on-path edge and `to` of an off-path\n // edge (or vice-versa), it is treated as on-path.\n // This map is only populated when edgeAnnotationsByHash is provided (migrate --show);\n // for every other command (graph/status/list) it is empty and the code below is a no-op.\n // NOTE: this is ONLY used for node-marker (○/∅) classification. Connector rows and\n // structural cells (tees, corners, arcs) use their per-cell migrationHash directly —\n // not this map and not any column-level aggregate.\n const contractHighlights = new Map<string, 'on-path' | 'off-path'>();\n if (opts.edgeAnnotationsByHash) {\n for (const row of model.rows) {\n if (row.kind !== 'edge' || row.edge === undefined) continue;\n const annotation = opts.edgeAnnotationsByHash.get(row.edge.migrationHash);\n if (annotation?.pathHighlight === undefined) continue;\n const highlight = annotation.pathHighlight;\n for (const hash of [row.edge.from, row.edge.to]) {\n if (hash === EMPTY_CONTRACT_HASH) continue;\n const existing = contractHighlights.get(hash);\n // On-path wins over off-path when a contract hash appears in both.\n if (existing !== 'on-path') {\n contractHighlights.set(hash, highlight);\n }\n }\n }\n }\n\n // In path-highlight mode (`opts.edgeAnnotationsByHash` present), the by-branch rotating\n // colour logic is suppressed entirely. Every glyph is styled by on-path / off-path role\n // via PATH_HIGHLIGHT_STYLES — never by lane column index. In normal mode (no annotations)\n // `pathHighlightActive` is false and the code below is a complete no-op; rotation applies.\n const pathHighlightActive = opts.edgeAnnotationsByHash !== undefined;\n\n /**\n * Resolve the lane and arrow overrides for a row in path-highlight mode.\n * - on-path → neutral single-path style (style.lane for glyphs, plain arrow, bold name).\n * Rotation colour is suppressed; `style.sourceHash`/`style.destHash` apply for hashes.\n * - off-path → uniform dim grey (forcedDim) on every glyph, arrow, name, and hash.\n * - undefined → `undefined` (no override). Unannotated rows use normal rotation. This covers\n * both non-path-highlight commands (graph/status/list) and any annotation without pathHighlight.\n * - When pathHighlightActive is false: always returns undefined, preserving normal rotation.\n */\n function pathStyleForHighlight(highlight: 'on-path' | 'off-path' | undefined):\n | {\n lane: ((text: string) => string) | undefined;\n arrow: ((text: string) => string) | undefined;\n dirName: ((text: string) => string) | undefined;\n hashOverride: ((text: string) => string) | undefined;\n }\n | undefined {\n if (!pathHighlightActive || highlight === undefined) return undefined;\n if (highlight === 'off-path') {\n const s = PATH_HIGHLIGHT_STYLES.offPath(opts.colorize);\n return { lane: s.lane, arrow: s.arrow, dirName: s.dirName, hashOverride: s.hashOverride };\n }\n // on-path → green lane glyphs, bold name, neutral hashes\n const s = PATH_HIGHLIGHT_STYLES.onPath(style, opts.colorize);\n return { lane: s.lane, arrow: s.arrow, dirName: s.dirName, hashOverride: s.hashOverride };\n }\n\n /**\n * Lane override for a given highlight in path-highlight mode.\n * Returns the `lane` part only — used for per-cell overrides.\n */\n function pathLaneFor(\n highlight: 'on-path' | 'off-path' | undefined,\n ): ((text: string) => string) | undefined {\n return pathStyleForHighlight(highlight)?.lane;\n }\n\n /**\n * Arrow override for a given highlight in path-highlight mode.\n * Returns the `arrow` part only — used for edge-lane cell arrow rendering.\n */\n function pathArrowFor(\n highlight: 'on-path' | 'off-path' | undefined,\n ): ((text: string) => string) | undefined {\n return pathStyleForHighlight(highlight)?.arrow;\n }\n\n const lines: string[] = [];\n\n for (let rowIndex = 0; rowIndex < model.rows.length; rowIndex++) {\n const row = model.rows[rowIndex];\n if (row === undefined) continue;\n\n if (row.kind === 'component-separator') {\n lines.push('');\n continue;\n }\n\n if (row.kind === 'branch-connector' || row.kind === 'merge-connector') {\n // In path-highlight mode, build a per-column lane override from each cell's own\n // migrationHash. Each structural cell (branch-tee, branch-corner, merge-tee,\n // merge-corner, vertical-pass, arc-crossing) carries the migrationHash of the\n // edge it visually belongs to (set by Stage 2). We look up that edge's annotation\n // directly — no column-level aggregate, no \"on-path wins\" across columns.\n let connectorColumnOverride: Map<number, (text: string) => string> | undefined;\n if (pathHighlightActive && opts.colorize) {\n connectorColumnOverride = new Map();\n for (let col = 0; col < row.cells.length; col++) {\n const cell = row.cells[col];\n if (cell === undefined || cell.kind === 'empty') continue;\n // arc-crossing: colour by the vertical lane's owner (migrationHash), not the arc.\n const hashForCell =\n 'migrationHash' in cell && cell.migrationHash !== undefined\n ? cell.migrationHash\n : undefined;\n if (hashForCell === undefined) continue;\n const highlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;\n const override = pathLaneFor(highlight);\n if (override !== undefined) {\n connectorColumnOverride.set(col, override);\n }\n }\n if (connectorColumnOverride.size === 0) {\n connectorColumnOverride = undefined;\n }\n }\n lines.push(\n trimTrailingWhitespace(\n renderConnectorRow(\n row,\n gridWidth,\n opts.colorize,\n style,\n palette,\n connectorColumnOverride,\n ),\n ),\n );\n continue;\n }\n\n // Determine the per-row path-highlight style for path-highlight rendering.\n // For edge rows: derived from the edge's annotation.\n // For node rows: derived from the contract hash's membership in on/off-path edges.\n // When pathHighlightActive is false, pathStyleForHighlight returns undefined and\n // the normal rotating-colour lane styler applies everywhere (no-op for non-show commands).\n let rowPathHighlight: 'on-path' | 'off-path' | undefined;\n if (row.kind === 'edge' && row.edge !== undefined) {\n rowPathHighlight = opts.edgeAnnotationsByHash?.get(row.edge.migrationHash)?.pathHighlight;\n } else if (row.kind === 'node' && row.contractHash !== undefined) {\n rowPathHighlight = contractHighlights.get(row.contractHash);\n }\n const rowStyle = pathStyleForHighlight(rowPathHighlight);\n const rowLaneOverride = rowStyle?.lane;\n const rowArrowOverride = rowStyle?.arrow;\n\n // Classify every cell by its own edge's annotation (migrationHash → edgeAnnotationsByHash).\n // Each structural cell (vertical-pass, branch-tee, arc-land-corner, etc.) carries the\n // migrationHash of the edge it visually belongs to (set by the layout builder, Stage 2).\n // We read that hash directly — no column-level aggregate, no \"on-path wins\" across columns.\n //\n // - vertical-pass: classifies by cell.migrationHash (the edge passing through), NOT by column.\n // - edge-lane: classifies by cell.migrationHash (the edge's own row).\n // - branch-tee/corner, merge-tee/corner, arc-*: classifies by cell.migrationHash.\n // - arc-crossing: classifies by cell.migrationHash (the vertical lane's owner), so the\n // crossing reads as the lane passing THROUGH, not the arc skipping over.\n // - node (○/∅): classifies by rowPathHighlight derived from contractHighlights (the\n // node's incident edges); falls through to rowLaneOverride.\n //\n // When pathHighlightActive is false (normal graph/status/list mode), all overrides are\n // undefined and the normal rotating-colour lane styler applies unchanged.\n const cellColors = resolveRowArcLaneColors(row.cells);\n let gutter = row.cells\n .map((cell, column) => {\n let laneOverride = rowLaneOverride;\n let arrowOverride = rowArrowOverride;\n let arcLaneOverride: ((text: string) => string) | undefined;\n if (pathHighlightActive) {\n if (cell.kind === 'edge-lane') {\n // Own cell: colour comes from this cell's own edge annotation.\n const cellHighlight = opts.edgeAnnotationsByHash?.get(\n cell.migrationHash,\n )?.pathHighlight;\n laneOverride = pathLaneFor(cellHighlight);\n arrowOverride = pathArrowFor(cellHighlight);\n } else if (cell.kind === 'node' && (cell.arcTee === true || cell.arcLand === true)) {\n // Node with arc decoration: the node marker takes the node's own row highlight\n // (rowLaneOverride), but the arc connector belongs to the back-arc edge which may\n // have a different annotation. Look up the arc cell's migrationHash to derive the\n // arc connector's colour independently.\n const arcColumn = cellColors.connector[column] ?? NEUTRAL_LANE_COLUMN;\n const arcCell = row.cells[arcColumn];\n const arcHash =\n arcCell !== undefined && 'migrationHash' in arcCell\n ? arcCell.migrationHash\n : undefined;\n if (arcHash !== undefined) {\n const arcHighlight = opts.edgeAnnotationsByHash?.get(arcHash)?.pathHighlight;\n arcLaneOverride = pathLaneFor(arcHighlight);\n }\n // laneOverride stays as rowLaneOverride (the node marker colour)\n } else if (cell.kind !== 'node' && cell.kind !== 'empty') {\n // Routing cells (vertical-pass, branch-tee, merge-corner, arc-*, horizontal-pass):\n // each carries a migrationHash for the edge it belongs to. Classify by that hash.\n //\n // arc-crossing in node/edge rows renders as '──' (the arc bridge over the crossing),\n // not '┼─'. Colour by the arc edge (arcMigrationHash) so an off-path arc bridge is\n // dim even when the crossed vertical lane (migrationHash) is on-path.\n // In connector rows, arc-crossing renders '┼─' where the junction belongs to the\n // vertical lane — handled separately in renderConnectorRow.\n const hashForCell =\n cell.kind === 'arc-crossing' &&\n 'arcMigrationHash' in cell &&\n cell.arcMigrationHash !== undefined\n ? cell.arcMigrationHash\n : 'migrationHash' in cell && cell.migrationHash !== undefined\n ? cell.migrationHash\n : undefined;\n if (hashForCell !== undefined) {\n const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;\n laneOverride = pathLaneFor(cellHighlight);\n arrowOverride = pathArrowFor(cellHighlight);\n }\n }\n // plain node cells (no arcTee/arcLand) fall through to rowLaneOverride\n }\n return renderCellPair(\n cell,\n column,\n cellColors,\n opts.colorize,\n style,\n palette,\n laneOverride,\n arrowOverride,\n arcLaneOverride,\n );\n })\n .join('');\n let laneSpan = row.cells.length;\n if (row.kind === 'node') {\n const contractHash = row.contractHash ?? EMPTY_CONTRACT_HASH;\n if (contractHash === EMPTY_CONTRACT_HASH) {\n laneSpan = 1;\n } else {\n let lastActiveColumn = -1;\n for (let column = row.cells.length - 1; column >= 0; column--) {\n if (row.cells[column]?.kind !== 'empty') {\n lastActiveColumn = column;\n break;\n }\n }\n laneSpan = lastActiveColumn >= 0 ? lastActiveColumn + 1 : 1;\n }\n }\n const labelColumn =\n row.kind === 'edge'\n ? maxEdgePrefixWidth\n : wideLabelColumn !== undefined &&\n (nodeHasArcDecoration(row) || row.contractHash !== undefined)\n ? wideLabelColumn\n : laneSpan * 2 + LABEL_GAP;\n if (\n row.kind === 'edge' &&\n row.edge?.from === EMPTY_CONTRACT_HASH &&\n (row.laneIndex ?? 0) === 0\n ) {\n // Init edge (∅ → first): only the first cell is rendered (the edge-lane cell).\n // rowLaneOverride is correct here — it comes from the edge's own annotation.\n gutter = row.cells\n .slice(0, 1)\n .map((cell, column) =>\n renderCellPair(\n cell,\n column,\n cellColors,\n opts.colorize,\n style,\n palette,\n rowLaneOverride,\n rowArrowOverride,\n ),\n )\n .join('');\n } else if (row.kind === 'node' && laneSpan < row.cells.length && !nodeHasArcDecoration(row)) {\n // Node gutter slice: may contain vertical-pass cells belonging to other edges.\n // Classify each cell by its own migrationHash so pass-through lanes carry the\n // correct colour, not the node's highlight.\n gutter = row.cells\n .slice(0, laneSpan)\n .map((cell, column) => {\n let cellLaneOverride = rowLaneOverride;\n let cellArrowOverride = rowArrowOverride;\n if (pathHighlightActive && cell.kind !== 'node' && cell.kind !== 'empty') {\n const hashForCell =\n cell.kind === 'arc-crossing' &&\n 'arcMigrationHash' in cell &&\n cell.arcMigrationHash !== undefined\n ? cell.arcMigrationHash\n : 'migrationHash' in cell && cell.migrationHash !== undefined\n ? cell.migrationHash\n : undefined;\n if (hashForCell !== undefined) {\n const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;\n cellLaneOverride = pathLaneFor(cellHighlight);\n cellArrowOverride = pathArrowFor(cellHighlight);\n }\n }\n return renderCellPair(\n cell,\n column,\n cellColors,\n opts.colorize,\n style,\n palette,\n cellLaneOverride,\n cellArrowOverride,\n );\n })\n .join('');\n } else if (gutter.length < laneSpan * 2) {\n gutter = gutter.padEnd(laneSpan * 2, ' ');\n }\n const dirNameWidth =\n row.kind === 'edge'\n ? edgeDirNameWidth\n : rowDirNameWidth(labelColumn, maxDirNameLen, dirNameGap);\n const gutterPad = padVisible(gutter, labelColumn);\n\n if (row.kind === 'node') {\n const contractHash = row.contractHash ?? EMPTY_CONTRACT_HASH;\n if (contractHash === EMPTY_CONTRACT_HASH) {\n // The ∅ node row's trailing cells are vertical-pass lanes belonging to arc edges.\n // Classify each by its own migrationHash so they carry the correct path-highlight\n // colour rather than the rotation code that falls out of the ambient lane styler.\n const trailingLanes = row.cells\n .slice(1)\n .map((cell, offset) => {\n let cellLaneOverride = rowLaneOverride;\n let cellArrowOverride = rowArrowOverride;\n if (pathHighlightActive && cell.kind !== 'node' && cell.kind !== 'empty') {\n const hashForCell =\n cell.kind === 'arc-crossing' &&\n 'arcMigrationHash' in cell &&\n cell.arcMigrationHash !== undefined\n ? cell.arcMigrationHash\n : 'migrationHash' in cell && cell.migrationHash !== undefined\n ? cell.migrationHash\n : undefined;\n if (hashForCell !== undefined) {\n const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;\n cellLaneOverride = pathLaneFor(cellHighlight);\n cellArrowOverride = pathArrowFor(cellHighlight);\n }\n }\n return renderCellPair(\n cell,\n offset + 1,\n cellColors,\n opts.colorize,\n style,\n palette,\n cellLaneOverride,\n cellArrowOverride,\n );\n })\n .join('');\n const emptyGutter = palette.emptySource.padEnd(2, ' ') + trailingLanes;\n const overlays = overlayNamesForContract(contractHash, opts);\n if (overlays.markers.length === 0 && overlays.refs.length === 0) {\n lines.push(trimTrailingWhitespace(emptyGutter));\n continue;\n }\n const overlay = formatContractNodeOverlays(style, overlays.markers, overlays.refs);\n lines.push(trimTrailingWhitespace(`${emptyGutter}${' '.repeat(LABEL_GAP)}${overlay}`));\n continue;\n }\n // In path-highlight mode, off-path nodes use `rowStyle.hashOverride` (uniform dim) so\n // inner ANSI codes (e.g. dim+cyan of `style.sourceHash`) cannot override the outer dim.\n // On-path nodes use `style.sourceHash` as normal (neutral purple-ish hash colour).\n const hashTextStyler = rowStyle?.hashOverride ?? style.sourceHash;\n const hashText = hashTextStyler(\n abbreviateHash(contractHash, hashLength, palette.emptySource),\n );\n const overlays = overlayNamesForContract(contractHash, opts);\n const hasOverlays = overlays.markers.length > 0 || overlays.refs.length > 0;\n const overlayPad = hasOverlays ? ' '.repeat(LABEL_GAP) : '';\n const overlay = hasOverlays\n ? formatContractNodeOverlays(style, overlays.markers, overlays.refs)\n : '';\n lines.push(trimTrailingWhitespace(`${gutterPad}${hashText}${overlayPad}${overlay}`));\n continue;\n }\n\n const edge = row.edge;\n if (edge === undefined) continue;\n\n const dirNamePadding = ' '.repeat(Math.max(0, dirNameWidth - edge.dirName.length));\n const laneIndex = row.laneIndex ?? 0;\n\n // The gutter is already coloured via the per-cell overrides threaded into renderCellPair.\n const edgeGutterPad = padVisible(gutter, labelColumn);\n\n let dirName: string;\n if (rowStyle !== undefined) {\n // Path-highlight mode (on-path or off-path annotation present):\n // `rowStyle.dirName` is set by PATH_HIGHLIGHT_STYLES — bold for on-path, forcedDim for off-path.\n // Rotation is suppressed entirely for both roles.\n // When rowStyle is undefined (unannotated row or non-show command), this branch is not entered.\n const dirNameStyler = rowStyle.dirName ?? style.dirName;\n dirName = `${dirNameStyler(edge.dirName)}${dirNamePadding}`;\n } else {\n // Normal mode: lane hue for branched lanes (column ≥ 1), bold-only for column 0.\n const dirNameStyler =\n opts.colorize && laneIndex > NEUTRAL_LANE_COLUMN\n ? (text: string) => forcedBold(laneColorForColumn(laneIndex)(text))\n : style.dirName;\n dirName = `${dirNameStyler(edge.dirName)}${dirNamePadding}`;\n }\n\n // Pass hashOverride from path-highlight styles so formatEdgeHashColumn applies it to ALL\n // sub-stylers (sourceHash, destHash, arrow glyph). Wrapping already-styled text in an outer\n // colour does not work — inner ANSI codes override the outer at the terminal level.\n const hashColumnOverride = rowStyle?.hashOverride;\n const hashColumn = formatEdgeHashColumn(edge, style, hashLength, palette, hashColumnOverride);\n const annotationSuffix = formatEdgeAnnotationSuffix(edge.migrationHash, opts, style);\n lines.push(\n trimTrailingWhitespace(`${edgeGutterPad}${dirName}${hashColumn}${annotationSuffix}`),\n );\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format a single on-path migration row for the `migrate --show` run-list.\n *\n * Uses the SAME styling as the tree renderer's on-path rows (PATH_HIGHLIGHT_STYLES.onPath)\n * so the run-list and graph tree are byte-for-byte identical in their name/hash columns.\n * The gutter is omitted — the list has no graph structure.\n *\n * This is the SINGLE code path for on-path row styling shared by both the graph tree\n * and the \"Will run, in order:\" list. To change the on-path colour, edit PATH_HIGHLIGHT_STYLES.\n */\nexport function formatOnPathMigrationRow(\n dirName: string,\n from: string,\n to: string,\n dirNameWidth: number,\n colorize: boolean,\n glyphMode: GlyphMode,\n): string {\n const palette = paletteFor(glyphMode);\n const style = createAnsiMigrationListStyler({ useColor: colorize });\n // Use PATH_HIGHLIGHT_STYLES.onPath as the single seam for on-path colour.\n // Pass `style` and `colorize` so the lane/glyph stylers respect the colour gate.\n const s = PATH_HIGHLIGHT_STYLES.onPath(style, colorize);\n const styledDirName = `${s.dirName(dirName)}${' '.repeat(Math.max(0, dirNameWidth - dirName.length))}`;\n const hashLength = MIGRATION_LIST_HASH_WIDTH;\n const emptySource = palette.emptySource;\n const fromAbbr =\n from === EMPTY_CONTRACT_HASH\n ? padFromHashColumn(style.glyph(emptySource), hashLength)\n : padFromHashColumn(style.sourceHash(abbreviateHashShort(from, hashLength)), hashLength);\n const toAbbr =\n to === EMPTY_CONTRACT_HASH\n ? style.glyph(emptySource)\n : style.destHash(abbreviateHashShort(to, hashLength));\n const arrow = style.glyph(palette.forwardArrow);\n return `${styledDirName} ${fromAbbr} ${arrow} ${toAbbr}`;\n}\n\nfunction abbreviateHashShort(hash: string, length: number): string {\n const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;\n return stripped.slice(0, length);\n}\n\nexport interface RenderMigrationGraphLegendOptions {\n readonly colorize: boolean;\n readonly glyphMode?: GlyphMode;\n}\n\nfunction formatLegendExampleMarkers(colorize: boolean): string {\n if (!colorize) {\n return '@contract @db';\n }\n const sigil = green('@');\n return `${sigil + bold(green('contract'))} ${sigil}${green('db')}`;\n}\n\n/**\n * A compact key for the tree visual language: the contract node glyph, the\n * in-lane direction arrows, the empty baseline, the system-marker `<…>` and\n * user-ref `(…)` bracket conventions (two illustrative example lines), and a\n * worked sample of the data-column `from → to` migration hash arrow.\n *\n * Honors the same glyph palette (unicode vs ASCII) and `colorize` gate as the\n * tree renderer, so the key matches whatever the graph itself drew and stays\n * pipe-safe (zero ANSI when color is off). The caller adds the trailing blank\n * line that separates this stderr key from the tree on stdout.\n */\nexport function renderMigrationGraphLegend(opts: RenderMigrationGraphLegendOptions): string {\n const palette = paletteFor(opts.glyphMode ?? 'unicode');\n const style = createAnsiMigrationListStyler({ useColor: opts.colorize });\n const node = palette.node.trimEnd();\n const sampleArrow = `${style.sourceHash('aaaaaa')} ${style.glyph(palette.forwardArrow)} ${style.destHash('bbbbbb')}`;\n const statusGlyphs = overlayStatusGlyphs(opts.glyphMode ?? 'unicode');\n const appliedPending = opts.colorize\n ? ` ${green(statusGlyphs.applied)} ${style.summary('applied')} ${yellow(statusGlyphs.pending)} ${style.summary('pending')}`\n : ` ${statusGlyphs.applied} ${style.summary('applied')} ${statusGlyphs.pending} ${style.summary('pending')}`;\n const exampleMarkers = formatLegendExampleMarkers(opts.colorize);\n const exampleRefs = opts.colorize ? style.refs(['prod', 'staging']) : '(prod, staging)';\n const lines = [\n 'Legend:',\n ` ${style.kind(node)} ${style.summary('contract')} ${style.kind(palette.edgeArrow.forward)} ${style.summary('forward')} ${style.kind(palette.edgeArrow.rollback)} ${style.summary('rollback')}`,\n ` ${style.kind(palette.edgeArrow.self)} ${style.summary('migration without schema change')}`,\n appliedPending,\n ` ${style.kind(palette.emptySource)} ${style.summary('empty database (baseline)')}`,\n ` ${exampleMarkers} ${style.summary('reserved markers — also typeable as --from/--to tokens')}`,\n ` ${exampleRefs} ${style.summary('user-defined refs')}`,\n ` ${sampleArrow} ${style.summary('migration from contract aaaaaa to bbbbbb')}`,\n ];\n return lines.join('\\n');\n}\n","import type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport type { GlyphMode } from '../glyph-mode';\nimport { buildMigrationGraphLayout } from './migration-graph-layout';\nimport { buildMigrationGraphRows } from './migration-graph-rows';\nimport {\n computeMaxDirNameLengthForLayout,\n computeMaxEdgeTreePrefixWidthForLayout,\n type MigrationEdgeAnnotation,\n renderMigrationGraphTree,\n} from './migration-graph-tree-render';\nimport {\n buildEdgeAnnotationsByHashFromListEntries,\n buildRefsByHashFromListEntries,\n type MigrationListStyler,\n} from './migration-list-render';\nimport type { MigrationListEntry } from './migration-list-types';\n\nexport { buildEdgeAnnotationsByHashFromListEntries } from './migration-list-render';\n\nexport function mergeMigrationEdgeAnnotations(\n listOverlay: ReadonlyMap<string, MigrationEdgeAnnotation>,\n statusOverlay: ReadonlyMap<string, MigrationEdgeAnnotation>,\n): ReadonlyMap<string, MigrationEdgeAnnotation> {\n const merged = new Map<string, MigrationEdgeAnnotation>();\n for (const [migrationHash, listAnnotation] of listOverlay) {\n const statusAnnotation = statusOverlay.get(migrationHash);\n merged.set(migrationHash, {\n ...listAnnotation,\n ...(statusAnnotation?.status !== undefined ? { status: statusAnnotation.status } : {}),\n });\n }\n return merged;\n}\n\nexport interface RenderMigrationGraphSpaceTreeInput {\n readonly graph: MigrationGraph;\n readonly migrations: readonly MigrationListEntry[];\n readonly liveContractHash: string;\n readonly glyphMode: GlyphMode;\n readonly colorize: boolean;\n readonly refsByHash?: ReadonlyMap<string, readonly string[]>;\n readonly statusOverlayByHash?: ReadonlyMap<string, MigrationEdgeAnnotation>;\n readonly dbHash?: string;\n readonly styler?: MigrationListStyler;\n readonly globalMaxEdgeTreePrefixWidth?: number;\n readonly globalMaxDirNameWidth?: number;\n /**\n * Whether this render is for the app space. When false, `contractHash` is\n * not forwarded to `buildMigrationGraphRows` (suppressing the floating\n * working-contract node) and `isAppSpace: false` is passed to\n * `renderMigrationGraphTree` (suppressing the `@contract` marker).\n * Defaults to `true` so single-space callers are unaffected.\n */\n readonly isAppSpace?: boolean;\n}\n\nexport interface ComputeGlobalMaxEdgeTreePrefixWidthInput {\n readonly graph: MigrationGraph;\n readonly liveContractHash: string;\n}\n\nexport function computeGlobalMaxEdgeTreePrefixWidth(\n inputs: readonly ComputeGlobalMaxEdgeTreePrefixWidthInput[],\n): number {\n let globalMax = 0;\n for (const input of inputs) {\n const rowModel = buildMigrationGraphRows(input.graph, {\n contractHash: input.liveContractHash,\n });\n const layout = buildMigrationGraphLayout(rowModel);\n globalMax = Math.max(globalMax, computeMaxEdgeTreePrefixWidthForLayout(layout));\n }\n return globalMax;\n}\n\nexport function computeGlobalMaxDirNameWidth(\n inputs: readonly ComputeGlobalMaxEdgeTreePrefixWidthInput[],\n): number {\n let globalMax = 0;\n for (const input of inputs) {\n const rowModel = buildMigrationGraphRows(input.graph, {\n contractHash: input.liveContractHash,\n });\n const layout = buildMigrationGraphLayout(rowModel);\n globalMax = Math.max(globalMax, computeMaxDirNameLengthForLayout(layout));\n }\n return globalMax;\n}\n\nfunction renderMigrationGraphSpaceTreeInternal(input: RenderMigrationGraphSpaceTreeInput): string {\n const appSpace = input.isAppSpace !== false;\n const rowModel = buildMigrationGraphRows(input.graph, {\n ...(appSpace ? { contractHash: input.liveContractHash } : {}),\n });\n const layout = buildMigrationGraphLayout(rowModel);\n const listOverlay = buildEdgeAnnotationsByHashFromListEntries(input.migrations);\n const edgeAnnotationsByHash =\n input.statusOverlayByHash === undefined\n ? listOverlay\n : mergeMigrationEdgeAnnotations(listOverlay, input.statusOverlayByHash);\n return renderMigrationGraphTree(layout, {\n refsByHash: input.refsByHash ?? buildRefsByHashFromListEntries(input.migrations),\n contractHash: input.liveContractHash,\n isAppSpace: appSpace,\n edgeAnnotationsByHash,\n colorize: input.colorize,\n glyphMode: input.glyphMode,\n ...(input.dbHash !== undefined ? { dbHash: input.dbHash } : {}),\n ...(input.styler !== undefined ? { styler: input.styler } : {}),\n ...(input.globalMaxEdgeTreePrefixWidth !== undefined\n ? { globalMaxEdgeTreePrefixWidth: input.globalMaxEdgeTreePrefixWidth }\n : {}),\n ...(input.globalMaxDirNameWidth !== undefined\n ? { globalMaxDirNameWidth: input.globalMaxDirNameWidth }\n : {}),\n });\n}\n\nexport function renderMigrationGraphSpaceTree(input: RenderMigrationGraphSpaceTreeInput): string {\n return renderMigrationGraphSpaceTreeInternal(input);\n}\n\nexport function renderMigrationGraphSpaceTrees(\n inputs: readonly RenderMigrationGraphSpaceTreeInput[],\n): readonly string[] {\n const globalMaxTreePrefix =\n inputs.length > 1 ? computeGlobalMaxEdgeTreePrefixWidth(inputs) : undefined;\n const globalMaxDirName = inputs.length > 1 ? computeGlobalMaxDirNameWidth(inputs) : undefined;\n return inputs.map((input) =>\n renderMigrationGraphSpaceTreeInternal({\n ...input,\n ...(globalMaxTreePrefix !== undefined\n ? { globalMaxEdgeTreePrefixWidth: globalMaxTreePrefix }\n : {}),\n ...(globalMaxDirName !== undefined ? { globalMaxDirNameWidth: globalMaxDirName } : {}),\n }),\n );\n}\n\nexport function indentMigrationGraphTreeBlock(treeOutput: string, indent: string): string {\n if (treeOutput.length === 0) {\n return treeOutput;\n }\n return treeOutput\n .split('\\n')\n .map((line) => (line.length === 0 ? line : `${indent}${line}`))\n .join('\\n');\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
2
2
  import { A as formatStyledHeader, K as errorInvalidSpaceId, _ as createTerminalUI, at as errorSpaceNotFound, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, q as errorLegendHumanOnly, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "./command-helpers-esJGBD4W.mjs";
3
3
  import { n as buildReadAggregate } from "./contract-space-aggregate-loader-CpNVrBqW.mjs";
4
- import { a as renderMigrationGraphLegend, c as renderMigrationListWithStyle, o as createAnsiMigrationListStyler } from "./migration-graph-space-render-CeNXh_Wy.mjs";
4
+ import { c as renderMigrationGraphLegend, f as renderMigrationListWithStyle, u as createAnsiMigrationListStyler } from "./migration-graph-space-render-B0HkTNj3.mjs";
5
5
  import { Command } from "commander";
6
6
  import { ifDefined } from "@prisma-next/utils/defined";
7
7
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -93,7 +93,8 @@ function renderMigrationListHumanOutput(result, options) {
93
93
  return renderMigrationListWithStyle(result, createAnsiMigrationListStyler({ useColor: options.useColor }), options.glyphMode, {
94
94
  colorize: options.useColor,
95
95
  liveContractHash: options.liveContractHash,
96
- graphForSpace: options.graphForSpace
96
+ graphForSpace: options.graphForSpace,
97
+ ...options.appSpaceId !== void 0 ? { appSpaceId: options.appSpaceId } : {}
97
98
  });
98
99
  }
99
100
  function computeSummary(spaces) {
@@ -215,7 +216,8 @@ function createMigrationListCommand() {
215
216
  glyphMode: ui.resolveGlyphMode(options.ascii === true),
216
217
  useColor: ui.useColor,
217
218
  liveContractHash,
218
- graphForSpace: (spaceId) => aggregate.space(spaceId)?.graph()
219
+ graphForSpace: (spaceId) => aggregate.space(spaceId)?.graph(),
220
+ appSpaceId: aggregate.app.spaceId
219
221
  }));
220
222
  });
221
223
  process.exit(exitCode);
@@ -225,4 +227,4 @@ function createMigrationListCommand() {
225
227
  //#endregion
226
228
  export { renderMigrationListHumanOutput as a, validateLegendOptions as c, migrationSpaceListEntriesFromAggregate as i, executeMigrationListCommand as n, runMigrationList as o, listRefsByContractHash as r, shouldShowLegend as s, createMigrationListCommand as t };
227
229
 
228
- //# sourceMappingURL=migration-list-vJWFuXca.mjs.map
230
+ //# sourceMappingURL=migration-list-mYmj2j33.mjs.map