Skip to content

Graph render redesign — line/plane/occlusion renderer (core slice)#762

Merged
wmadden-electric merged 3 commits into
mainfrom
render-redesign-core
Jun 8, 2026
Merged

Graph render redesign — line/plane/occlusion renderer (core slice)#762
wmadden-electric merged 3 commits into
mainfrom
render-redesign-core

Conversation

@wmadden-electric

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

Copy link
Copy Markdown
Contributor

Slice: render-redesign-core of the migration-graph-rendering project.
Base: render-redesign-design (stacked — this builds on the design + plan branch).

What this does

Rebuilds the Tier-3 migration-graph renderer so colouring is correct-by-construction — no more colour "bleed". The line is the primitive; each cell is a z-ordered set of lines with directions and a plane; rendering is an occlusion projection that picks the topmost-plane line per cell and reads its colour straight off the owning line. No tees (├ ┬ ┼) — corners only, two columns per lane, single-owner-per-cell invariant.

How it's verified — an executable scenario-gallery oracle

Correctness is pinned by hand-authored golden fixtures ([glyphs, name?, colours]) rendered by a trivial, independent renderCellsnot the real renderer, so the test isn't tautological. The real pipeline must satisfy render(input) === golden for every catalogue scenario, plus a "green only on-path" invariant. Run pnpm --filter @prisma-next/cli gallery [filter] to view any scenario in colour.

Highlights

  • New model: LineRef / CellLine{directions, plane} / Cell / Grid (migration-graph-model.ts).
  • Layout assigns planes (forward = base, back-arcs = upper, continuous) and clips forward verticals at crossings (migration-graph-grid-layout.ts).
  • Occlusion renderer (migration-graph-occlusion-render.ts) with mode-dependent z-order (trunk-on-top flat / on-path-on-top focus) and an ASCII alphabet.
  • Clean-room command renderer (migration-graph-command-render.ts + -labels.ts): rows, gutter, and per-row labels all derived from one grid — fixes the prior off-by-one label offset.
  • The old StructuralCell layout, the switch (cell.kind) render, the tee renderer, and the lane-colour/corner-gutter splice are deleted.
  • Branch palette: white · cyan · yellow · blueBright · magenta · green — no red (reads as an error); green reserved-but-usable (flat lane uses normal green SGR 32, on-path highlight uses greenBright SGR 92).

Deferred to render-redesign-geometry (by design)

  • Back-arc convergence (multiple rollbacks landing on one node) — currently per-arc lanes.
  • A cosmetic bare | after a multi-edge convergence node.
  • The real-world showcase golden (needs convergence) — shelved on branch showcase-golden-shelf.

Verification

  • render(input) === golden for the full catalogue; green-only-on-path invariant holds.
  • Full cli suite green (1300+/1302; the 2 intermittent failures are pre-existing control-api/JSON parallel-pollution flakes that pass in isolation).
  • Real multi-branch / wide-fan demo fixtures render with correct alignment and unified per-lane colour.
  • Typecheck, lint, lint:deps green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a gallery CLI script to render and view hand-authored fixtures.
    • Introduced a new grid-based migration-graph command renderer for terminal output.
  • Improvements

    • Better focus-mode coloring and on-path/off-path highlighting with consistent label alignment.
    • Replaced legacy tree layout with grid layout; terminal empty nodes now show a circle marker.
  • Tests

    • Expanded gallery and renderer tests, added snapshots and ANSI/color validation.

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

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR replaces the tree-layout-based migration graph rendering system with a new grid/occlusion-based pipeline, adds label-formatting and lane colorization, integrates the new renderer into migrate/list/status commands, and adds gallery tooling plus golden-driven tests validating color, glyph, and alignment invariants.

Changes

Migration Graph Grid Rendering Architecture

Layer / File(s) Summary
Grid data model & types
src/utils/formatters/migration-graph-model.ts
Adds types: Direction, PathRole, LineRef, NodeRef, CellLine, Cell, Grid, GridOptions, and Highlight.
Grid layout engine
src/utils/formatters/migration-graph-grid-layout.ts
Implements buildGrid with lane/rank assignment, deterministic display order, connector/self-loop/fork/merge/back-arc emission, vertical pass-through tracking, and single-owner assertions.
Occlusion cell rendering
src/utils/formatters/migration-graph-occlusion-render.ts
Renders grid rows by occlusion (plane ordering) with forced ANSI colors, lane tinting, focus coloring, and glyph alphabets (unicode/ascii).
Label formatting & legend
src/utils/formatters/migration-graph-labels.ts
Adds MigrationEdgeAnnotation and label formatting: node labels, migration labels, run-list row formatting, PATH_HIGHLIGHT_STYLES, and renderMigrationGraphLegend.
Grid-to-command text rendering
src/utils/formatters/migration-graph-command-render.ts
Implements RenderMigrationGraphCommandInput, computeLabelColumn, computeMaxDirNameWidth, and renderMigrationGraphCommand to produce aligned labeled text from a Grid.
Space rendering pipeline refactor
src/utils/formatters/migration-graph-space-render.ts
Replaces tree-based rendering with grid pipeline: adds highlightFromEdgeAnnotations, builds grids per-space, and computes cross-space global widths via grid measurements.
Migrate --show integration
src/commands/migrate.ts
Precomputes per-space row models and grids, builds edgeAnnotations map, derives globalLabelColumn and globalMaxDirNameWidth, and calls renderMigrationGraphCommand for aligned output.
Command import updates
src/commands/{migration-graph,migration-list,migration-status,migration-status-overlay}.ts
Updates imports to use migration-graph-labels, grid/layout/command render utilities, and reorders imports to match the new pipeline.

Golden Testing Framework & Validation

Layer / File(s) Summary
Gallery cell rendering primitives
test/utils/formatters/gallery-cells.ts
Adds Colour palette, Row model, ScenarioInput types, RenderContext, renderCells, and parseGrid for authoring golden pictures.
Golden scenario fixtures
test/utils/formatters/gallery-goldens.ts, gallery-goldens-backlink.ts
Adds hand-authored GOLDENS and BACKLINK_GOLDENS covering linear, fork, merge, diamond, rollback, fan, and backlink scenarios in flat/focus variants.
Scenario rendering infra
test/utils/formatters/migration-graph-scenario-gallery.ts
Exports deterministic scenario builders, renderScenario, renderScenarioByKey, and forced-color helpers for test stability.
Golden-pipeline validation
test/utils/formatters/golden-pipeline.test.ts
Vitest suite translating goldens into real MigrationGraph, rendering grids, tokenizing ANSI+structure, and asserting exact structure+color parity plus green-only-on-path invariants.
Snapshots & gallery tests
test/utils/formatters/migration-graph-gallery-snapshots.test.ts
Snapshots verbatim ANSI output per scenario variant and asserts corner-glyph absence of legacy tee characters and presence of mixed-focus colors.

Test Updates

Layer / File(s) Summary
Migration-list tests & styler
test/commands/migration-list.test.ts, test/utils/formatters/migration-list-render.test.ts, migration-list-styler.test.ts
Update expected outputs to include terminal empty-node glyph, change connector expectations from tee to corner patterns, and adjust forced-color expectations for self-edge gutter coloring.
Migration graph & colored output
test/commands/migration-graph.test.ts, test/commands/migration-graph-coloured-output.test.ts
Update legend import; add comprehensive verbatim-colored renderer tests and glyph-mode/ascii guards with snapshots and ANSI assertions.
Parity & render-mode tests
test/commands/migration-read-commands-parity.test.ts, test/utils/formatters/migration-graph-rows.test.ts
Force color in parity tests, assert ANSI SGR presence in gutter, and replace annotated-tree string-equality checks with grid+command invariants (no tees, labels present, label-arrow co-location).

Gallery CLI Tool

Layer / File(s) Summary
Gallery CLI
package.json, scripts/gallery.ts
Adds npm run gallery script and a CLI scripts/gallery.ts that filters GOLDENS/BACKLINK_GOLDENS by scenario:strategy:variant, renders with renderCells, prints headers/separators, and reports a summary.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly Related PRs

  • prisma/prisma-next#735: Related changes to migrate --show migration-graph rendering and path-highlight behavior.
  • prisma/prisma-next#674: Related refactor migrating away from the legacy tree renderer toward grid/labels-based formatting.
  • prisma/prisma-next#705: Related rehoming of migration edge annotation/legend logic affecting status overlay and list rendering.

Suggested Reviewers

  • wmadden

"I hop the lanes in ANSI green,
corners where tees once had been—
goldens glow, tests cheer the sight,
rails aligned in evening light. 🐇"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.47% 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 title directly and specifically identifies the main change: redesigning the graph renderer using a line/plane/occlusion model as the core architectural shift.
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-core

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/prisma-next/@prisma-next/extension-author-tools@762

@prisma-next/mongo-runtime

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

@prisma-next/family-mongo

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

@prisma-next/sql-runtime

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

@prisma-next/family-sql

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

@prisma-next/extension-arktype-json

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

@prisma-next/middleware-cache

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

@prisma-next/mongo

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

@prisma-next/extension-paradedb

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

@prisma-next/extension-pgvector

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

@prisma-next/extension-postgis

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

@prisma-next/postgres

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

@prisma-next/sql-orm-client

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

@prisma-next/sqlite

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

@prisma-next/extension-supabase

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

@prisma-next/target-mongo

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

@prisma-next/adapter-mongo

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

@prisma-next/driver-mongo

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

@prisma-next/contract

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

@prisma-next/utils

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

@prisma-next/config

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

@prisma-next/errors

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

@prisma-next/framework-components

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

@prisma-next/operations

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

@prisma-next/ts-render

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

@prisma-next/contract-authoring

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

@prisma-next/ids

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

@prisma-next/psl-parser

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

@prisma-next/psl-printer

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

@prisma-next/cli

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

@prisma-next/cli-telemetry

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

@prisma-next/emitter

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

@prisma-next/migration-tools

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

prisma-next

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

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

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

@prisma-next/mongo-codec

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

@prisma-next/mongo-contract

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

@prisma-next/mongo-value

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

@prisma-next/mongo-contract-psl

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

@prisma-next/mongo-contract-ts

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

@prisma-next/mongo-emitter

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

@prisma-next/mongo-schema-ir

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

@prisma-next/mongo-query-ast

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

@prisma-next/mongo-orm

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

@prisma-next/mongo-query-builder

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

@prisma-next/mongo-lowering

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

@prisma-next/mongo-wire

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

@prisma-next/sql-contract

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

@prisma-next/sql-errors

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

@prisma-next/sql-operations

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

@prisma-next/sql-schema-ir

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

@prisma-next/sql-contract-psl

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

@prisma-next/sql-contract-ts

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

@prisma-next/sql-contract-emitter

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

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

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

@prisma-next/sql-relational-core

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

@prisma-next/sql-builder

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

@prisma-next/target-postgres

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

@prisma-next/target-sqlite

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

@prisma-next/adapter-postgres

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

@prisma-next/adapter-sqlite

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

@prisma-next/driver-postgres

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

@prisma-next/driver-sqlite

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

commit: e9be5ab

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

size-limit report 📦

Path Size
postgres / no-emit 147.91 KB (0%)
postgres / emit 117.71 KB (0%)
mongo / no-emit 76.67 KB (0%)
mongo / emit 70.96 KB (0%)
cf-worker / no-emit 177.86 KB (0%)
cf-worker / emit 144.42 KB (0%)

@wmadden wmadden 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.

I don't want to see the words "clean-room" in the source.

Comment thread packages/1-framework/3-tooling/cli/scripts/gallery.ts Outdated
@wmadden-electric wmadden-electric changed the base branch from render-redesign-design to main June 8, 2026 07:43
@wmadden-electric

Copy link
Copy Markdown
Contributor Author

Addressed the review:

  • Swept every "clean-room" mention and every transient projects/ reference out of the source and tests, and trimmed or deleted the verbose header comments throughout (kept only short ones that say something the code doesn't).
  • Removed the dead --old gallery mode and converted the conditional spreads to ifDefined().

I also corrected the base to main and collapsed the stale branch onto current main as a single commit. The diff is now this slice only — the migrate-show/refs content that had leaked in is already on main, so it dropped out. Full cli suite green (1302 passed), typecheck / lint / lint:deps clean.

@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

🧹 Nitpick comments (1)
packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts (1)

284-293: 💤 Low value

Consider optional chaining to avoid non-null assertion.

The non-null assertion on line 285 is safe (guarded by the while condition), but optional chaining would be more idiomatic:

 while (merged.length > 0) {
-  const last = merged[merged.length - 1]!;
+  const last = merged.at(-1);
+  if (last === undefined) break;
   const trimmed = last.text.trimEnd();
🤖 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/golden-pipeline.test.ts`
around lines 284 - 293, Replace the non-null assertion on merged[merged.length -
1]! with an optional-safe access—e.g., use merged.at(-1) and guard it before
use: change const last = merged[merged.length - 1]! to const last =
merged.at(-1); if (!last) break; then proceed to trim and possibly pop; this
removes the `!` while preserving the current loop logic in the block handling
merged, last, and trimmed.
🤖 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-list-render.test.ts`:
- Around line 217-220: The test currently only forbids the single tee glyph '├',
but the invariant forbids the full legacy-tee set; update the assertion that
checks the rendered corner to also reject '┬', '┴', and '┼'. Locate the
expectations that reference output (the expect(output).not.toContain('├') line)
and replace it with a single negative assertion that ensures none of the tee
glyphs ['├','┬','┴','┼'] appear in output (e.g., a negative regex or checking
each glyph), keeping the existing positive corner regex
expect(output).toMatch(/[│─]─[╮╯]/) intact.

---

Nitpick comments:
In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts`:
- Around line 284-293: Replace the non-null assertion on merged[merged.length -
1]! with an optional-safe access—e.g., use merged.at(-1) and guard it before
use: change const last = merged[merged.length - 1]! to const last =
merged.at(-1); if (!last) break; then proceed to trim and possibly pop; this
removes the `!` while preserving the current loop logic in the block handling
merged, last, and trimmed.
🪄 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: ec1b874c-7f3c-4cc9-b0fc-c12940af9560

📥 Commits

Reviewing files that changed from the base of the PR and between 04d39e5 and 6c17b3c.

⛔ Files ignored due to path filters (8)
  • 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__/graph-render.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/design/graph-render-redesign.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-core/plan.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-core/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-geometry/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/trace.jsonl is excluded by !projects/**
📒 Files selected for processing (34)
  • packages/1-framework/3-tooling/cli/package.json
  • packages/1-framework/3-tooling/cli/scripts/gallery.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-list.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status-overlay.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-command-render.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-lane-colors.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-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/src/utils/formatters/migration-graph-space-render.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-tree-render.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-list-render.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph-coloured-output.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-list.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-read-commands-parity.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-cells.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.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-cell-identity.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-colour-matrix.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-layout.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-rows.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-tree-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-styler.test.ts
💤 Files with no reviewable changes (7)
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-layout.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-layout.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-cell-identity.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-lane-colors.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-tree-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-colour-matrix.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-tree-render.ts

wmadden-electric pushed a commit that referenced this pull request Jun 8, 2026
The no-tee invariant forbids every tee glyph; the corner assertion only
rejected ├, so a regression introducing ┬ ┴ ┼ would have passed. Broaden the
negative match to the whole set (addresses CodeRabbit review on PR #762).

Signed-off-by: Will Madden <madden@prisma.io>
wmadden added 2 commits June 8, 2026 11:01
…clusion)

Replace the position-keyed StructuralCell grid and the switch(cell.kind)
renderer with a line/plane/occlusion model: a line carries identity, the
layout assigns each line a plane, and the renderer projects each cell to the
topmost-plane line — taking its glyph from that line's directions and its
colour straight off the line. This removes the colour-bleed class of bugs by
construction.

- Model + layout + renderer: migration-graph-{model,grid-layout,occlusion-render}.ts.
- Commands (graph / status / list --graph / migrate --show) render rows, gutter,
  and per-row labels from one grid via migration-graph-{command-render,labels}.ts.
- Glyph alphabet is verticals + corners + arrows + node markers — no tees; with
  two columns per lane every cell has one owner, so colour is never arbitrated.
- Branch palette: white, cyan, yellow, blueBright, magenta, green (no red; the
  on-path highlight stays greenBright).
- Verified by a hand-authored scenario-gallery oracle: goldens are serialised by
  a trivial independent renderer, and the real pipeline is asserted to reproduce
  them (render(input) === golden), plus a green-only-on-path invariant.
- Removes the old renderer (migration-graph-{layout,tree-render,lane-colors}.ts)
  and its tests.

Back-arc convergence and configurable geometry are left to the sibling
render-redesign-geometry slice.

Signed-off-by: Will Madden <madden@prisma.io>
The no-tee invariant forbids every tee glyph; the corner assertion only
rejected ├, so a regression introducing ┬ ┴ ┼ would have passed. Broaden the
negative match to the whole set (addresses CodeRabbit review on PR #762).

Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric wmadden-electric changed the title Graph render redesign — clean-room line/plane/occlusion renderer (core slice) Graph render redesign — line/plane/occlusion renderer (core slice) Jun 8, 2026
@wmadden-electric wmadden-electric enabled auto-merge (squash) June 8, 2026 09:02

@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

🧹 Nitpick comments (1)
packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts (1)

349-358: 💤 Low value

Dead loop body — remove or complete the TODO.

Lines 351-357 iterate over lines but the loop body only contains comments; no actual logic executes. Either remove this loop or implement the "best-effort check" mentioned in the comments.

🧹 Suggested cleanup
 function assertGreenOnlyOnPath(golden: ScenarioGolden, rendered: string): void {
   const lines = rendered.split('\n');
-  for (const line of lines) {
-    if (!line.includes(GREEN_BRIGHT)) continue;
-    // This line has green — it should only be on-path related.
-    // (We do a best-effort check: if we can find the migration name for this
-    // line and it's off-path, that's a violation.)
-    // For now we just collect violations without blocking.
-  }
-
   // Actual assertion: green must NOT appear on a line that is purely off-path.
🤖 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/golden-pipeline.test.ts`
around lines 349 - 358, The loop in assertGreenOnlyOnPath currently contains
only comments and must be implemented or removed; implement the "best-effort
check" by scanning each rendered line for GREEN_BRIGHT, extracting the migration
identifier/name with the same regex/pattern the tests use elsewhere (use the
migration naming symbols from ScenarioGolden/migrations), then check that the
found migration is marked on-path in the ScenarioGolden data (e.g., via
golden.migrations or golden.onPath set); collect violations into an array (e.g.,
violations) and at the end assert/throw a clear test failure if any off-path
migrations were found highlighted in green, otherwise return silently. Ensure
you reference the function assertGreenOnlyOnPath, the GREEN_BRIGHT marker, and
ScenarioGolden/migrations when locating where to add this logic.
🤖 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/golden-pipeline.test.ts`:
- Line 392: Update the stale test-suite description in the describe(...) call
for the "golden-pipeline" tests: remove the "RED baseline — expected to fail on
current renderer" clause so the description reflects that tests should pass
(e.g., change to "golden-pipeline: render(input) === golden" or similar). Edit
the describe string in the test file's describe('golden-pipeline: render(input)
=== golden (RED baseline — expected to fail on current renderer)', ...) to a
concise, accurate message matching the PR expectation.

---

Nitpick comments:
In
`@packages/1-framework/3-tooling/cli/test/utils/formatters/golden-pipeline.test.ts`:
- Around line 349-358: The loop in assertGreenOnlyOnPath currently contains only
comments and must be implemented or removed; implement the "best-effort check"
by scanning each rendered line for GREEN_BRIGHT, extracting the migration
identifier/name with the same regex/pattern the tests use elsewhere (use the
migration naming symbols from ScenarioGolden/migrations), then check that the
found migration is marked on-path in the ScenarioGolden data (e.g., via
golden.migrations or golden.onPath set); collect violations into an array (e.g.,
violations) and at the end assert/throw a clear test failure if any off-path
migrations were found highlighted in green, otherwise return silently. Ensure
you reference the function assertGreenOnlyOnPath, the GREEN_BRIGHT marker, and
ScenarioGolden/migrations when locating where to add this logic.
🪄 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: 459e3f9f-2c50-4297-9f16-a6a33ae88d98

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17b3c and e9be5ab.

⛔ Files ignored due to path filters (8)
  • 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__/graph-render.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/design/graph-render-redesign.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-core/plan.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-core/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/slices/render-redesign-geometry/spec.md is excluded by !projects/**
  • projects/migration-graph-rendering/trace.jsonl is excluded by !projects/**
📒 Files selected for processing (34)
  • packages/1-framework/3-tooling/cli/package.json
  • packages/1-framework/3-tooling/cli/scripts/gallery.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-list.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status-overlay.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-command-render.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-lane-colors.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-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/src/utils/formatters/migration-graph-space-render.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-tree-render.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-list-render.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph-coloured-output.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-list.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-read-commands-parity.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-cells.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.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-cell-identity.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-colour-matrix.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-layout.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-rows.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-tree-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-styler.test.ts
💤 Files with no reviewable changes (7)
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-layout.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-layout.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-tree-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-colour-matrix.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-cell-identity.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-lane-colors.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-tree-render.ts
✅ Files skipped from review due to trivial changes (7)
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-list-render.ts
  • packages/1-framework/3-tooling/cli/package.json
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-list.test.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-list.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-model.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • packages/1-framework/3-tooling/cli/src/commands/migration-status-overlay.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-styler.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-goldens.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-list-render.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-rows.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-read-commands-parity.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-graph-coloured-output.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-labels.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-gallery-snapshots.test.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/gallery-cells.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migration-graph-space-render.ts
  • packages/1-framework/3-tooling/cli/test/utils/formatters/migration-graph-scenario-gallery.ts
  • packages/1-framework/3-tooling/cli/scripts/gallery.ts


const ALL_GOLDENS: readonly ScenarioGolden[] = [...GOLDENS, ...BACKLINK_GOLDENS];

describe('golden-pipeline: render(input) === golden (RED baseline — expected to fail on current renderer)', () => {

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

Stale "expected to fail" description contradicts PR verification.

The test suite description says "RED baseline — expected to fail on current renderer", but the PR objectives state all checks are green (1302 passed). If these tests now pass, update the description to reflect the current state.

📝 Suggested fix
-describe('golden-pipeline: render(input) === golden (RED baseline — expected to fail on current renderer)', () => {
+describe('golden-pipeline: render(input) === golden', () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe('golden-pipeline: render(input) === golden (RED baseline — expected to fail on current renderer)', () => {
describe('golden-pipeline: render(input) === golden', () => {
🤖 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/golden-pipeline.test.ts`
at line 392, Update the stale test-suite description in the describe(...) call
for the "golden-pipeline" tests: remove the "RED baseline — expected to fail on
current renderer" clause so the description reflects that tests should pass
(e.g., change to "golden-pipeline: render(input) === golden" or similar). Edit
the describe string in the test file's describe('golden-pipeline: render(input)
=== golden (RED baseline — expected to fail on current renderer)', ...) to a
concise, accurate message matching the PR expectation.

@wmadden-electric wmadden-electric merged commit 47359eb into main Jun 8, 2026
21 checks passed
@wmadden-electric wmadden-electric deleted the render-redesign-core branch June 8, 2026 09:27
wmadden-electric pushed a commit that referenced this pull request Jun 8, 2026
…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>
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