Skip to content

feat(cli): migration-graph convergence, geometry, layout + colour fixes#767

Merged
wmadden-electric merged 18 commits into
mainfrom
render-redesign-geometry
Jun 8, 2026
Merged

feat(cli): migration-graph convergence, geometry, layout + colour fixes#767
wmadden-electric merged 18 commits into
mainfrom
render-redesign-geometry

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

Continues the Tier-3 migration-graph renderer redesign (built on the line/plane/occlusion core merged in #762). Started as back-arc convergence + configurable geometry; while validating against the real-world showcase fixture it surfaced and fixed a series of layout and colour bugs. All flat-mode behaviour, no change to focus-mode path semantics beyond colour.

Changes

Convergence + geometry

  • Back-arc convergence — node-skipping rollbacks landing on the same target node share one back-lane instead of one per arc. Each arc keeps its own colour; occlusion arbitrates the shared column.
  • Configurable geometrycolsPerLane default lifted to a named DEFAULT_COLS_PER_LANE constant + a scaling test (proves a one-line change rescales the grid with no renderer edit).

Layout bug fixes (each with a permanent golden / property-test guard)

  • Disconnected components no longer interleave — computeDisplayOrder honours the row model's per-component grouping; lanes reset per component; one blank separator between components.
  • Asymmetric-diamond merge node stays on the lane-0 trunk instead of being stranded in a side lane with a stray corner.
  • Trunk continuation past a merge — a reconciled merge node's lane now propagates to its forward continuation, so the trunk stays on one lane.

Colour

  • Greedy lane colouring (git-style) replacing the lane-index/name-sorted scheme: branches alive at the same time get distinct colours, a back-arc never wears its origin branch's colour (nor the on-path green), colours recycle when a branch ends, and back-arc z-order follows source position (bottom-most on top). Guarded by a property test asserting both rules.
  • Migration names un-bolded — flat mode tints each name with its lane hue; focus mode tints on-path names green / dims off-path. Neither bolded.

Housekeeping

  • Deleted rewrite-obsoleted slice specs (bugs in the deleted tee-based renderer) and added an authoritative projects/migration-graph-rendering/plan.md.

Tests

  • New: hand-authored convergence goldens, geometry scaling test, disconnected-component / asymmetric-diamond / continued-merge goldens, lane-colour property test.
  • Full graph/formatter suite green; golden-pipeline (the hand-authored structure+colour oracle) green; focus-mode goldens unchanged where intended.
  • pnpm --filter @prisma-next/cli typecheck, pnpm lint:deps clean.

Not included (follow-up)

The real-world showcase golden is intentionally not in this PR — its candidate was generated against the pre-fix renderer and is stale. It will be regenerated against the now-correct renderer and reviewed separately. The on-disk examples/ showcase demo fixture is untouched.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved migration graph grid layout for disconnected components and complex rollback merge scenarios.
    • Enhanced back-arc routing with better color and lane assignment for overlapping arcs targeting the same node.
  • Tests

    • Added comprehensive test coverage for migration graph layout geometry and rollback convergence scenarios.

@wmadden-electric wmadden-electric requested a review from a team as a code owner June 8, 2026 11:02
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a9a210bc-d404-4e5d-ae22-5a81a42cf9a4

📥 Commits

Reviewing files that changed from the base of the PR and between b911317 and b026d04.

⛔ Files ignored due to path filters (12)
  • packages/1-framework/3-tooling/cli/test/commands/__snapshots__/migration-graph-coloured-output.test.ts.snap is excluded by !**/*.snap
  • packages/1-framework/3-tooling/cli/test/utils/formatters/__snapshots__/migration-graph-gallery-snapshots.test.ts.snap is excluded by !**/*.snap
  • projects/migration-graph-rendering/README.md is excluded by !projects/**
  • projects/migration-graph-rendering/plan.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/connector-crossing-glyph/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/converging-back-arcs/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/diamond-fixture-regeneration/code-review.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/diamond-fixture-regeneration/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/node-merge-landing-marker/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-geometry/plan.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/showcase-multilane-merge/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/trace.jsonl is excluded by !projects/**
📒 Files selected for processing (13)
  • packages/1-framework/3-tooling/cli/scripts/gallery.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-grid-layout.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-labels.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-model.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-occlusion-render.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-known-broken.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-gallery-snapshots.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-geometry.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-lane-colours.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-scenario-gallery.ts
💤 Files with no reviewable changes (13)
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-known-broken.ts
  • packages/1-framework/3-tooling/cli/scripts/gallery.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-labels.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-model.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-occlusion-render.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-geometry.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-scenario-gallery.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-lane-colours.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-gallery-snapshots.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-grid-layout.ts

📝 Walkthrough

Walkthrough

Refactors migration-graph lane allocation to run per disconnected component with per-edge lane overrides, rewrites back-arc routing to group rollbacks by target (shared geom lanes) and compute separate geom/plane/colour lanes, introduces DEFAULT_COLS_PER_LANE and separator cells, and adds/updates scenarios and tests validating convergence and colouring invariants.

Changes

Back-arc convergence routing and layout refactor

Layer / File(s) Summary
Model: separator cell & default cols-per-lane
packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-model.ts
Adds optional Cell.separator?: boolean and exports DEFAULT_COLS_PER_LANE = 2 as the default columns-per-lane allocation.
Renderer imports & colsPerLane consumption
packages/.../migration-graph-occlusion-render.ts, packages/.../scripts/gallery.ts
Import and use DEFAULT_COLS_PER_LANE (replace hardcoded 2), preserve separator rows in rendered outputs, and include KNOWN_BROKEN_GOLDENS in gallery aggregation.
Grid layout: API surface and setup changes
packages/.../migration-graph-grid-layout.ts
Add edgeLane to LaneAssignment, reformat imports, filter forward non-self edges earlier, and prepare per-component lane assignment scaffolding.
Lane allocation per component & edge overrides
packages/.../migration-graph-grid-layout.ts
Run BFS lane allocation per disconnected component (resetting lane indices), populate edgeLane overrides, reconcile merges by selecting trunk parent and propagate lane changes to affected descendants; compute numLanes across components.
Display ordering & grid index emission
packages/.../migration-graph-grid-layout.ts
computeDisplayOrder emits null separators between components and sorts nodes inside a component by rank desc, lane asc; buildGrid uses opts.colsPerLane ?? DEFAULT_COLS_PER_LANE and assigns display indices skipping separators.
Back-arc routing overhaul (grouped targets)
packages/.../migration-graph-grid-layout.ts
Group skipping rollback arcs by target node into targetGroups, assign one shared geomLane per group ordered by target depth, compute planeLane (z-order) and greedy colourLane bottom-to-top accounting for active forward lanes, reserved green, and origin-lane exclusion; derive numBackLanes from targetGroups.
Back-arc placement & plane selection
packages/.../migration-graph-grid-layout.ts
Use planeLane for placement and focus-aware elevation; backArcPlane now returns arc.planeLane with focus adjustments.
Grid emission: separators, connectors, and per-edge lanes
packages/.../migration-graph-grid-layout.ts
Emit separator rows for component boundaries; fork/merge connectors, inbound-edge ordering, laneCurrentEdge, and migration row column selection now prefer edgeLane overrides via edgeLaneFor(...), falling back to endpoint lanes.
Label styling tweaks
packages/.../migration-graph-labels.ts
Remove forced-bold forced-color usage; tint directory name green in on-path mode and avoid forced bolding in flat lane-tint mode.
Gallery scenarios & goldens updates
packages/.../migration-graph-scenario-gallery.ts, packages/.../gallery-goldens-backlink.ts, packages/.../gallery-goldens.ts, packages/.../gallery-goldens-known-broken.ts
Add rollback-converge-2/-3 scenarios, continued-merge and other fixtures; update backlink goldens to reflect single shared back-lane; add KNOWN_BROKEN_GOLDENS (empty) and include it in gallery aggregation.
Golden pipeline tests and conditional known-broken suite
packages/.../golden-pipeline.test.ts
Neutralize suite title and add conditional it.fails block that runs known-broken goldens through the same structure+colour check.
Convergence structural snapshot tests
packages/.../migration-graph-gallery-snapshots.test.ts
Add helpers and tests asserting converging rollbacks render with a single back-lane width and that the topmost node is the expected highest-rank tip for converge scenarios.
Geometry tests for colsPerLane default/scaling
packages/.../migration-graph-geometry.test.ts
New tests assert DEFAULT_COLS_PER_LANE === 2, linear grid-width scaling with colsPerLane, no tee glyphs at colsPerLane=3, and default rendering equals colsPerLane=2.
Lane colouring invariant tests
packages/.../migration-graph-lane-colours.test.ts
New suite validates greedy colouring invariants: active rails per row use distinct palette indices and back-arc colours differ from origin lane and avoid reserved green across minimal and regression scenarios.

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

  • prisma/prisma-next#762: Implementation-adjacent changes to migration-graph layout/back-arc routing and renderer codepaths.
  • prisma/prisma-next#702: Related work on skip-rollback/back-arc landing handling and landing glyph classification.

Poem

🐰 I hopped through lanes and mapped each rail,
Edges converge where shared soft paths prevail,
Constants planted, separators bloom wide,
Tests cheer the garden where rollbacks now bide,
🌿 carrots of correctness, neatly supplied.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(cli): migration-graph convergence, geometry, layout + colour fixes' directly and comprehensively summarizes the main changes: back-arc convergence, configurable geometry, layout fixes, and colour improvements—all clearly highlighted in the PR objectives and reflected across the modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch render-redesign-geometry

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new

pkg-pr-new Bot commented Jun 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

@prisma-next/extension-author-tools

npm i https://pkg.pr.new/@prisma-next/extension-author-tools@767

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/@prisma-next/mongo-runtime@767

@prisma-next/family-mongo

npm i https://pkg.pr.new/@prisma-next/family-mongo@767

@prisma-next/sql-runtime

npm i https://pkg.pr.new/@prisma-next/sql-runtime@767

@prisma-next/family-sql

npm i https://pkg.pr.new/@prisma-next/family-sql@767

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/@prisma-next/extension-arktype-json@767

@prisma-next/middleware-cache

npm i https://pkg.pr.new/@prisma-next/middleware-cache@767

@prisma-next/mongo

npm i https://pkg.pr.new/@prisma-next/mongo@767

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/@prisma-next/extension-paradedb@767

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/@prisma-next/extension-pgvector@767

@prisma-next/extension-postgis

npm i https://pkg.pr.new/@prisma-next/extension-postgis@767

@prisma-next/postgres

npm i https://pkg.pr.new/@prisma-next/postgres@767

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/@prisma-next/sql-orm-client@767

@prisma-next/sqlite

npm i https://pkg.pr.new/@prisma-next/sqlite@767

@prisma-next/extension-supabase

npm i https://pkg.pr.new/@prisma-next/extension-supabase@767

@prisma-next/target-mongo

npm i https://pkg.pr.new/@prisma-next/target-mongo@767

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/@prisma-next/adapter-mongo@767

@prisma-next/driver-mongo

npm i https://pkg.pr.new/@prisma-next/driver-mongo@767

@prisma-next/contract

npm i https://pkg.pr.new/@prisma-next/contract@767

@prisma-next/utils

npm i https://pkg.pr.new/@prisma-next/utils@767

@prisma-next/config

npm i https://pkg.pr.new/@prisma-next/config@767

@prisma-next/errors

npm i https://pkg.pr.new/@prisma-next/errors@767

@prisma-next/framework-components

npm i https://pkg.pr.new/@prisma-next/framework-components@767

@prisma-next/operations

npm i https://pkg.pr.new/@prisma-next/operations@767

@prisma-next/ts-render

npm i https://pkg.pr.new/@prisma-next/ts-render@767

@prisma-next/contract-authoring

npm i https://pkg.pr.new/@prisma-next/contract-authoring@767

@prisma-next/ids

npm i https://pkg.pr.new/@prisma-next/ids@767

@prisma-next/psl-parser

npm i https://pkg.pr.new/@prisma-next/psl-parser@767

@prisma-next/psl-printer

npm i https://pkg.pr.new/@prisma-next/psl-printer@767

@prisma-next/cli

npm i https://pkg.pr.new/@prisma-next/cli@767

@prisma-next/cli-telemetry

npm i https://pkg.pr.new/@prisma-next/cli-telemetry@767

@prisma-next/emitter

npm i https://pkg.pr.new/@prisma-next/emitter@767

@prisma-next/migration-tools

npm i https://pkg.pr.new/@prisma-next/migration-tools@767

prisma-next

npm i https://pkg.pr.new/prisma-next@767

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/@prisma-next/vite-plugin-contract-emit@767

@prisma-next/mongo-codec

npm i https://pkg.pr.new/@prisma-next/mongo-codec@767

@prisma-next/mongo-contract

npm i https://pkg.pr.new/@prisma-next/mongo-contract@767

@prisma-next/mongo-value

npm i https://pkg.pr.new/@prisma-next/mongo-value@767

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/@prisma-next/mongo-contract-psl@767

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/@prisma-next/mongo-contract-ts@767

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/@prisma-next/mongo-emitter@767

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/@prisma-next/mongo-schema-ir@767

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/@prisma-next/mongo-query-ast@767

@prisma-next/mongo-orm

npm i https://pkg.pr.new/@prisma-next/mongo-orm@767

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/@prisma-next/mongo-query-builder@767

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/@prisma-next/mongo-lowering@767

@prisma-next/mongo-wire

npm i https://pkg.pr.new/@prisma-next/mongo-wire@767

@prisma-next/sql-contract

npm i https://pkg.pr.new/@prisma-next/sql-contract@767

@prisma-next/sql-errors

npm i https://pkg.pr.new/@prisma-next/sql-errors@767

@prisma-next/sql-operations

npm i https://pkg.pr.new/@prisma-next/sql-operations@767

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/@prisma-next/sql-schema-ir@767

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/@prisma-next/sql-contract-psl@767

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/@prisma-next/sql-contract-ts@767

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/@prisma-next/sql-contract-emitter@767

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/@prisma-next/sql-lane-query-builder@767

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/@prisma-next/sql-relational-core@767

@prisma-next/sql-builder

npm i https://pkg.pr.new/@prisma-next/sql-builder@767

@prisma-next/target-postgres

npm i https://pkg.pr.new/@prisma-next/target-postgres@767

@prisma-next/target-sqlite

npm i https://pkg.pr.new/@prisma-next/target-sqlite@767

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/@prisma-next/adapter-postgres@767

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/@prisma-next/adapter-sqlite@767

@prisma-next/driver-postgres

npm i https://pkg.pr.new/@prisma-next/driver-postgres@767

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/@prisma-next/driver-sqlite@767

commit: b026d04

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

size-limit report 📦

Path Size
postgres / no-emit 149.32 KB (0%)
postgres / emit 118.4 KB (0%)
mongo / no-emit 76.67 KB (0%)
mongo / emit 70.96 KB (0%)
cf-worker / no-emit 179.38 KB (0%)
cf-worker / emit 145.16 KB (0%)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts (1)

8-13: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the rollback-merge coverage header to match converged behavior.

Line 11 still says “separate back-lanes”, but this file now models a shared converged back-lane (and adds rollback-merge-3 with the same convergence model).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts`
around lines 8 - 13, Update the coverage header for the `rollback-merge`
scenario in gallery-goldens-backlink.ts to describe the converged/shared
back-lane model (instead of saying “separate back-lanes”), and adjust the
phrasing to indicate that `rollback-merge` (and the newly added
`rollback-merge-3`) model two rollback arcs converging onto the same
back-lane/target; locate the comment block that starts with “Backlink scenarios”
and replace the line describing `rollback-merge` so it reflects the
shared/converged back-lane behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-gallery-snapshots.test.ts`:
- Around line 7-9: Update the outdated comment wording that refers to
“it.fails”/RED in the convergence invariant comments: locate the comment block
describing the convergence invariant (the one that mentions "skipping rollbacks
sharing a target occupy one back-lane, not one per arc") and replace references
to "it.fails" or "RED" with language indicating these are now normal passing
assertions (e.g., "now asserted" or "passing test"); make the same change in the
other comment block later in the file that covers the same invariant (previously
at the second block covering lines 136–151) so both comments accurately reflect
that the test is a regular passing assertion rather than an it.fails/RED
expectation.

---

Outside diff comments:
In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts`:
- Around line 8-13: Update the coverage header for the `rollback-merge` scenario
in gallery-goldens-backlink.ts to describe the converged/shared back-lane model
(instead of saying “separate back-lanes”), and adjust the phrasing to indicate
that `rollback-merge` (and the newly added `rollback-merge-3`) model two
rollback arcs converging onto the same back-lane/target; locate the comment
block that starts with “Backlink scenarios” and replace the line describing
`rollback-merge` so it reflects the shared/converged back-lane behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 329c6c41-a1e5-43ef-99a4-ad4f43942ab2

📥 Commits

Reviewing files that changed from the base of the PR and between 3496511 and b911317.

⛔ Files ignored due to path filters (4)
  • packages/1-framework/3-tooling/cli/test/utils/formatters/__snapshots__/migration-graph-gallery-snapshots.test.ts.snap is excluded by !**/*.snap
  • projects/migration-graph-rendering/slices/converging-back-arcs/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-geometry/plan.md is excluded by !projects/**
  • projects/migration-graph-rendering/trace.jsonl is excluded by !projects/**
📒 Files selected for processing (8)
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-grid-layout.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-model.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-occlusion-render.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens-backlink.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-gallery-snapshots.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-geometry.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-scenario-gallery.ts

Comment on lines +7 to +9
* A convergence invariant (marked it.fails until convergence is implemented) asserts
* that skipping rollbacks sharing a target occupy one back-lane, not one per arc.
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove outdated “RED/it.fails” wording from convergence comments.

Line 7 and Lines 136-151 still describe these as it.fails/RED checks, but the tests now run as normal passing assertions.

Also applies to: 136-151

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-gallery-snapshots.test.ts`
around lines 7 - 9, Update the outdated comment wording that refers to
“it.fails”/RED in the convergence invariant comments: locate the comment block
describing the convergence invariant (the one that mentions "skipping rollbacks
sharing a target occupy one back-lane, not one per arc") and replace references
to "it.fails" or "RED" with language indicating these are now normal passing
assertions (e.g., "now asserted" or "passing test"); make the same change in the
other comment block later in the file that covers the same invariant (previously
at the second block covering lines 136–151) so both comments accurately reflect
that the test is a regular passing assertion rather than an it.fails/RED
expectation.

wmadden added 17 commits June 8, 2026 16:59
Decompose back-arc convergence + configurable geometry into three
test-first dispatches. Mark converging-back-arcs superseded (it targeted
the deleted old layout/tee renderer; its outcome moves here).

Signed-off-by: Will Madden <madden@prisma.io>
Correct D1/D2 to the vitest snapshot harness (structural convergence
assertion, not hand-drawn golden); pin the structural definition of
'converged' (one back-lane per target group).

Signed-off-by: Will Madden <madden@prisma.io>
…assertion

Adds two scenario fixtures (rollback-converge-2, rollback-converge-3) where
multiple skipping rollback arcs all land on the same target node. The structural
assertion block (convergence structural assertions) uses it.fails to lock in the
expected converged grid width (4 columns) while today's per-arc layout allocates
one back-lane per arc (6 and 8 columns respectively). The it.fails tests are
intentionally RED until the layout algorithm is updated to merge same-target
back-arcs into a single lane; at that point the it.fails wrappers are removed.

Signed-off-by: Will Madden <madden@prisma.io>
…-lane

Skipping rollbacks that land on the same target node now share a single
geometric lane (rail column) instead of getting one lane each. numBackLanes
now equals the count of distinct target nodes among skipping rollbacks, not
the arc count — reducing grid width from (lanes+arcs)*2 to (lanes+groups)*2.

Each arc keeps its own colourLane so colour differentiation is preserved;
occlusion arbitrates the shared column per the existing plane/z-order model.

Flip both convergence structural assertions from it.fails to it, strengthen
the tip-topmost check to assert the highest-rank tip node's contractHash
(not just that some node leads grid[0]), and re-record the five
rollback-converge-2/3 snapshot keys to the converged narrower output.

Signed-off-by: Will Madden <madden@prisma.io>
…geometry plan

Signed-off-by: Will Madden <madden@prisma.io>
… scaling proof

Replaces the bare literal `2` in both `buildGrid` and `renderGridRow` with
`DEFAULT_COLS_PER_LANE`, defined in `migration-graph-model.ts` alongside
`GridOptions`. No other tunable geometry literals were found in the four
audited files — the remaining numeric offsets (`railCol + 1`, etc.) are all
structurally derived from `colsPerLane` and are not independent constants.

Adds `migration-graph-geometry.test.ts` which proves the scaling invariant:
passing `colsPerLane: 3` to `buildGrid` widens the fork-2 grid from 4 to 6
columns (numLanes × colsPerLane) with no renderer code change, the no-tee
alphabet holds at colsPerLane=3, and the default output is byte-identical
to colsPerLane=2.

Signed-off-by: Will Madden <madden@prisma.io>
…m D3 review

Signed-off-by: Will Madden <madden@prisma.io>
… add 3-arc golden

The stale two-lane rollback-merge goldens broke when D2 introduced back-arc
convergence. Replace the three existing rollback-merge goldens (flat, focus:via-A,
focus:via-B) with the converged one-lane form derived from the design: one shared
back-lane column, each source tees with its own corner (lane colour follows arc
priority / migration-list order), single ○◂╯ landing.

Add rollback-merge-3 (∅→rm3_a→…→rm3_e, three arcs all landing on rm3_a) with a
flat golden to cover the 3-arc converging case.

Drop the stale "RED baseline — expected to fail" framing from the golden-pipeline
describe block; the oracle is now a real passing suite (54/54).

No src/ changes. No snapshot changes.

Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: Will Madden <madden@prisma.io>
…oritative plan

The line/plane/occlusion rewrite (#762) made several fine-grained glyph-bug
slices moot — they targeted the deleted tee-based renderer. Delete
converging-back-arcs, connector-crossing-glyph, node-merge-landing-marker
(dead by construction in the new model), plus showcase-multilane-merge and
diamond-fixture-regeneration (low-value examples/ chores, captured as optional
follow-ups). Add plan.md as the single source of truth for what's done vs left.

Signed-off-by: Will Madden <madden@prisma.io>
Bug 1 (disconnected components interleave): sort within each component
separately in computeDisplayOrder; reset nextLane to 0 per component in
buildLaneAssignment; emit separator rows between components that renderGrid
preserves as blank lines.

Bug 2 (asymmetric diamond merge node stranded on non-trunk lane): track
per-edge lanes in edgeLane map during BFS; reconcile merge nodes to the
highest-rank parent's lane after BFS; use edgeLane throughout fork connector
and inEdges sort so branch lines render in their allocated columns.

Adds two-component:flat and asymmetric-diamond:flat goldens; clears the
known-broken list; updates coloured-output and gallery snapshots.

Signed-off-by: Will Madden <madden@prisma.io>
The showcase golden candidate was generated against the pre-fix renderer and
is now stale; its file is untracked. Remove the gallery import so the tree is
self-consistent. The candidate will be regenerated after the remaining showcase
layout bugs are fixed.

Signed-off-by: Will Madden <madden@prisma.io>
When an asymmetric-diamond merge node is reconciled to the trunk lane
after BFS, its forward continuation was already assigned the old branch
lane and never updated. This caused the trunk to jump lanes at the merge
point.

The fix: after moving a merge node to its trunk lane, BFS forward through
its outbound edges and move any descendant still on the old lane to the
new trunk lane. The branch edges pointing INTO the merge are left on their
branch lanes so the branch column still renders correctly.

Moves continued-merge golden from KNOWN_BROKEN_GOLDENS to GOLDENS;
updates showcase snapshots (improvement: trunk stays on lane 0 through
the merge instead of indenting into lane 1).

Signed-off-by: Will Madden <madden@prisma.io>
Back-arc colours were assigned by a simple counter (numLanes + i) which
wraps modulo 6 — causing arcs in graphs with 4+ forward lanes to reuse
white (palette index 0, the trunk colour) and green (index 5, reserved
for focus on-path).

Replace the counter with a greedy bottom-up walk: for each back-arc at
its target node, pick the lowest palette index not already held by any
concurrently-active forward lane or back-arc, additionally excluding the
arc's own origin lane's colour and green. This satisfies two rules:

  1. No two concurrently-active lanes share a palette colour.
  2. No back-arc reuses its origin lane's colour or green.

Z-order (planeLane) is now based on source position (bottom-most source
draws on top) rather than colour index, decoupling colour from occlusion.

Includes a property test (migration-graph-lane-colours.test.ts) that
builds a minimal 4-forward-lane + 3-arc graph to assert both rules and
confirm the pre-fix violation. Snapshot goldens for rollback-converge-2,
rollback-converge-3, and showcase:rotating updated to reflect the new
(correct) colour assignments.

Signed-off-by: Will Madden <madden@prisma.io>
Flat mode tints each migration name with its lane hue (not bold); focus mode
tints on-path names green (matching the route) and dims off-path — neither
bolded. Regenerate the graph + coloured-output snapshots.

Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric wmadden-electric force-pushed the render-redesign-geometry branch from b911317 to 5ea3318 Compare June 8, 2026 15:00
@wmadden-electric wmadden-electric changed the title feat(cli): migration-graph back-arc convergence + configurable geometry feat(cli): migration-graph convergence, geometry, layout + colour fixes Jun 8, 2026
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric wmadden-electric enabled auto-merge (squash) June 8, 2026 15:42
@wmadden-electric wmadden-electric merged commit 840c2b8 into main Jun 8, 2026
21 checks passed
@wmadden-electric wmadden-electric deleted the render-redesign-geometry branch June 8, 2026 15:53
wmadden-electric added a commit that referenced this pull request Jun 9, 2026
## Close-out: migration-graph-rendering

Closes the `migration-graph-rendering` project (TML-2746). It began as a
redesign of `migration graph`'s renderer and broadened into a revamp of
the whole interrogative migration **read-command family** (`list` /
`graph` / `status` / `log`) on a shared renderer + ledger foundation.
All work has shipped; this PR migrates the durable knowledge into
`docs/` and deletes the transient project scaffolding.

### Definition of Done — verified

| Outcome | Evidence |
|---|---|
| Tier-3 renderer rebuilt (line/plane/occlusion) | #762 |
| Back-arc convergence, configurable geometry, greedy lane colouring,
layout fixes | #767 |
| Ledger foundation (per-migration journal) | #665 |
| `list`/`status`/`log` revamped on the shared renderer; dagre + `list
--graph` retired | shipped; verified —
`migration-list/status/log/graph.ts` use the shared renderer; no
`dagre`/`tree-render`/`layout` renderers remain |
| Read-command consistency (TML-2801) | re-validated this PR: 4/7
findings resolved, 2 partial, 1 open (4 small follow-ups noted below) |
| Showcase real-world golden | on `main` |

No unmet acceptance criteria. External-reference scan for
`projects/migration-graph-rendering/` is empty (reference-strip step was
a no-op).

### Durable knowledge migrated to `docs/`

- **ADR 227** — Migration read commands share one graphical renderer
with command-specific annotations.
- **ADR 228** — The migration apply ledger is a per-migration journal.
- **ADR 229** — The migration graph renderer uses a line/plane/occlusion
model (the renderer's internal design — lines as the primitive,
single-owner cells, occlusion over blended glyphs). All three verified
against shipped code.
- **`docs/reference/Migration Graph Visual Language.md`** — the
glyph/layout vocabulary the renderer draws from (was the project's
`mockups.md`).
The read-command consistency audit was **re-validated** against current
code (verdict: largely accomplished — 4/7 findings resolved, 2 partial,
1 open) and captured as a Linear follow-up ticket (**TML-2877**, related
to TML-2801) rather than a committed doc, since what remains is
actionable backlog, not long-lived reference.

Transient artefacts (spec, plan, slice specs/plans/reviews,
`decisions.md` — now ADR'd, `learnings.md`, the followups draft,
`trace.jsonl`, prototype, the audit doc) deleted with the folder / moved
to Linear.

### Follow-ups (tracked, not in this PR)

- **TML-2877** — the four remaining read-command consistency items (show
`--space` policy, log unscoped-semantics doc, check see-also, show/check
decoration flags, + a parity-test extension).
- **PR #773** — the demo fixture no-op self-edge fix + offline integrity
guard.

### Retro — lessons

- **A wholesale rewrite obsoletes fine-grained bug-slices.** Three
glyph-bug slice specs (tee/marker bugs) were made moot by the
line/plane/occlusion rewrite — they targeted deleted code. Re-triage the
backlog after a rewrite; don't carry dead slices.
- **Hand-authored goldens beat auto-snapshots for correctness.**
`toMatchSnapshot()` self-certifies whatever the renderer emits; the
hand-authored `golden-pipeline` oracle caught a convergence regression
the snapshots happily recorded as "correct."
- **Real-world fixtures expose layout bugs unit fixtures miss.**
Validating against the `showcase` graph surfaced four distinct
layout/colour bugs (disconnected-component interleave,
asymmetric-diamond merge lane, trunk-continuation, greedy-colour
wraparound) that the simple scenarios never hit.
- **`@prisma-next/cli` runs vitest with `isolate: false`** — "passes
locally" ≠ passes in CI (parallel state pollution). Candidate for a
durable testing note.
- **`fixtures:emit` can emit an integrity-failing fixture** — the
emitter and `migration check` disagreed (a hash-collapse produced a
no-op self-edge). Landed an offline demo integrity guard (#773).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Will Madden <madden@prisma.io>
Co-authored-by: Will Madden <madden@prisma.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants