Skip to content

TML-2546: restructure migration CLI surface around resolved vocabulary#523

Merged
wmadden merged 72 commits into
mainfrom
tml-2546-review-migration-cli-commands-and-vocabulary
May 18, 2026
Merged

TML-2546: restructure migration CLI surface around resolved vocabulary#523
wmadden merged 72 commits into
mainfrom
tml-2546-review-migration-cli-commands-and-vocabulary

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented May 18, 2026

Linked issue

Refs TML-2546.

Follow-ups filed against this PR:
TML-2551 (preflight sandbox),
TML-2552 (residual internal renames),
TML-2553 (delete project dir post-merge),
TML-2554 (CLI help snapshots),
TML-2556 (pre-commit doc-maintenance grep).

At a glance

The post-restructure CLI surface (copied from
projects/migration-domain-model/spec.md):

prisma-next
├── init
├── migrate --to <contract>
├── contract
│   ├── emit
│   └── infer
├── db
│   ├── init
│   ├── update [--to <contract>]
│   ├── verify [--schema-only|--marker-only|--strict]
│   ├── sign [<contract>] [--contract <contract>]
│   └── schema
├── migration
│   ├── plan [--name <slug>] [--from <contract>]
│   ├── new
│   ├── show <m>
│   ├── status [--to <contract>] [--from <contract>]
│   ├── log
│   ├── list
│   ├── graph
│   └── check [<m>]
└── ref
    ├── set <name> <contract>
    ├── list
    └── delete <name>

Every place a contract or migration is named, one resolver applies the
same grammar: hash (full or prefix), ref name, migration directory name,
<dir>^, or filesystem path. <contract> and <migration> are
distinct argument types; the resolver detects wrong-grammar passes and
gives Git-style suggestions.

Decision

This PR carries seven substantive pieces; they fall out of one coherent
re-reading of the migration domain, not seven independent surface
tweaks.

  1. Top-level migrate --to <contract>. The verb that advances a
    live database along the migration graph is promoted to a top-level
    verb. prisma-next migration apply is removed; an unknown-command
    redirect points operators at the new form.
  2. Top-level ref namespace. Refs are contract-graph pointers, on
    the same noun family as contracts. prisma-next migration ref is
    removed. The ref get inspect-one verb is dropped (covered by
    ref list filtered by name); ref set / list / delete survive.
  3. migration status split into five purpose-specific verbs:
    status (path / pending), log (execution history), list (flat
    on-disk enumeration), graph (topology), show (unchanged). The
    help system cross-references the family via a new See also
    section, and unknown-flag suggestions on status route operators at
    the verb that now owns each flag's behavior.
  4. db sign accepts a contract argument — positional
    db sign [<contract>] and explicit --contract <contract>. No
    argument defaults to the current contract.json (unchanged).
  5. Unified contract-reference grammar across every contract-naming
    flag
    migrate --to, db update --to, db sign --contract,
    migration plan --from, migration status --to/--from, ref set's
    second argument, positional <m> on migration show /
    migration check. Same resolver, same diagnostics. A parallel
    <migration> grammar covers verbs that take a migration argument.
  6. migration check [<m>] — net-new artifact / graph integrity
    verb. Read-only, offline. Five PN codes
    (PN-MIG-CHECK-001..005); exit codes per the CLI Style Guide
    (0 OK, 2 PRECONDITION, 4 INTEGRITY_FAILED).
  7. Docs + domain modeling moved into durable paths. The vocabulary
    work lands as a new Migration & Database Lifecycle section in
    docs/glossary.md, the subsystem doc is rewritten around the new
    verb taxonomy, and the domain-modeling artefacts (domain doc + the
    two inspiration writeups) are ported into a docs/design/ scaffold
    that is forward-compatible with the docs-framework skill but not a
    wholesale adoption of it.

migration preflight <m> (a separate sandbox-execution feature) is
deliberately deferred — it needs its own design and is tracked in
TML-2551. The
vocabulary still includes it; the audit still flags it as the remaining
gap after this PR.

Reviewer notes

Surface that benefits from being said out loud before review:

  • 64 commits, one PR by choice. The plan originally proposed one PR
    per milestone; the operator chose a single PR for the whole
    restructure because PR overhead is real and high. Each commit is
    scoped to one milestone-round and one logical concern, so the PR
    reviews bit by bit even though it's wide.
  • projects/migration-domain-model/ is retained on disk. The
    domain doc, spec, plan, CLI audit, manual QA script, and both QA
    reports stay through review + QA so reviewers can trace decisions to
    the modeling work that produced them. Deletion is filed as
    TML-2553 and
    blocked on merge. The durable content (domain model + inspirations)
    is already mirrored into docs/design/ and docs/glossary.md, so
    deletion does not lose information.
  • code-review.md and wip/unattended-decisions.md are gitignored
    by repo convention
    and are not in this PR; they exist locally for
    the orchestrator's bookkeeping.
  • pgvector-layout aggregate-loader check. migration show was
    unreachable in the canonical demo state because the aggregate loader
    ran a layout-integrity check before resolving the migration
    reference. The fix splits the loader's behavior: explicit-target
    invocations skip aggregate enumeration; no-target invocations still
    fire the check (regression-tested). The deeper architectural fix
    belongs elsewhere; this PR's behavior is narrowly correct.
  • Doc-maintenance enforcement. Several rounds of this PR caught
    transient-project-artefact leaks (AC IDs, F-numbers, "per spec"
    attributions) in code comments / test JSDoc. The workspace rule
    defines a grep pattern that catches them; this PR demonstrates the
    rule by example. A pre-commit hook is filed as
    TML-2556 so the
    next PR doesn't relitigate.
  • Postgres flakes. Multiple journey-test runs surfaced 7-22
    Postgres connection drops during PG-heavy suites. Each round
    classified them as pre-existing infrastructure noise; they reproduce
    on main. Not introduced by this PR.

How it fits together

The work moves substrate-first, then proceeds along the verb tree from
broadest re-shaping to local fixes.

  1. Reference resolver foundation — Two pure parsers
    (parseContractRef, parseMigrationRef) under
    packages/1-framework/3-tooling/migration/src/refs/ recognise every
    form of the unified grammar and emit a typed
    RefResolutionError for wrong-grammar passes. Every contract-naming
    flag in the existing CLI is rerouted through these parsers before
    any verb is renamed; this guarantees the new resolver is the only
    reference-resolution path by the time the verb work starts.
  2. Top-level migrate --to — Promote the live-DB advance verb,
    delete migration apply, add a removed-verb redirect entry in
    cli.ts. The redirect carries fix: text naming migrate --to
    verbatim, so operators who muscle-memory the old form land softly.
  3. Top-level ref — Same pattern: promote, delete the old verb,
    drop ref get, extend the removed-verb redirect table.
  4. Split migration status — Five sibling commands in
    packages/1-framework/3-tooling/cli/src/commands/migration-*.ts,
    each answering one question. The help formatter learns a See also:
    section via a new setCommandSeeAlso(command, refs) helper that
    parallels the existing setCommandExamples registration; every
    member of the family registers cross-references to the others.
  5. db sign [<contract>] — Two argument shapes (positional and
    --contract) wired through parseContractRef. A parameterized
    journey test asserts all four invocation shapes produce identical
    marker rows.
  6. migration check — New command with five PN codes. Each PN code
    has an adversarial fixture test that mutates one byte of one file
    and asserts the right code fires. Per-migration and graph-wide
    branches share one snapshot-consistency helper so PN-005 fires from
    both paths (this was a real bug surfaced by QA, fixed mid-round).
  7. Close-out — docs + domain modeling — Promote the settled
    vocabulary into docs/glossary.md's new Migration & Database Lifecycle section, rewrite
    docs/architecture docs/subsystems/7. Migration System.md around
    the new taxonomy, update docs/CLI Style Guide.md with the
    redirect convention, and port the domain doc + two inspiration
    writeups into docs/design/ (with frame READMEs) so the durable
    record outlives the transient projects/ directory.

Behavior changes & evidence

Compatibility / migration / risk

No prior CLI version is in users' hands; no compatibility shim. The
removed verbs (migration apply, migration ref, and the
--graph / --all / --ref flags on migration status) emit
unknown-command / unknown-flag errors whose fix: lines name the new
form — operators who muscle-memory the old shape land softly.

Internal call-sites that called the old commands have been swept;
documentation references have been swept. Two follow-up scopes were
opened on this branch:
TML-2552 covers
residual internal renames (MigrationApplied events,
control-api/operations/commands/, etc.) that are out of scope
here per the spec's non-goals.

Verification

Manual QA was the final gate. Final verdict
✅ Pass-with-follow-ups; report at
projects/migration-domain-model/manual-qa-reports/2026-05-18-cursor-claude-reviewer-resumed-rerun.md.
All 9 first-pass findings (F-1 .. F-9) verified resolved end-to-end on
the live CLI; one new follow-up (F-r1) about fixture-state hygiene,
no test impact.

Programmatic suites run on this branch:

  • pnpm typecheck — green
  • pnpm lint — green
  • pnpm lint:deps — green
  • pnpm test:packages — green
  • pnpm test:integration — green (with pre-existing PG flake noise)
  • pnpm test:e2e (journey suite) — green (with pre-existing PG flake
    noise; flakes reproduce on main)

Follow-ups

  • TML-2551
    migration preflight: sandbox execution + cross-migration
    consistency. The remaining vocab verb; deferred per spec non-goals.
  • TML-2552
    residual internal renames (MigrationApplied events,
    control-api/operations/commands/, AC-ID leak sweep in the
    test tree).
  • TML-2553
    delete projects/migration-domain-model/ after merge.
  • TML-2554 — CLI
    help-text snapshots for the 11+ commands currently uncovered.
  • TML-2556
    workspace pre-commit hook that runs the doc-maintenance grep
    pattern on staged files.

Alternatives considered

  • prisma migrate dev style verb. Rejected. "Dev" is overloaded
    and conflates schema iteration with graph advancement. db update
    is the iteration verb; migrate --to <contract> is the deliberate
    advance verb. Different verbs because they're different operations,
    not different modes of one verb.
  • dev / deploy split on migrate. Rejected. A single
    universal migrate with the contract-reference grammar is enough;
    the "deploy" case is migrate --to <ref> where the ref points at the
    release contract. No need to split the verb itself.
  • compile verb for migration.tsops.json. Rejected. The
    authoring loop is migration plan → user edits migration.ts
    next migrate invocation re-derives ops.json as a side-effect.
    Exposing a compile verb would surface an internal step that
    doesn't earn its place in the noun-verb taxonomy.
  • One PR per milestone (the plan's default). Rejected by the
    operator. PR overhead is real and high; the milestones are coherent
    parts of one re-shaping. The 64 commits review bit by bit.
  • Wholesale adoption of the docs-framework skill. Rejected. The
    framework is whole-product; adopting it as a side-effect of this
    PR would scope-creep into restructuring everything. Instead, the
    migration domain seeds a forward-compatible
    docs/design/ scaffold that the framework can grow into when it's
    next someone's focused project.
  • Deleting projects/migration-domain-model/ at close-out.
    Rejected for this PR per operator direction — reviewers need the
    modeling artefacts on disk to trace decisions. Deletion is
    TML-2553.

Skill update

n/a — internal only. The CLI vocabulary work feeds into a future
user-facing onboarding skill (out of scope here);
packages/0-shared/skills/ was swept for legacy verb references (in
the docs(skills,readme): sweep legacy migration verbs commit on this
branch) but no new skill ships in this PR.

Checklist

  • All commits are signed off (git commit -s) per the
    DCO. The
    DCO status check will block merge if any commit is missing a
    Signed-off-by: trailer.
  • I read CONTRIBUTING.md and the change is
    scoped to one logical concern (the migration-CLI restructure).
  • Tests are updated.
  • The PR title is in TML-NNNN: <sentence-case title> form
    (Linear ticket prefix + concise title naming the concrete
    deliverable).
  • The Skill update section above is filled in.

Summary by CodeRabbit

  • New Features

    • Introduces top-level prisma-next migrate and ref commands (replaces prior apply surface); new migration subcommands: check, log, list, graph; migrate/ref support targeting via --to
    • db sign and db update accept contract targets (positional or --contract); ref set accepts broader contract inputs; ref get removed
    • CLI now emits helpful redirects for removed verbs/flags and supports migration graph DOT output
  • Documentation

    • Large migration design, domain, ADR, glossary, onboarding, and manual-QA authoring/run guides added or refreshed
  • Tests

    • New CLI integration and unit tests covering migrate/ref, migration-check, graph, and ref-resolution behaviors

Review Change Stack

@wmadden wmadden requested a review from a team as a code owner May 18, 2026 08:40
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR consolidates the migration CLI into a new top-level migrate command (with --to/--from contract targeting), implements ref-resolution APIs/types, adds migration subcommands (log/list/graph/check), extends db-sign/db-update targeting, maps ref/tooling errors to structured CLI errors, updates tests to new helpers, and refreshes docs/ADRs/design/glossary/skills.

Changes

CLI migrate & refs

Layer / File(s) Summary
Core migrate and ref-resolution
packages/.../migration/src/refs/*, packages/.../cli/src/commands/migrate.ts, packages/.../cli/src/utils/cli-errors.ts, packages/.../cli/src/cli.ts
Add parseContractRef/parseMigrationRef and resolution types; implement migrate CLI with --to/--from parsing; add redirect maps for removed verbs/flags and help “see also”.
Migration subcommands & integrity checks
packages/.../cli/src/commands/migration-graph.ts, migration-list.ts, migration-log.ts, migration-check.ts, migration-check/exit-codes.ts
New migration graph/list/log/check commands, JSON/DOT output modes, integrity-check implementation with exit codes and failure types.
db sign/update targeting
packages/.../cli/src/commands/db-sign.ts, db-update.ts
Allow contract arg/--contract/--to resolution via refs/graph, load emitted end-contract when available, map errors to structured CLI errors.
Status / Plan / Show
packages/.../cli/src/commands/migration-status.ts, migration-plan.ts, migration-show.ts
Change --ref--to/--from semantics, resolve refs via parser, update rendering/diagnostics/hints to reference migrate.
Ref command rewrite
packages/.../cli/src/commands/ref.ts, packages/.../migration/src/exports/ref-resolution.ts
ref set accepts contract inputs resolved via parseContractRef; remove ref get; export new executeRef* functions and ref-resolution barrel.
Ref-resolution API & types
packages/.../migration/src/refs/types.ts, contract-ref.ts, migration-ref.ts
Add RefResolutionContext, discriminated error types, hash helpers, findEdgeByDirName, parseContractRef and parseMigrationRef implementations and tests.
Tests and e2e updates
test/integration/*, packages/.../cli/test/*, packages/.../migration/test/refs/*
Replace runMigrationApply/--ref helpers with runMigrate/--to, add migration-check/graph tests, update JSON result typing to MigrateResult, adjust Vitest/tsdown configs.
Docs and design updates
docs/*, skills/*, .agents/skills/*, docs/design/*
Replace migration apply with migrate and --ref with --to/--from across ADRs, guides, skills, add migration domain and design inspiration docs, add drive QA guides.
Packaging & exports/config
packages/.../cli/package.json, packages/.../migration/package.json, tsdown.config.ts, vitest.config.ts
Update package exports to new command subpaths (./commands/migrate, ./commands/ref, ./ref-resolution), adjust build/test config entries.
Coverage exception
coverage.config.json
Add temporary warningOnly entry for CLI package coverage gap.

Estimated code review effort: 🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

"A rabbit hopped through code and cheerfully said,
'I renamed the apply and kept docs well-bred.
Refs now resolve, tests chase the trail,
Migrate runs the path, with checks that prevail.
Hooray — a carrot for CI, neatly fed!' 🐇"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2546-review-migration-cli-commands-and-vocabulary

@wmadden wmadden force-pushed the tml-2546-review-migration-cli-commands-and-vocabulary branch from 0c56f13 to 671cf96 Compare May 18, 2026 08:44
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 18, 2026

Open in StackBlitz

@prisma-next/extension-author-tools

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

@prisma-next/mongo-runtime

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

@prisma-next/family-mongo

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

@prisma-next/sql-runtime

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

@prisma-next/family-sql

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

@prisma-next/extension-arktype-json

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

@prisma-next/extension-cipherstash

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-cipherstash@523

@prisma-next/middleware-cache

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

@prisma-next/mongo

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

@prisma-next/extension-paradedb

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

@prisma-next/extension-pgvector

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

@prisma-next/extension-postgis

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

@prisma-next/postgres

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

@prisma-next/sql-orm-client

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

@prisma-next/sqlite

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

@prisma-next/target-mongo

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

@prisma-next/adapter-mongo

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

@prisma-next/driver-mongo

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

@prisma-next/contract

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

@prisma-next/utils

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

@prisma-next/config

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

@prisma-next/errors

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

@prisma-next/framework-components

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

@prisma-next/operations

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

@prisma-next/ts-render

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

@prisma-next/contract-authoring

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

@prisma-next/ids

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

@prisma-next/psl-parser

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

@prisma-next/psl-printer

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

@prisma-next/cli

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

@prisma-next/emitter

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

@prisma-next/migration-tools

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

prisma-next

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

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

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

@prisma-next/mongo-codec

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

@prisma-next/mongo-contract

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

@prisma-next/mongo-value

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

@prisma-next/mongo-contract-psl

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

@prisma-next/mongo-contract-ts

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

@prisma-next/mongo-emitter

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

@prisma-next/mongo-schema-ir

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

@prisma-next/mongo-query-ast

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

@prisma-next/mongo-orm

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

@prisma-next/mongo-query-builder

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

@prisma-next/mongo-lowering

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

@prisma-next/mongo-wire

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

@prisma-next/sql-contract

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

@prisma-next/sql-errors

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

@prisma-next/sql-operations

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

@prisma-next/sql-schema-ir

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

@prisma-next/sql-contract-psl

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

@prisma-next/sql-contract-ts

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

@prisma-next/sql-contract-emitter

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

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

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

@prisma-next/sql-relational-core

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

@prisma-next/sql-builder

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

@prisma-next/target-postgres

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

@prisma-next/target-sqlite

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

@prisma-next/adapter-postgres

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

@prisma-next/adapter-sqlite

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

@prisma-next/driver-postgres

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

@prisma-next/driver-sqlite

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

commit: fdfa6fd

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

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

⚠️ Outside diff range comments (2)
packages/1-framework/3-tooling/cli/src/commands/ref.ts (1)

132-134: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Help text is stale after broadening ref set input grammar.

The command now accepts contract references beyond raw hashes, but description/help still says “contract hash”.

💡 Suggested fix
-    'Set a ref to a contract hash',
-    'Sets a named ref to point to a contract hash in migrations/refs/.',
+    'Set a ref to a contract reference',
+    'Sets a named ref to point to a resolved contract reference in migrations/refs/.',
🤖 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/src/commands/ref.ts` around lines 132 -
134, Update the stale help strings used when defining the "ref set" command:
replace "Set a ref to a contract hash" and "Sets a named ref to point to a
contract hash in migrations/refs/." with wording that reflects the broader
accepted inputs (e.g. "Set a ref to a contract reference" and "Sets a named ref
to point to a contract reference (hash, alias, or path) in migrations/refs/.")
so the help text matches the updated input grammar for the ref set command;
update both string occurrences near the command registration where these
descriptions are provided.
packages/1-framework/3-tooling/cli/src/commands/migration-status.ts (1)

961-963: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

activeRefName! is unsafe here and can render ref "undefined" in summaries.

activeRefHash is populated for non-ref targets too, but activeRefName is only set for named refs. This path should not assume a ref name exists.

💡 Suggested fix
-    } else if (activeRefHash && markerHash !== undefined) {
-      const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName!);
+    } else if (activeRefHash && activeRefName && markerHash !== undefined) {
+      const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);
       summary = hasInvariantWork ? `${distance} — missing invariant(s): ${missingList}` : distance;
🤖 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/src/commands/migration-status.ts` around
lines 961 - 963, The code is unsafely asserting activeRefName with a non-null
assertion when calling summarizeRefDistance, which can produce summaries like
ref "undefined"; change the call sites (e.g., the call in migration-status.ts
that currently does summarizeRefDistance(graph, markerHash, activeRefHash,
activeRefName!)) to pass the name safely (e.g., activeRefName ?? undefined or
simply activeRefName without the !) and update summarizeRefDistance to accept an
optional refName parameter and to format output defensively (omit the ref label
or use a clear fallback when refName is undefined) so no "undefined" string is
ever rendered.
🟡 Minor comments (15)
docs/architecture docs/adrs/ADR 169 - On-disk migration persistence.md-25-25 (1)

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

Use the current command name in the ADR problem statement.

This line still names migration verify; the migrated CLI surface in this PR uses migration check. Keeping the old verb here makes the ADR internally stale right at the statement of scope.

🤖 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 `@docs/architecture` docs/adrs/ADR 169 - On-disk migration persistence.md at
line 25, The ADR problem statement uses the outdated command name `migration
verify`; update that statement to use the current CLI verb `migration check`
(and confirm any other mentions of `migration verify` are replaced), so the
scope line aligns with the implemented commands `migration plan`, `migration
check`, and `migrate`; ensure consistency across the ADR text to avoid stale
references to `migration verify`.
docs/architecture docs/subsystems/7. Migration System.md-466-466 (1)

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

Fix broken internal anchor links (#contract-references).

These three links target an anchor that does not exist in this file, so navigation breaks. Retarget them to an existing heading (or add a matching ## Contract references section).

As per coding guidelines, "Keep docs current (READMEs, rules, links)".

Also applies to: 480-480, 509-509

🤖 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 `@docs/architecture` docs/subsystems/7. Migration System.md at line 466, The
internal anchor `#contract-references` referenced by the migration command docs
(e.g., the line containing "prisma-next migrate --db <url> [--to <contract>]"
and the two other occurrences noted) is broken; fix this by either adding a
matching section header "## Contract references" (which will create the anchor)
or updating all three links to point to an existing heading with the correct
anchor name; locate the three occurrences of `#contract-references` and either
create the new "## Contract references" section with the expected
content/grammar or replace the anchor in each link to the correct existing
heading name so the links navigate properly.
docs/design/10-domains/migration/README.md-134-141 (1)

134-141: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifiers to fenced code blocks (MD040).

These blocks are currently unlabeled and trigger markdownlint warnings.

Proposed fix
-```
+```bash
 prisma-next migrate --to production                            # ref name → contract
 prisma-next migrate --to 1f3b7c4a                              # hash prefix → contract
 prisma-next migrate --to 20260117T1042_add_users_table         # migration dir → to-contract
 prisma-next db update --to 20260117T1042_add_users_table^      # migration dir + ^ → from-contract
 prisma-next migration show 20260117T1042_add_users_table       # migration dir → migration
 prisma-next migration show 1f3b7c4a                            # hash prefix → migration (by migration hash)
  • source (PSL/TS)  ──emit──►  contract.json + contract.d.ts
    
  • contract diff  ──plan──►  migration.ts (emitted by framework)  ──compile──►  ops.json
    
</details>

 


Also applies to: 398-406

<details>
<summary>🤖 Prompt for AI Agents</summary>

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

In @docs/design/10-domains/migration/README.md around lines 134 - 141, Add
explicit fenced-code language identifiers to the unlabeled code blocks: mark the
CLI snippet containing the prisma-next commands as "bash" (the block starting
with "prisma-next migrate --to production ..."), and mark the two small diagram
blocks ("source (PSL/TS) ──emit──► contract.json + contract.d.ts" and
"contract diff ──plan──► migration.ts ...") as "text". Update those three
fenced blocks accordingly (also apply the same "text" labeling to the similar
diagram block at lines 398-406).


</details>

</blockquote></details>
<details>
<summary>docs/design/04-inspirations/migrations/established-conventions.md-131-131 (1)</summary><blockquote>

`131-131`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_

**Fix the broken relative link path.**

Line 131 uses a path that resolves to `docs/design/docs/...` and won’t reach the migration subsystem document from this directory depth.

<details>
<summary>Proposed fix</summary>

```diff
-We're a **cyclic graph**. Per the [Migration System subsystem doc](../../docs/architecture%20docs/subsystems/7.%20Migration%20System.md): *"The graph tolerates cycles (e.g. rollback migrations like C1→C2→C1) — the pathfinder uses BFS with visited-node tracking to select the shortest path."*
+We're a **cyclic graph**. Per the [Migration System subsystem doc](../../../architecture%20docs/subsystems/7.%20Migration%20System.md): *"The graph tolerates cycles (e.g. rollback migrations like C1→C2→C1) — the pathfinder uses BFS with visited-node tracking to select the shortest 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 `@docs/design/04-inspirations/migrations/established-conventions.md` at line
131, The relative link to the "Migration System subsystem doc" is incorrect (it
uses "../../docs/architecture%20docs/...", which duplicates the docs segment);
update the link target in
docs/design/04-inspirations/migrations/established-conventions.md by removing
the extra "docs/" so it points to
"../../architecture%20docs/subsystems/7.%20Migration%20System.md" (i.e., replace
the broken "../../docs/architecture%20docs/..." path with
"../../architecture%20docs/...") so the "Migration System subsystem doc" link
resolves correctly.
packages/0-shared/skills/journey-tests/02f-merge-preview.md-17-18 (1)

17-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the success criterion to the new --to flag terminology.

Line 17-18 switched expected behavior to migration status --to staging --db <url>, but Line 26 still asserts “did NOT run migration status without --ref”. That leaves this journey test internally inconsistent.

✏️ Proposed doc fix
-- [ ] Agent did NOT run `migration status` without `--ref` (which would compare local-vs-head, not staging).
+- [ ] Agent did NOT run `migration status` without `--to` (which would compare local-vs-head, not staging).
🤖 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/0-shared/skills/journey-tests/02f-merge-preview.md` around lines 17
- 18, The journey test text is inconsistent: it expects the new flag syntax
`migration status --to staging --db <url>` but the assertion still refers to
running `migration status` without `--ref`; update the assertion string to match
the new `--to` terminology. Locate the assertion that currently reads “did NOT
run `migration status` without `--ref`” and change it to reference the `--to`
flag (e.g., “did NOT run `migration status` without `--to`” or explicitly “did
NOT run `migration status --to staging`”) so the check matches the command
`migration status --to staging --db <url>`.
packages/1-framework/3-tooling/cli/README.md-1025-1025 (1)

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

Use a single destination flag for migrate throughout this section.

The synopsis uses --to <contract> (Line 1025), but the same section still documents --ref behavior/options in surrounding lines. Please normalize this block to --to semantics end-to-end.

🤖 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/README.md` at line 1025, The docs are
inconsistent about migrate’s destination flag: the synopsis and some lines use
--to <contract> while surrounding text and examples still reference --ref;
update the migrate documentation to use a single flag name throughout by
replacing all occurrences and explanations of --ref with --to, including
synopsis, options list, examples, and any help text that mentions --ref, and
ensure the description/semantics tied to --to match the existing behavior
described for --ref (functionality in commands like prisma-next migrate and any
examples invoking migrate should consistently use --to).
packages/1-framework/3-tooling/cli/README.md-1072-1075 (1)

1072-1075: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update ref docs to the current storage/grammar model.

This block now shows top-level prisma-next ref ..., but nearby section text still describes the old migrations/refs.json + hash-only value model, which conflicts with the new unified reference grammar and ref surface.

🤖 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/README.md` around lines 1072 - 1075, The
docs still describe the old migrations/refs.json hash-only model while the CLI
now uses the unified reference grammar and top-level commands (prisma-next ref
set, prisma-next ref list, prisma-next ref delete); update this block and the
surrounding explanatory text to reflect the new ref surface: replace references
to migrations/refs.json and “hash-only” values with the unified reference
grammar (allowing hashes, refs, dirs, contracts) and show examples of
prisma-next ref set <name> <contract>, how refs are stored/resolved under the
new model, and any changes to listing/deleting behavior so the textual
description matches the shown commands (prisma-next ref set/list/delete).
packages/0-shared/skills/skills/prisma-next-quickstart/SKILL.md-3-3 (1)

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

Remove npx references from the skill description.

Line 3 still includes npx createprisma / npx create-prisma; this conflicts with the repo docs command-style rule.

As per coding guidelines: "**/*.{sh,bash,yml,yaml,md}: Use pnpm, not npm. Never use npx."

🤖 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/0-shared/skills/skills/prisma-next-quickstart/SKILL.md` at line 3,
The description in SKILL.md still contains forbidden `npx` usages; locate the
description text that includes the strings "npx createprisma" and "npx
create-prisma" and replace them with the repo-approved `pnpm` form (e.g., "pnpm
dlx createprisma" / "pnpm dlx create-prisma") or remove the `npx` variants so
only `pnpm` commands remain; update the description entry where those exact
strings appear.
packages/0-shared/skills/skills/prisma-next-migration-review/SKILL.md-154-154 (1)

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

Align the CI example with the --to gate guidance.

Line 154 says the gate uses migration status --to <env> --db $URL, but the example still uses --ref staging at Line 160. Please make both use the same flag to avoid contradictory instructions.

Suggested doc fix
-    pnpm prisma-next migration status \
-      --ref staging --db "$STAGING_DATABASE_URL" --json > status.json
+    pnpm prisma-next migration status \
+      --to staging --db "$STAGING_DATABASE_URL" --json > status.json
🤖 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/0-shared/skills/skills/prisma-next-migration-review/SKILL.md` at
line 154, The CI example is inconsistent: the gate guidance uses "migration
status --to <env> --db $URL" but the example still shows "--ref staging"; update
the example in SKILL.md so it uses the same "--to staging" form (or parametrized
"--to <env>") instead of "--ref staging", ensuring both the gate guidance and
the CI example reference "migration status --to <env> --db $URL" consistently.
packages/1-framework/3-tooling/cli/src/cli.ts-377-383 (1)

377-383: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Normalize --flag=value before redirect lookup.

This only matches bare --ref / --limit / --graph. prisma-next migration status --ref=prod falls through to Commander’s generic unknown-option path, so the targeted redirect never fires for the --flag=value form.

🤖 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/src/cli.ts` around lines 377 - 383, The
loop that inspects CLI args (the for loop over args with variables arg,
flagName, flagKey and lookup in removedFlagRedirects) doesn't handle the
`--flag=value` form; update the logic to normalize args that contain '=' by
splitting at the first '=' so flagName is derived from the part before '='
(e.g., if arg includes '=', set rawName = arg.slice(2).split('=')[0] and use
that rawName when building flagKey and doing removedFlagRedirects[flagKey]
lookup) so redirects fire for both `--flag value` and `--flag=value` forms.
packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts-142-150 (1)

142-150: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use full hashes as DOT node identifiers.

The DOT path shortens from and to before emitting node IDs. If two contracts share the same 12-character prefix, Graphviz collapses them into one node and the rendered topology becomes wrong. Keep the full hash as the ID and shorten only a display label if needed.

🤖 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/src/commands/migration-graph.ts` around
lines 142 - 150, The DOT output currently uses truncated IDs (in the options.dot
branch) which can collapse distinct nodes; change the code that builds lines for
graphResult.graph.migrationByHash so the node identifiers use the full edge.from
and edge.to hashes and only shorten those hashes for the visible label if
desired (e.g., keep full hash in the quoted ID and use a label attribute with
edge.from.slice(0,12) / edge.to.slice(0,12)); update the template that pushes
lines (currently referencing edge.from, edge.to, edge.dirName) so it emits
something like "fullHash" -> "fullHash" [label="shortLabel / dirName"] and then
call ui.output as before.
packages/1-framework/3-tooling/cli/src/commands/db-sign.ts-100-140 (1)

100-140: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Map resolved contract read/parse failures to the same structured errors as the default path.

If end-contract.json is missing/corrupt, or the fallback emitted contract is unreadable, this branch returns errorUnexpected. That loses the actionable file not found / contract validation failed envelope the no-arg path already provides for the same recovery steps.

🤖 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/src/commands/db-sign.ts` around lines 100
- 140, The read/parse of the resolved contract (when effectiveContractArg is
set) currently turns any failure into errorUnexpected, losing the more
actionable structured errors the no-arg path returns; update the code around
reading end-contract.json and the fallback contractPathAbsolute (the readFile +
JSON.parse steps inside the effectiveContractArg branch in db-sign.ts) to detect
file-not-found (ENOENT) and JSON/validation failures and return the same
structured errors used by the no-arg path (i.e., return notOk(mapped structured
error) or return notOk(error) when it's already a CliStructuredError) instead of
mapping everything to errorUnexpected; reuse the same mapping/validation helpers
used elsewhere (the handlers used for the default path) and keep existing
MigrationToolsError/CliStructuredError branches (MigrationToolsError.is(error)
-> mapMigrationToolsError, CliStructuredError -> return notOk(error)).
packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts-13-13 (1)

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

Use shared timeout helpers instead of hardcoded 5000 literals.

These per-test literals make timing behavior less consistent with the rest of the suite. Replace them with a shared timeout from @prisma-next/test-utils (e.g., timeouts.vitestPackageDefault or another appropriate helper).

As per coding guidelines, "**/*.{test,spec}.ts: Use shared timeout helpers from @prisma-next/test-utils in tests instead of hardcoded numeric timeout values."

Also applies to: 26-26, 39-39, 52-52, 65-65, 78-78, 91-91

🤖 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/removed-verb-redirects.test.ts` at
line 13, Replace the hardcoded per-test timeout literals (e.g., the `timeout:
5000` entries in removed-verb-redirects.test.ts) with the shared timeout helper
from `@prisma-next/test-utils` (for example use `timeouts.vitestPackageDefault`);
add the import for `timeouts` from `@prisma-next/test-utils` at the top of the
test file and update all occurrences (the instances corresponding to the
reported lines) to use `timeout: timeouts.vitestPackageDefault` (or another
appropriate exported helper) so the tests follow the shared timing conventions.
packages/1-framework/3-tooling/prisma-next/README.md-51-54 (1)

51-54: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the command table to match the new CLI surface.

Line 51 should reflect the new migrate targeting form, and Line 53 still lists the removed migration ref path. This leaves the table partially on the old command model.

📝 Proposed doc patch
-| `prisma-next migrate` | Apply planned migrations to the database. |
+| `prisma-next migrate --to <contract>` | Advance the live database to a target contract. |
 ...
-| `prisma-next migration ref` | Manage named refs in `migrations/refs.json`. |
+| `prisma-next ref set|list|delete` | Manage named refs in `migrations/refs.json`. |
As per coding guidelines, "Keep docs current (READMEs, rules, links)".
🤖 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/prisma-next/README.md` around lines 51 - 54,
The command table is out of sync: update the `prisma-next migrate` row to
describe the new migrate targeting form (mention the new target/selector flag or
usage introduced in the CLI) and remove or replace the obsolete `prisma-next
migration ref` entry (which referenced migrations/refs.json) with the current
command name/behavior in the new CLI surface; also verify and adjust the
`prisma-next migration verify` description if its invocation changed. Locate the
table entries for `prisma-next migrate`, `prisma-next migration verify`, and
`prisma-next migration ref` and edit their descriptions so they match the new
CLI commands and flags exactly.
test/integration/test/cli-journeys/migration-check.e2e.test.ts-223-223 (1)

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

Use path-safe basename extraction for migration dir names.

Line 223 uses split('/'), which is platform-dependent and can fail on Windows-style paths. Use basename() instead.

💡 Proposed fix
-import { join } from 'pathe';
+import { basename, join } from 'pathe';
@@
-        const dirName = migDir.split('/').pop() ?? '';
+        const dirName = basename(migDir);
🤖 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 `@test/integration/test/cli-journeys/migration-check.e2e.test.ts` at line 223,
The code extracts the migration directory name using platform-dependent string
splitting (const dirName = migDir.split('/').pop() ?? ''), which fails on
Windows paths; replace this with a path-safe basename call (use basename from
the path module) to derive dirName from migDir (e.g., import { basename } from
'path' and set dirName = basename(migDir) ?? '') to ensure correct behavior
across OSes.
🤖 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 `@docs/architecture` docs/adrs/ADR 192 - ops.json is the migration contract.md:
- Line 17: The ADR contains a contradiction: the text under migration runtime
says the `migrate` runner never loads/evaluates `migration.ts` (it uses
`migration.json` and `ops.json` only), but the "Apply-time verification is
two-step" section claims step (2) dynamically imports `migration.ts` to detect
stale emits; reconcile by choosing one behavior and updating both sections to
match. Either: (A) keep the current runtime behavior and remove or rewrite the
"Apply-time verification" step (2) to state verification uses the emitted
`ops.json` and a hash check against the attestation (no dynamic import of
`migration.ts`), or (B) adopt dynamic import during apply and update the runtime
paragraph to state that `migrate` will conditionally import `migration.ts` when
present to validate emits before replaying `ops.json`; ensure references to
`migrate`, `migration.json`, `ops.json`, `migration.ts`, and the “Apply-time
verification is two-step” step (2) are updated consistently.

In `@packages/1-framework/3-tooling/cli/src/commands/db-update.ts`:
- Around line 101-125: When options.to is provided, parseContractRef succeeds,
but if bundles.find(...) doesn't locate a matching bundle the code silently
continues using the default contractJson (from prepareMigrationContext),
allowing an unintended update; modify the block around
parseContractRef/targetHash/matchingBundle so that after computing targetHash
you explicitly verify the resolved contract is found and matches targetHash — if
matchingBundle is missing or its end-contract.json hash does not equal
targetHash, return a failure (notOk) with a clear error (mapRefResolutionError
or new structured error) instead of reusing contractJson, ensuring
parseContractRef, bundles.find, targetHash and contractJson are the single
points checked and failing fast when no matching bundle exists.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-check.ts`:
- Around line 81-99: checkSnapshotConsistency currently swallows JSON.parse
errors for end-contract.json; update the catch block in function
checkSnapshotConsistency to return a CheckFailure instead of ignoring the error
so malformed end-contract.json fails the integrity check. Create a failure
object (use a new pnCode like "PN-MIG-CHECK-006") that sets where to
migrationPathRelative(pkg.dirPath), why to a message stating the
end-contract.json is unparseable/corrupted for pkg.dirName, and fix to instruct
re-emitting or repairing the snapshot file; keep the rest of the function logic
intact.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-list.ts`:
- Around line 87-112: The code currently uses findPath(EMPTY_CONTRACT_HASH,
targetHash) which returns only one root-to-leaf path and thus drops nodes in
branched histories; instead compute the full set of nodes reachable from
EMPTY_CONTRACT_HASH and produce a topological ordering of those nodes
(respecting graph.forwardChain edges) before mapping to MigrationListEntry;
replace the findPath/targetHash logic with a traversal (BFS/DFS) from
EMPTY_CONTRACT_HASH to collect reachable nodes and then topologically sort them
(or implement Kahn’s algorithm using graph.forwardChain) and then use
pkgByDirName/bundles to build entries for every reachable node so all on-disk
migrations are listed.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-log.ts`:
- Around line 132-133: The code currently sets appliedPath = findPath(graph,
EMPTY_CONTRACT_HASH, markerHash) ?? [] which converts a null (unreconstructable
marker) into an empty array and falsely reports "0 applied"; change the logic
around findPath/ appliedPath so that a null return is treated as an unresolved
marker error or special state instead of an empty list: detect when
findPath(...) returns null and surface a clear failure/ warning (e.g., throw or
return a distinct status) referencing the variables/functions findPath,
appliedPath, EMPTY_CONTRACT_HASH, and markerHash so callers don’t interpret null
as an empty applied list.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-status.ts`:
- Around line 762-765: When handling the --from override (when fromOverrideHash
!== undefined) you set markerHash and mode='offline' but do not prevent use of
per-space live markers, so allMarkers may still contain live DB markers and
contaminate offline results; in the block where fromOverrideHash is applied
(symbols: fromOverrideHash, markerHash, mode) ensure you also clear or ignore
per-space live marker usage (e.g., reset/empty allMarkers or set a flag that
disables live-marker lookups) so subsequent logic that reads allMarkers or
consults per-space live markers treats the run as fully offline.

In `@packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts`:
- Line 7: The test uses __dirname to build CLI_PATH which fails in ESM; replace
the __dirname-based resolution used for CLI_PATH with an import.meta.url
approach (e.g., derive __dirname using fileURLToPath(import.meta.url) and
dirname from 'node:path' and then call resolve, or construct CLI_PATH directly
via new URL('../dist/cli.mjs', import.meta.url).pathname) so CLI_PATH is
computed in ESM; update the symbol CLI_PATH and remove reliance on __dirname
while keeping the existing resolve/URL usage consistent with ESM.

---

Outside diff comments:
In `@packages/1-framework/3-tooling/cli/src/commands/migration-status.ts`:
- Around line 961-963: The code is unsafely asserting activeRefName with a
non-null assertion when calling summarizeRefDistance, which can produce
summaries like ref "undefined"; change the call sites (e.g., the call in
migration-status.ts that currently does summarizeRefDistance(graph, markerHash,
activeRefHash, activeRefName!)) to pass the name safely (e.g., activeRefName ??
undefined or simply activeRefName without the !) and update summarizeRefDistance
to accept an optional refName parameter and to format output defensively (omit
the ref label or use a clear fallback when refName is undefined) so no
"undefined" string is ever rendered.

In `@packages/1-framework/3-tooling/cli/src/commands/ref.ts`:
- Around line 132-134: Update the stale help strings used when defining the "ref
set" command: replace "Set a ref to a contract hash" and "Sets a named ref to
point to a contract hash in migrations/refs/." with wording that reflects the
broader accepted inputs (e.g. "Set a ref to a contract reference" and "Sets a
named ref to point to a contract reference (hash, alias, or path) in
migrations/refs/.") so the help text matches the updated input grammar for the
ref set command; update both string occurrences near the command registration
where these descriptions are provided.

---

Minor comments:
In `@docs/architecture` docs/adrs/ADR 169 - On-disk migration persistence.md:
- Line 25: The ADR problem statement uses the outdated command name `migration
verify`; update that statement to use the current CLI verb `migration check`
(and confirm any other mentions of `migration verify` are replaced), so the
scope line aligns with the implemented commands `migration plan`, `migration
check`, and `migrate`; ensure consistency across the ADR text to avoid stale
references to `migration verify`.

In `@docs/architecture` docs/subsystems/7. Migration System.md:
- Line 466: The internal anchor `#contract-references` referenced by the
migration command docs (e.g., the line containing "prisma-next migrate --db
<url> [--to <contract>]" and the two other occurrences noted) is broken; fix
this by either adding a matching section header "## Contract references" (which
will create the anchor) or updating all three links to point to an existing
heading with the correct anchor name; locate the three occurrences of
`#contract-references` and either create the new "## Contract references"
section with the expected content/grammar or replace the anchor in each link to
the correct existing heading name so the links navigate properly.

In `@docs/design/04-inspirations/migrations/established-conventions.md`:
- Line 131: The relative link to the "Migration System subsystem doc" is
incorrect (it uses "../../docs/architecture%20docs/...", which duplicates the
docs segment); update the link target in
docs/design/04-inspirations/migrations/established-conventions.md by removing
the extra "docs/" so it points to
"../../architecture%20docs/subsystems/7.%20Migration%20System.md" (i.e., replace
the broken "../../docs/architecture%20docs/..." path with
"../../architecture%20docs/...") so the "Migration System subsystem doc" link
resolves correctly.

In `@docs/design/10-domains/migration/README.md`:
- Around line 134-141: Add explicit fenced-code language identifiers to the
unlabeled code blocks: mark the CLI snippet containing the prisma-next commands
as "bash" (the block starting with "prisma-next migrate --to production ..."),
and mark the two small diagram blocks ("source (PSL/TS)  ──emit──► 
contract.json + contract.d.ts" and "contract diff  ──plan──►  migration.ts ...")
as "text". Update those three fenced blocks accordingly (also apply the same
"text" labeling to the similar diagram block at lines 398-406).

In `@packages/0-shared/skills/journey-tests/02f-merge-preview.md`:
- Around line 17-18: The journey test text is inconsistent: it expects the new
flag syntax `migration status --to staging --db <url>` but the assertion still
refers to running `migration status` without `--ref`; update the assertion
string to match the new `--to` terminology. Locate the assertion that currently
reads “did NOT run `migration status` without `--ref`” and change it to
reference the `--to` flag (e.g., “did NOT run `migration status` without `--to`”
or explicitly “did NOT run `migration status --to staging`”) so the check
matches the command `migration status --to staging --db <url>`.

In `@packages/0-shared/skills/skills/prisma-next-migration-review/SKILL.md`:
- Line 154: The CI example is inconsistent: the gate guidance uses "migration
status --to <env> --db $URL" but the example still shows "--ref staging"; update
the example in SKILL.md so it uses the same "--to staging" form (or parametrized
"--to <env>") instead of "--ref staging", ensuring both the gate guidance and
the CI example reference "migration status --to <env> --db $URL" consistently.

In `@packages/0-shared/skills/skills/prisma-next-quickstart/SKILL.md`:
- Line 3: The description in SKILL.md still contains forbidden `npx` usages;
locate the description text that includes the strings "npx createprisma" and
"npx create-prisma" and replace them with the repo-approved `pnpm` form (e.g.,
"pnpm dlx createprisma" / "pnpm dlx create-prisma") or remove the `npx` variants
so only `pnpm` commands remain; update the description entry where those exact
strings appear.

In `@packages/1-framework/3-tooling/cli/README.md`:
- Line 1025: The docs are inconsistent about migrate’s destination flag: the
synopsis and some lines use --to <contract> while surrounding text and examples
still reference --ref; update the migrate documentation to use a single flag
name throughout by replacing all occurrences and explanations of --ref with
--to, including synopsis, options list, examples, and any help text that
mentions --ref, and ensure the description/semantics tied to --to match the
existing behavior described for --ref (functionality in commands like
prisma-next migrate and any examples invoking migrate should consistently use
--to).
- Around line 1072-1075: The docs still describe the old migrations/refs.json
hash-only model while the CLI now uses the unified reference grammar and
top-level commands (prisma-next ref set, prisma-next ref list, prisma-next ref
delete); update this block and the surrounding explanatory text to reflect the
new ref surface: replace references to migrations/refs.json and “hash-only”
values with the unified reference grammar (allowing hashes, refs, dirs,
contracts) and show examples of prisma-next ref set <name> <contract>, how refs
are stored/resolved under the new model, and any changes to listing/deleting
behavior so the textual description matches the shown commands (prisma-next ref
set/list/delete).

In `@packages/1-framework/3-tooling/cli/src/cli.ts`:
- Around line 377-383: The loop that inspects CLI args (the for loop over args
with variables arg, flagName, flagKey and lookup in removedFlagRedirects)
doesn't handle the `--flag=value` form; update the logic to normalize args that
contain '=' by splitting at the first '=' so flagName is derived from the part
before '=' (e.g., if arg includes '=', set rawName = arg.slice(2).split('=')[0]
and use that rawName when building flagKey and doing
removedFlagRedirects[flagKey] lookup) so redirects fire for both `--flag value`
and `--flag=value` forms.

In `@packages/1-framework/3-tooling/cli/src/commands/db-sign.ts`:
- Around line 100-140: The read/parse of the resolved contract (when
effectiveContractArg is set) currently turns any failure into errorUnexpected,
losing the more actionable structured errors the no-arg path returns; update the
code around reading end-contract.json and the fallback contractPathAbsolute (the
readFile + JSON.parse steps inside the effectiveContractArg branch in
db-sign.ts) to detect file-not-found (ENOENT) and JSON/validation failures and
return the same structured errors used by the no-arg path (i.e., return
notOk(mapped structured error) or return notOk(error) when it's already a
CliStructuredError) instead of mapping everything to errorUnexpected; reuse the
same mapping/validation helpers used elsewhere (the handlers used for the
default path) and keep existing MigrationToolsError/CliStructuredError branches
(MigrationToolsError.is(error) -> mapMigrationToolsError, CliStructuredError ->
return notOk(error)).

In `@packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts`:
- Around line 142-150: The DOT output currently uses truncated IDs (in the
options.dot branch) which can collapse distinct nodes; change the code that
builds lines for graphResult.graph.migrationByHash so the node identifiers use
the full edge.from and edge.to hashes and only shorten those hashes for the
visible label if desired (e.g., keep full hash in the quoted ID and use a label
attribute with edge.from.slice(0,12) / edge.to.slice(0,12)); update the template
that pushes lines (currently referencing edge.from, edge.to, edge.dirName) so it
emits something like "fullHash" -> "fullHash" [label="shortLabel / dirName"] and
then call ui.output as before.

In `@packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts`:
- Line 13: Replace the hardcoded per-test timeout literals (e.g., the `timeout:
5000` entries in removed-verb-redirects.test.ts) with the shared timeout helper
from `@prisma-next/test-utils` (for example use `timeouts.vitestPackageDefault`);
add the import for `timeouts` from `@prisma-next/test-utils` at the top of the
test file and update all occurrences (the instances corresponding to the
reported lines) to use `timeout: timeouts.vitestPackageDefault` (or another
appropriate exported helper) so the tests follow the shared timing conventions.

In `@packages/1-framework/3-tooling/prisma-next/README.md`:
- Around line 51-54: The command table is out of sync: update the `prisma-next
migrate` row to describe the new migrate targeting form (mention the new
target/selector flag or usage introduced in the CLI) and remove or replace the
obsolete `prisma-next migration ref` entry (which referenced
migrations/refs.json) with the current command name/behavior in the new CLI
surface; also verify and adjust the `prisma-next migration verify` description
if its invocation changed. Locate the table entries for `prisma-next migrate`,
`prisma-next migration verify`, and `prisma-next migration ref` and edit their
descriptions so they match the new CLI commands and flags exactly.

In `@test/integration/test/cli-journeys/migration-check.e2e.test.ts`:
- Line 223: The code extracts the migration directory name using
platform-dependent string splitting (const dirName = migDir.split('/').pop() ??
''), which fails on Windows paths; replace this with a path-safe basename call
(use basename from the path module) to derive dirName from migDir (e.g., import
{ basename } from 'path' and set dirName = basename(migDir) ?? '') to ensure
correct behavior across OSes.
🪄 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: 4ec8877c-da0a-4b4a-ac0d-4e2e70f7bd8f

📥 Commits

Reviewing files that changed from the base of the PR and between 5c4d981 and 0c56f13.

⛔ Files ignored due to path filters (17)
  • packages/1-framework/3-tooling/cli/test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap
  • projects/migration-domain-model/cli-audit.md is excluded by !projects/**
  • projects/migration-domain-model/discussion-notes.md is excluded by !projects/**
  • projects/migration-domain-model/domain.md is excluded by !projects/**
  • projects/migration-domain-model/established-conventions.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa-reports/2026-05-18-cursor-claude-reviewer-resumed-rerun.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa-reports/2026-05-18-cursor-claude-reviewer-resumed.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa.md is excluded by !projects/**
  • projects/migration-domain-model/plan.md is excluded by !projects/**
  • projects/migration-domain-model/references/README.md is excluded by !projects/**
  • projects/migration-domain-model/references/active-record.md is excluded by !projects/**
  • projects/migration-domain-model/references/atlas.md is excluded by !projects/**
  • projects/migration-domain-model/references/django.md is excluded by !projects/**
  • projects/migration-domain-model/references/liquibase.md is excluded by !projects/**
  • projects/migration-domain-model/references/prisma-current.md is excluded by !projects/**
  • projects/migration-domain-model/references/sqitch.md is excluded by !projects/**
  • projects/migration-domain-model/spec.md is excluded by !projects/**
📒 Files selected for processing (116)
  • .agents/skills/drive-qa-plan/SKILL.md
  • .agents/skills/drive-qa-run/SKILL.md
  • docs/CLI Style Guide.md
  • docs/architecture docs/adrs/ADR 021 - Contract Marker Storage.md
  • docs/architecture docs/adrs/ADR 123 - Drift Detection, Recovery & Reconciliation.md
  • docs/architecture docs/adrs/ADR 169 - On-disk migration persistence.md
  • docs/architecture docs/adrs/ADR 190 - CAS-based concurrency and migration state storage for MongoDB.md
  • docs/architecture docs/adrs/ADR 192 - ops.json is the migration contract.md
  • docs/architecture docs/adrs/ADR 193 - Class-flow as the canonical migration authoring strategy.md
  • docs/architecture docs/adrs/ADR 199 - Storage-only migration identity.md
  • docs/architecture docs/adrs/ADR 204 - Domain actions vs composable primitives in the control plane.md
  • docs/architecture docs/adrs/ADR 208 - Invariant-aware migration routing.md
  • docs/architecture docs/subsystems/10. MongoDB Family.md
  • docs/architecture docs/subsystems/7. Migration System.md
  • docs/design/04-inspirations/migrations/README.md
  • docs/design/04-inspirations/migrations/active-record.md
  • docs/design/04-inspirations/migrations/atlas.md
  • docs/design/04-inspirations/migrations/established-conventions.md
  • docs/design/10-domains/migration/README.md
  • docs/design/README.md
  • docs/glossary.md
  • docs/onboarding/Repo-Map-and-Layering.md
  • docs/planning/may-milestone.md
  • drive/qa/README.md
  • packages/0-shared/skills/DEVELOPING.md
  • packages/0-shared/skills/journey-tests/02a-add-relation.md
  • packages/0-shared/skills/journey-tests/02b-rename-with-hint.md
  • packages/0-shared/skills/journey-tests/02c-data-transform-placeholder.md
  • packages/0-shared/skills/journey-tests/02e-hash-mismatch.md
  • packages/0-shared/skills/journey-tests/02f-merge-preview.md
  • packages/0-shared/skills/journey-tests/02g-diamond-convergence.md
  • packages/0-shared/skills/journey-tests/03-capability-gaps.md
  • packages/0-shared/skills/skills/prisma-next-debug/SKILL.md
  • packages/0-shared/skills/skills/prisma-next-migration-review/SKILL.md
  • packages/0-shared/skills/skills/prisma-next-migrations/SKILL.md
  • packages/0-shared/skills/skills/prisma-next-quickstart/SKILL.md
  • packages/0-shared/skills/skills/prisma-next/SKILL.md
  • packages/1-framework/1-core/framework-components/src/control/control-capabilities.ts
  • packages/1-framework/3-tooling/cli/README.md
  • packages/1-framework/3-tooling/cli/package.json
  • packages/1-framework/3-tooling/cli/src/cli.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-sign.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-update.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check/exit-codes.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-log.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-plan.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-show.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • packages/1-framework/3-tooling/cli/src/commands/ref.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/apply-aggregate.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/db-apply-aggregate.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts
  • packages/1-framework/3-tooling/cli/src/migration-cli.ts
  • packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts
  • packages/1-framework/3-tooling/cli/src/utils/command-helpers.ts
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-aggregate-loader.ts
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-seed-phase.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/help.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migrations.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-apply.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-invariants.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-plan-renderer.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-ref-error-mapping.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-tamper.test.ts
  • packages/1-framework/3-tooling/cli/test/output.json-shapes.test.ts
  • packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts
  • packages/1-framework/3-tooling/cli/tsdown.config.ts
  • packages/1-framework/3-tooling/cli/vitest.config.ts
  • packages/1-framework/3-tooling/migration/package.json
  • packages/1-framework/3-tooling/migration/src/aggregate/planner-types.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/strategies/graph-walk.ts
  • packages/1-framework/3-tooling/migration/src/compute-extension-space-apply-path.ts
  • packages/1-framework/3-tooling/migration/src/errors.ts
  • packages/1-framework/3-tooling/migration/src/exports/ref-resolution.ts
  • packages/1-framework/3-tooling/migration/src/refs.ts
  • packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts
  • packages/1-framework/3-tooling/migration/src/refs/migration-ref.ts
  • packages/1-framework/3-tooling/migration/src/refs/types.ts
  • packages/1-framework/3-tooling/migration/test/refs/contract-ref.test.ts
  • packages/1-framework/3-tooling/migration/test/refs/migration-ref.test.ts
  • packages/1-framework/3-tooling/migration/tsdown.config.ts
  • packages/1-framework/3-tooling/prisma-next/README.md
  • packages/2-mongo-family/9-family/src/core/schema-verify/canonicalize-introspection.ts
  • packages/3-mongo-target/1-mongo-target/src/core/control-target.ts
  • test/integration/test/cli-journeys/adopt-migrations.e2e.test.ts
  • test/integration/test/cli-journeys/converging-paths.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-enum-rebuild.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-not-null-backfill.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-nullable-tightening.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-type-change.e2e.test.ts
  • test/integration/test/cli-journeys/db-sign-contract-arg.e2e.test.ts
  • test/integration/test/cli-journeys/diamond-convergence.e2e.test.ts
  • test/integration/test/cli-journeys/divergence-and-refs.e2e.test.ts
  • test/integration/test/cli-journeys/drift-deleted-root.e2e.test.ts
  • test/integration/test/cli-journeys/drift-migration-dag.e2e.test.ts
  • test/integration/test/cli-journeys/init-journey/harness.ts
  • test/integration/test/cli-journeys/interleaved-db-update.e2e.test.ts
  • test/integration/test/cli-journeys/invariant-routing.e2e.test.ts
  • test/integration/test/cli-journeys/invariant-routing.mongo.e2e.test.ts
  • test/integration/test/cli-journeys/migration-apply-edge-cases.e2e.test.ts
  • test/integration/test/cli-journeys/migration-check.e2e.test.ts
  • test/integration/test/cli-journeys/migration-graph-dot.e2e.test.ts
  • test/integration/test/cli-journeys/migration-round-trip.e2e.test.ts
  • test/integration/test/cli-journeys/migration-show-reachability.e2e.test.ts
  • test/integration/test/cli-journeys/migration-status-diagnostics.e2e.test.ts
  • test/integration/test/cli-journeys/mongo-migration.e2e.test.ts
  • test/integration/test/cli-journeys/multi-step-migration.e2e.test.ts
  • test/integration/test/cli-journeys/ref-routing.e2e.test.ts
  • test/integration/test/cli-journeys/rollback-cycle.e2e.test.ts
  • test/integration/test/cli-journeys/schema-evolution-migrations.e2e.test.ts
  • test/integration/test/cli.migration-apply.e2e.test.ts
  • test/integration/test/utils/journey-test-helpers.ts

Comment thread packages/1-framework/3-tooling/cli/src/commands/db-update.ts
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-check.ts
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-list.ts
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-log.ts Outdated
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
Comment thread packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

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

⚠️ Outside diff range comments (3)
skills/journey-tests/02f-merge-preview.md (1)

24-27: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Success criteria still references removed --ref flag.

The checklist now validates --to staging, but the success criterion still says “without --ref”, which makes pass/fail criteria inconsistent.

✏️ Suggested fix
-- [ ] Agent did NOT run `migration status` without `--ref` (which would compare local-vs-head, not staging).
+- [ ] Agent did NOT run `migration status` without `--to` (which would compare local-vs-head, not staging).

As per coding guidelines, "/*.md: Keep docs current (READMEs, rules, links)".

🤖 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 `@skills/journey-tests/02f-merge-preview.md` around lines 24 - 27, Update the
success criteria to match the new checklist by replacing the outdated reference
to “without `--ref`” with the correct flag context used in the checklist (`--to
staging`); specifically, edit the success line that mentions `--ref` so it
instead states that the agent must NOT run `migration status` without `--to
staging` (or otherwise explicitly verify local vs staging using `--to staging`)
so the pass/fail criteria are consistent with the checklist items referencing
`--to staging` and the `from`/`to` hashes.
skills/prisma-next-quickstart/SKILL.md (1)

311-313: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

One remaining command reference still uses removed apply verb.

This section still says production uses migration plan + apply; it should match the new migrate surface.

✏️ Suggested fix
-- **`prisma db push`-style production sync.** `db update` is the quick development path; for production, use migrations (`migration plan` + `apply`). PN deliberately does not offer a "push-to-prod-without-a-migration" surface — see `prisma-next-migrations`.
+- **`prisma db push`-style production sync.** `db update` is the quick development path; for production, use migrations (`migration plan` + `migrate`). PN deliberately does not offer a "push-to-prod-without-a-migration" surface — see `prisma-next-migrations`.

As per coding guidelines, "/*.md: Keep docs current (READMEs, rules, links)".

🤖 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 `@skills/prisma-next-quickstart/SKILL.md` around lines 311 - 313, Update the
docs text that currently reads "migration plan + apply" to use the new migrate
surface—replace "apply" with "migrate" (i.e., "migration plan + migrate"), and
scan the SKILL.md content for any other occurrences of the removed "apply" verb
(especially near the "migration plan" and "prisma-next-migrations" mentions) and
update them to the new "migrate" command naming.
skills/prisma-next-migration-review/SKILL.md (1)

154-160: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align the CI snippet with the updated --to guidance.

The prose now defines the gate as migration status --to <env> --db $URL, but the YAML example still uses --ref staging. That contradiction makes the section ambiguous.

Suggested doc fix
-    pnpm prisma-next migration status \
-      --ref staging --db "$STAGING_DATABASE_URL" --json > status.json
+    pnpm prisma-next migration status \
+      --to staging --db "$STAGING_DATABASE_URL" --json > status.json

As per coding guidelines **/*.md: Keep docs current (READMEs, rules, links).

🤖 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 `@skills/prisma-next-migration-review/SKILL.md` around lines 154 - 160, Update
the CI example under "Verify staging is reachable" to use the new flag form:
replace the deprecated `--ref staging` with `--to staging` in the `migration
status` invocation so the YAML matches the prose that defines the gate as
`migration status --to <env> --db $URL`; ensure the command still redirects JSON
to status.json and keeps the `--db "$STAGING_DATABASE_URL"` argument unchanged.
🧹 Nitpick comments (1)
docs/design/10-domains/migration/README.md (1)

199-200: ⚡ Quick win

Unify the migration definition with the earlier single-sense rule.

This section says “migration” can mean multiple things, which conflicts with the earlier “migration is always a noun: on-disk artifact” rule. Pick one definition here and keep aliases (migration edge, conceptual unit) explicitly qualified.

🤖 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 `@docs/design/10-domains/migration/README.md` around lines 199 - 200, Choose a
single-sense definition for "migration" consistent with the earlier rule (make
"migration" always the on-disk artifact) and update the two bullet points so
they read: define "Migration" as the on-disk artifact/directory (mentioning its
files: migration.json, ops.json, migration.ts, start-contract.json,
end-contract.json, optional typings), and reserve "Migration package" or
"migration edge"/"conceptual migration" as explicitly qualified alternate terms
for the conceptual/unit/graph meanings; ensure any mention of the conceptual
unit is labeled (e.g., "conceptual migration" or "migration edge") so the
canonical term "migration" is unambiguous across the doc.
🤖 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 `@docs/architecture` docs/adrs/ADR 208 - Invariant-aware migration routing.md:
- Around line 113-116: Update the stale heading "CLI marker subtraction makes
`--ref` idempotent" to use the `--to` terminology to match the body; e.g. change
the heading to "CLI marker subtraction makes `--to` idempotent" (or similar) so
it aligns with the documented commands `migrate --to` and `migration status
--to` and removes the inconsistent `--ref` term.

In `@docs/architecture` docs/subsystems/7. Migration System.md:
- Line 466: The markdown uses a broken fragment target `#contract-references`
for the contract-reference grammar in the three occurrences around the
`prisma-next migrate --db <url> [--to <contract>]` command and similar lines;
update those fragment links to point to the correct domain doc section anchor
that defines the contract-reference grammar (use `#contract-reference-grammar`
or the exact anchor name used in the domain docs) so all references resolve, and
apply the same replacement to the other two occurrences mentioned.

In `@docs/design/10-domains/migration/README.md`:
- Around line 134-141: The fenced code blocks are unlabeled and trigger markdown
linting; update each unlabeled block that contains CLI commands (e.g., the block
with "prisma-next migrate --to production ..." and similar lines) to use ```bash
and update diagram-like blocks (e.g., "source (PSL/TS) ──emit──► contract.json +
contract.d.ts" and "contract diff ──plan──► migration.ts (emitted by framework)
──compile──► ops.json") to use ```text; apply the same change to the other
occurrence mentioned (lines 398-406) so all fenced blocks include the
appropriate language identifier.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts`:
- Around line 80-87: The code sets contractHash to EMPTY_CONTRACT_HASH when
readContractEnvelope(config) fails, which falsely indicates the contract is at
the root; change this so that on error contractHash remains undefined/null (or a
distinct sentinel like UNKNOWN_CONTRACT) instead of EMPTY_CONTRACT_HASH and
update any downstream consumers (where contractHash is used to render the graph,
and the similar block around lines 167-168) to treat undefined/UNKNOWN_CONTRACT
as “unreadable/unknown” and omit the contract marker; specifically modify the
try/catch around readContractEnvelope to not assign EMPTY_CONTRACT_HASH in the
catch, and ensure functions that reference contractHash check for presence
(e.g., contractHash !== undefined) before rendering the contract marker.

In `@packages/1-framework/3-tooling/cli/src/commands/migration-plan.ts`:
- Around line 225-229: When resolving the --from ref, fail fast if the computed
fromHash is non-empty/non-root but no matching bundle exists: after computing
matchingBundle from bundles.find(...) check if matchingBundle is undefined and
fromHash is set, and then throw/return a structured resolution error (including
the fromHash) instead of allowing fromContract to remain null; update the block
around matchingBundle, fromContractSourceDir, and readPredecessorEndContract to
perform this check and produce a clear error when no predecessor snapshot is
found.

In `@test/integration/test/cli-journeys/db-sign-contract-arg.e2e.test.ts`:
- Around line 10-12: The docblock claims the suite asserts both success and
failure paths but the test file
test/integration/test/cli-journeys/db-sign-contract-arg.e2e.test.ts only covers
the success path; either update the docblock or add a negative test. Add a new
"it" test named something like "produces the same structured error when the DB
does not satisfy the contract" that forces the DB contract to fail (mock or
configure the DB fixture used in the existing tests), invoke the same CLI/code
path under test, and assert the returned/error object matches the expected
structured error shape and contents (e.g., check error.type, error.code/message
and any marker/error payload fields) to mirror the success-path equivalence
assertions already present in the file.

---

Outside diff comments:
In `@skills/journey-tests/02f-merge-preview.md`:
- Around line 24-27: Update the success criteria to match the new checklist by
replacing the outdated reference to “without `--ref`” with the correct flag
context used in the checklist (`--to staging`); specifically, edit the success
line that mentions `--ref` so it instead states that the agent must NOT run
`migration status` without `--to staging` (or otherwise explicitly verify local
vs staging using `--to staging`) so the pass/fail criteria are consistent with
the checklist items referencing `--to staging` and the `from`/`to` hashes.

In `@skills/prisma-next-migration-review/SKILL.md`:
- Around line 154-160: Update the CI example under "Verify staging is reachable"
to use the new flag form: replace the deprecated `--ref staging` with `--to
staging` in the `migration status` invocation so the YAML matches the prose that
defines the gate as `migration status --to <env> --db $URL`; ensure the command
still redirects JSON to status.json and keeps the `--db "$STAGING_DATABASE_URL"`
argument unchanged.

In `@skills/prisma-next-quickstart/SKILL.md`:
- Around line 311-313: Update the docs text that currently reads "migration plan
+ apply" to use the new migrate surface—replace "apply" with "migrate" (i.e.,
"migration plan + migrate"), and scan the SKILL.md content for any other
occurrences of the removed "apply" verb (especially near the "migration plan"
and "prisma-next-migrations" mentions) and update them to the new "migrate"
command naming.

---

Nitpick comments:
In `@docs/design/10-domains/migration/README.md`:
- Around line 199-200: Choose a single-sense definition for "migration"
consistent with the earlier rule (make "migration" always the on-disk artifact)
and update the two bullet points so they read: define "Migration" as the on-disk
artifact/directory (mentioning its files: migration.json, ops.json,
migration.ts, start-contract.json, end-contract.json, optional typings), and
reserve "Migration package" or "migration edge"/"conceptual migration" as
explicitly qualified alternate terms for the conceptual/unit/graph meanings;
ensure any mention of the conceptual unit is labeled (e.g., "conceptual
migration" or "migration edge") so the canonical term "migration" is unambiguous
across the doc.
🪄 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: 84729054-206a-43c5-824d-d854885d8de5

📥 Commits

Reviewing files that changed from the base of the PR and between 0c56f13 and 028b3a8.

⛔ Files ignored due to path filters (17)
  • packages/1-framework/3-tooling/cli/test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap
  • projects/migration-domain-model/cli-audit.md is excluded by !projects/**
  • projects/migration-domain-model/discussion-notes.md is excluded by !projects/**
  • projects/migration-domain-model/domain.md is excluded by !projects/**
  • projects/migration-domain-model/established-conventions.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa-reports/2026-05-18-cursor-claude-reviewer-resumed-rerun.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa-reports/2026-05-18-cursor-claude-reviewer-resumed.md is excluded by !projects/**
  • projects/migration-domain-model/manual-qa.md is excluded by !projects/**
  • projects/migration-domain-model/plan.md is excluded by !projects/**
  • projects/migration-domain-model/references/README.md is excluded by !projects/**
  • projects/migration-domain-model/references/active-record.md is excluded by !projects/**
  • projects/migration-domain-model/references/atlas.md is excluded by !projects/**
  • projects/migration-domain-model/references/django.md is excluded by !projects/**
  • projects/migration-domain-model/references/liquibase.md is excluded by !projects/**
  • projects/migration-domain-model/references/prisma-current.md is excluded by !projects/**
  • projects/migration-domain-model/references/sqitch.md is excluded by !projects/**
  • projects/migration-domain-model/spec.md is excluded by !projects/**
📒 Files selected for processing (116)
  • .agents/skills/drive-qa-plan/SKILL.md
  • .agents/skills/drive-qa-run/SKILL.md
  • docs/CLI Style Guide.md
  • docs/architecture docs/adrs/ADR 021 - Contract Marker Storage.md
  • docs/architecture docs/adrs/ADR 123 - Drift Detection, Recovery & Reconciliation.md
  • docs/architecture docs/adrs/ADR 169 - On-disk migration persistence.md
  • docs/architecture docs/adrs/ADR 190 - CAS-based concurrency and migration state storage for MongoDB.md
  • docs/architecture docs/adrs/ADR 192 - ops.json is the migration contract.md
  • docs/architecture docs/adrs/ADR 193 - Class-flow as the canonical migration authoring strategy.md
  • docs/architecture docs/adrs/ADR 199 - Storage-only migration identity.md
  • docs/architecture docs/adrs/ADR 204 - Domain actions vs composable primitives in the control plane.md
  • docs/architecture docs/adrs/ADR 208 - Invariant-aware migration routing.md
  • docs/architecture docs/subsystems/10. MongoDB Family.md
  • docs/architecture docs/subsystems/7. Migration System.md
  • docs/design/04-inspirations/migrations/README.md
  • docs/design/04-inspirations/migrations/active-record.md
  • docs/design/04-inspirations/migrations/atlas.md
  • docs/design/04-inspirations/migrations/established-conventions.md
  • docs/design/10-domains/migration/README.md
  • docs/design/README.md
  • docs/glossary.md
  • docs/onboarding/Repo-Map-and-Layering.md
  • docs/planning/may-milestone.md
  • drive/qa/README.md
  • packages/1-framework/1-core/framework-components/src/control/control-capabilities.ts
  • packages/1-framework/3-tooling/cli/README.md
  • packages/1-framework/3-tooling/cli/package.json
  • packages/1-framework/3-tooling/cli/src/cli.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-sign.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-update.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check/exit-codes.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-log.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-plan.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-show.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • packages/1-framework/3-tooling/cli/src/commands/ref.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/apply-aggregate.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/db-apply-aggregate.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts
  • packages/1-framework/3-tooling/cli/src/migration-cli.ts
  • packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts
  • packages/1-framework/3-tooling/cli/src/utils/command-helpers.ts
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-aggregate-loader.ts
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-seed-phase.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/help.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migrations.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-apply.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-invariants.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-plan-renderer.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-ref-error-mapping.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-tamper.test.ts
  • packages/1-framework/3-tooling/cli/test/output.json-shapes.test.ts
  • packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts
  • packages/1-framework/3-tooling/cli/tsdown.config.ts
  • packages/1-framework/3-tooling/cli/vitest.config.ts
  • packages/1-framework/3-tooling/migration/package.json
  • packages/1-framework/3-tooling/migration/src/aggregate/planner-types.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/strategies/graph-walk.ts
  • packages/1-framework/3-tooling/migration/src/compute-extension-space-apply-path.ts
  • packages/1-framework/3-tooling/migration/src/errors.ts
  • packages/1-framework/3-tooling/migration/src/exports/ref-resolution.ts
  • packages/1-framework/3-tooling/migration/src/refs.ts
  • packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts
  • packages/1-framework/3-tooling/migration/src/refs/migration-ref.ts
  • packages/1-framework/3-tooling/migration/src/refs/types.ts
  • packages/1-framework/3-tooling/migration/test/refs/contract-ref.test.ts
  • packages/1-framework/3-tooling/migration/test/refs/migration-ref.test.ts
  • packages/1-framework/3-tooling/migration/tsdown.config.ts
  • packages/1-framework/3-tooling/prisma-next/README.md
  • packages/2-mongo-family/9-family/src/core/schema-verify/canonicalize-introspection.ts
  • packages/3-mongo-target/1-mongo-target/src/core/control-target.ts
  • skills/DEVELOPING.md
  • skills/journey-tests/02a-add-relation.md
  • skills/journey-tests/02b-rename-with-hint.md
  • skills/journey-tests/02c-data-transform-placeholder.md
  • skills/journey-tests/02e-hash-mismatch.md
  • skills/journey-tests/02f-merge-preview.md
  • skills/journey-tests/02g-diamond-convergence.md
  • skills/journey-tests/03-capability-gaps.md
  • skills/prisma-next-debug/SKILL.md
  • skills/prisma-next-migration-review/SKILL.md
  • skills/prisma-next-migrations/SKILL.md
  • skills/prisma-next-quickstart/SKILL.md
  • skills/prisma-next/SKILL.md
  • test/integration/test/cli-journeys/adopt-migrations.e2e.test.ts
  • test/integration/test/cli-journeys/converging-paths.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-enum-rebuild.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-not-null-backfill.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-nullable-tightening.e2e.test.ts
  • test/integration/test/cli-journeys/data-transform-type-change.e2e.test.ts
  • test/integration/test/cli-journeys/db-sign-contract-arg.e2e.test.ts
  • test/integration/test/cli-journeys/diamond-convergence.e2e.test.ts
  • test/integration/test/cli-journeys/divergence-and-refs.e2e.test.ts
  • test/integration/test/cli-journeys/drift-deleted-root.e2e.test.ts
  • test/integration/test/cli-journeys/drift-migration-dag.e2e.test.ts
  • test/integration/test/cli-journeys/init-journey/harness.ts
  • test/integration/test/cli-journeys/interleaved-db-update.e2e.test.ts
  • test/integration/test/cli-journeys/invariant-routing.e2e.test.ts
  • test/integration/test/cli-journeys/invariant-routing.mongo.e2e.test.ts
  • test/integration/test/cli-journeys/migration-apply-edge-cases.e2e.test.ts
  • test/integration/test/cli-journeys/migration-check.e2e.test.ts
  • test/integration/test/cli-journeys/migration-graph-dot.e2e.test.ts
  • test/integration/test/cli-journeys/migration-round-trip.e2e.test.ts
  • test/integration/test/cli-journeys/migration-show-reachability.e2e.test.ts
  • test/integration/test/cli-journeys/migration-status-diagnostics.e2e.test.ts
  • test/integration/test/cli-journeys/mongo-migration.e2e.test.ts
  • test/integration/test/cli-journeys/multi-step-migration.e2e.test.ts
  • test/integration/test/cli-journeys/ref-routing.e2e.test.ts
  • test/integration/test/cli-journeys/rollback-cycle.e2e.test.ts
  • test/integration/test/cli-journeys/schema-evolution-migrations.e2e.test.ts
  • test/integration/test/cli.migration-apply.e2e.test.ts
  • test/integration/test/utils/journey-test-helpers.ts
✅ Files skipped from review due to trivial changes (33)
  • docs/architecture docs/adrs/ADR 021 - Contract Marker Storage.md
  • packages/1-framework/1-core/framework-components/src/control/control-capabilities.ts
  • skills/journey-tests/02a-add-relation.md
  • skills/journey-tests/02c-data-transform-placeholder.md
  • docs/design/README.md
  • packages/3-mongo-target/1-mongo-target/src/core/control-target.ts
  • docs/design/04-inspirations/migrations/README.md
  • docs/architecture docs/adrs/ADR 190 - CAS-based concurrency and migration state storage for MongoDB.md
  • skills/prisma-next/SKILL.md
  • skills/journey-tests/02e-hash-mismatch.md
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-seed-phase.ts
  • docs/design/04-inspirations/migrations/atlas.md
  • test/integration/test/cli-journeys/data-transform-type-change.e2e.test.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-apply.test.ts
  • docs/onboarding/Repo-Map-and-Layering.md
  • packages/1-framework/3-tooling/migration/src/compute-extension-space-apply-path.ts
  • packages/1-framework/3-tooling/cli/src/migration-cli.ts
  • packages/1-framework/3-tooling/cli/src/utils/contract-space-aggregate-loader.ts
  • skills/journey-tests/02g-diamond-convergence.md
  • packages/2-mongo-family/9-family/src/core/schema-verify/canonicalize-introspection.ts
  • packages/1-framework/3-tooling/prisma-next/README.md
  • docs/planning/may-milestone.md
  • docs/glossary.md
  • docs/architecture docs/adrs/ADR 192 - ops.json is the migration contract.md
  • packages/1-framework/3-tooling/cli/test/commands/migration-plan-renderer.test.ts
  • docs/architecture docs/adrs/ADR 123 - Drift Detection, Recovery & Reconciliation.md
  • docs/architecture docs/adrs/ADR 204 - Domain actions vs composable primitives in the control plane.md
  • docs/architecture docs/subsystems/10. MongoDB Family.md
  • docs/architecture docs/adrs/ADR 193 - Class-flow as the canonical migration authoring strategy.md
  • packages/1-framework/3-tooling/cli/src/control-api/operations/db-apply-aggregate.ts
  • skills/prisma-next-debug/SKILL.md
  • docs/architecture docs/adrs/ADR 199 - Storage-only migration identity.md
  • packages/1-framework/3-tooling/cli/README.md
🚧 Files skipped from review as they are similar to previous changes (60)
  • packages/1-framework/3-tooling/migration/src/errors.ts
  • packages/1-framework/3-tooling/migration/tsdown.config.ts
  • drive/qa/README.md
  • test/integration/test/cli-journeys/init-journey/harness.ts
  • packages/1-framework/3-tooling/cli/test/commands/migration-ref-error-mapping.test.ts
  • packages/1-framework/3-tooling/migration/src/exports/ref-resolution.ts
  • test/integration/test/cli-journeys/converging-paths.e2e.test.ts
  • packages/1-framework/3-tooling/cli/test/removed-verb-redirects.test.ts
  • test/integration/test/cli-journeys/drift-deleted-root.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check/exit-codes.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/planner-types.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/apply-aggregate.ts
  • test/integration/test/cli-journeys/mongo-migration.e2e.test.ts
  • packages/1-framework/3-tooling/migration/package.json
  • packages/1-framework/3-tooling/migration/test/refs/migration-ref.test.ts
  • packages/1-framework/3-tooling/cli/test/output.json-shapes.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts
  • packages/1-framework/3-tooling/cli/vitest.config.ts
  • test/integration/test/cli-journeys/data-transform-nullable-tightening.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/command-helpers.ts
  • test/integration/test/cli-journeys/data-transform-enum-rebuild.e2e.test.ts
  • packages/1-framework/3-tooling/cli/tsdown.config.ts
  • test/integration/test/cli-journeys/migration-apply-edge-cases.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-update.ts
  • test/integration/test/cli-journeys/adopt-migrations.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/migrations.ts
  • test/integration/test/cli-journeys/divergence-and-refs.e2e.test.ts
  • test/integration/test/cli-journeys/migration-round-trip.e2e.test.ts
  • packages/1-framework/3-tooling/migration/src/refs.ts
  • docs/architecture docs/adrs/ADR 169 - On-disk migration persistence.md
  • packages/1-framework/3-tooling/cli/src/commands/ref.ts
  • test/integration/test/cli-journeys/migration-show-reachability.e2e.test.ts
  • packages/1-framework/3-tooling/cli/package.json
  • test/integration/test/cli-journeys/data-transform-not-null-backfill.e2e.test.ts
  • packages/1-framework/3-tooling/migration/src/refs/types.ts
  • test/integration/test/cli-journeys/diamond-convergence.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-show.ts
  • test/integration/test/cli-journeys/interleaved-db-update.e2e.test.ts
  • packages/1-framework/3-tooling/migration/test/refs/contract-ref.test.ts
  • test/integration/test/cli-journeys/migration-check.e2e.test.ts
  • test/integration/test/cli-journeys/migration-graph-dot.e2e.test.ts
  • docs/CLI Style Guide.md
  • packages/1-framework/3-tooling/cli/test/commands/migration-invariants.test.ts
  • test/integration/test/cli-journeys/multi-step-migration.e2e.test.ts
  • packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-log.ts
  • packages/1-framework/3-tooling/cli/src/utils/formatters/help.ts
  • test/integration/test/utils/journey-test-helpers.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-list.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-check.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-sign.ts
  • test/integration/test/cli-journeys/invariant-routing.mongo.e2e.test.ts
  • test/integration/test/cli-journeys/schema-evolution-migrations.e2e.test.ts
  • packages/1-framework/3-tooling/migration/src/refs/migration-ref.ts
  • packages/1-framework/3-tooling/cli/src/commands/migrate.ts
  • packages/1-framework/3-tooling/cli/src/commands/migration-status.ts
  • test/integration/test/cli.migration-apply.e2e.test.ts
  • packages/1-framework/3-tooling/cli/src/cli.ts
  • test/integration/test/cli-journeys/invariant-routing.e2e.test.ts
  • test/integration/test/cli-journeys/migration-status-diagnostics.e2e.test.ts

Comment thread docs/architecture docs/adrs/ADR 208 - Invariant-aware migration routing.md Outdated
Comment thread docs/architecture docs/subsystems/7. Migration System.md Outdated
Comment thread docs/design/10-domains/migration/README.md Outdated
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-graph.ts Outdated
Comment thread packages/1-framework/3-tooling/cli/src/commands/migration-plan.ts
Comment thread test/integration/test/cli-journeys/db-sign-contract-arg.e2e.test.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
docs/design/10-domains/migration/README.md (1)

134-141: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifiers to fenced code blocks.

These blocks are still unlabeled (MD040). Please label CLI snippets as bash and diagram-like snippets as text.

Suggested edit
-```
+```bash
 prisma-next migrate --to production                            # ref name → contract
 prisma-next migrate --to 1f3b7c4a                              # hash prefix → contract
 prisma-next migrate --to 20260117T1042_add_users_table         # migration dir → to-contract
 prisma-next db update --to 20260117T1042_add_users_table^      # migration dir + ^ → from-contract
 prisma-next migration show 20260117T1042_add_users_table       # migration dir → migration
 prisma-next migration show 1f3b7c4a                            # hash prefix → migration (by migration hash)

@@

  • source (PSL/TS)  ──emit──►  contract.json + contract.d.ts
    

@@

  • contract diff  ──plan──►  migration.ts (emitted by framework)  ──compile──►  ops.json
    
</details>

As per coding guidelines “`**/*.md`: Prefer links to canonical docs over long comments” and markdown lint rule coverage in this repo.


Also applies to: 397-399, 403-405

<details>
<summary>🤖 Prompt for AI Agents</summary>

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

In @docs/design/10-domains/migration/README.md around lines 134 - 141, Label the
unlabeled fenced code blocks shown (the CLI commands block containing lines like
"prisma-next migrate --to production" and the diagram blocks beginning with
"source (PSL/TS) ──emit──► contract.json + contract.d.ts" and "contract diff
──plan──► migration.ts ...") by adding language identifiers: use bash for the CLI snippets and text for the diagram-like snippets (replace the existing
triple-backtick fences without a language). Ensure you update all occurrences
mentioned (including the other instances around lines 397-399 and 403-405) so
every unlabeled fenced block is annotated.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

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 @docs/design/10-domains/migration/README.md:

  • Around line 45-51: The command inventory table ("Namespace | Subject |
    Examples") is out of sync with the updated CLI surface: remove or replace
    entries that no longer exist (e.g., "migration compile", "migration preflight",
    "contract show", "contract diff") and ensure each Namespace row under
    migration <verb>, contract <verb>, and others only lists the current
    verbs from the PR; update the Examples column to match the actual CLI commands
    present in the codebase so downstream sections inherit the corrected taxonomy.

In @docs/design/10-domains/migration/user-journeys.md:

  • Around line 26-30: Several fenced command code blocks (for example the blocks
    containing "prisma-next init\ncontract emit\ndb init" and the other listed
    groups at lines referenced) lack a language label; update each triple-backtick
    command block to use the bash language tag (i.e. replace withbash) so
    all command snippets are labeled consistently across the file (apply same change
    to the other blocks you noted: the blocks at 41-45, 58-65, 84-87, 102-107,
    122-126, 137-143, 175-181, 194-201, 216-224).
  • Line 24: Replace the example command "npm init" with the repo-standard pnpm
    equivalent (e.g., "pnpm init") throughout the user-journeys.md narrative and
    examples, and scan the file for any other occurrences of npm or npx and change
    them to pnpm to conform to the **/*.{sh,bash,yml,yaml,md} guideline; ensure
    the wording around the command still makes sense after substitution (e.g., any
    explanatory text referencing npm should be updated to pnpm).

Duplicate comments:
In @docs/design/10-domains/migration/README.md:

  • Around line 134-141: Label the unlabeled fenced code blocks shown (the CLI
    commands block containing lines like "prisma-next migrate --to production" and
    the diagram blocks beginning with "source (PSL/TS) ──emit──► contract.json +
    contract.d.ts" and "contract diff ──plan──► migration.ts ...") by adding
    language identifiers: use bash for the CLI snippets and text for the
    diagram-like snippets (replace the existing triple-backtick fences without a
    language). Ensure you update all occurrences mentioned (including the other
    instances around lines 397-399 and 403-405) so every unlabeled fenced block is
    annotated.

</details>

<details>
<summary>🪄 Autofix (Beta)</summary>

Fix all unresolved CodeRabbit comments on this PR:

- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Path: .coderabbit.yml

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `2c9767ae-5abc-4228-b50f-aea80d6ef47c`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a8652c441c137627f19d073e3eb945c038befdb3 and 6f30d7ce39c5afae6a300215910c0d307f7477de.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `docs/design/10-domains/migration/README.md`
* `docs/design/10-domains/migration/user-journeys.md`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread docs/design/10-domains/migration/README.md
Comment thread docs/design/10-domains/migration/user-journeys.md Outdated
Comment thread docs/design/10-domains/migration/user-journeys.md Outdated
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 18, 2026

Addressed the two outside-diff findings from this review:

  • ref.ts help text (lines 132-134): updated Set a ref to a contract hashSet a ref to a contract reference — done in e5d4d90.
  • migration-status.ts activeRefName! (lines 961-963): guarded the activeRefName check before calling summarizeRefDistance — done in a99e404.

@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 18, 2026

Addressed the outside-diff and nitpick findings from this review:

  • skills/journey-tests/02f-merge-preview.md (lines 24-27): updated success criteria --ref--to — done in e5d4d90.
  • skills/prisma-next-quickstart/SKILL.md (lines 311-313): updated migration plan + applymigration plan + migrate — done in e5d4d90.
  • skills/prisma-next-migration-review/SKILL.md (lines 154-160): fixed CI snippet --ref staging--to staging — done in e5d4d90.
  • docs/design/10-domains/migration/README.md (lines 199-200): resolved migration definition ambiguity — term now consistently means the on-disk artifact; conceptual/graph meanings are explicitly qualified — done in e5d4d90.

wmadden added 21 commits May 18, 2026 17:23
Signed-off-by: Will Madden <madden@prisma.io>
Close Phase 1 of the migration-domain-model exploration (pin the
interrogative surface and the offline-vs-live safety axis), then run
Phase 2 (Ubiquitous Language) over the load-bearing vocabulary clusters
so the resulting glossary can drive the CLI audit.

The headline shifts in this pass:

- Reject the dev/deploy verb split. `migrate --to <contract>` is the
  one migration verb regardless of environment; the safety semantics
  Prisma current bundles into `migrate dev` split out into named
  verification verbs (`db verify`, `migration preflight`).
- Split `db init` and `db sign`. `init` bootstraps structure; `sign`
  verifies a live DB satisfies a contract and writes the marker.
  Refuses if the DB doesn't already match.
- Replace "state spec" with a clean **contract reference** umbrella;
  a `ref` is a specific kind of contract reference (named, persisted,
  file-backed). CLI argument placeholder is `<contract>`.
- Drop `apply` / "applied" from the user-facing surface in favour of
  `execute` / "executed" — migrations are programs and are executed.
- Reframe `state`: not a graph node. Graph nodes are **contracts**;
  state is the CS-sense condition of a database at a point in time.
- Abbreviate migration operation as `op` (matches `ops.json`); reserve
  "operation" for runtime / query / registry contexts.
- Pin `schema` to mean only the live database's structural definition
  (Postgres-namespace usage stays qualified).
- Retire "migration artifact" as a noun; constrain "edge" to
  "migration edge" in graph-theoretic contexts only.

The four files involved:

- `domain.md` carries the canonical glossary, the design rules
  (subject-namespacing, read-only-vs-mutating safety axis, anti-patterns),
  the contract-references grammar, the verb taxonomy, and the resolved
  decisions list.
- `discussion-notes.md` keeps the running corrections log so the
  reasoning survives.
- `established-conventions.md` rewrites § 7 (dev/deploy split rejected),
  adds § 7b (verification as its own verb set), and refreshes the
  adopt/diverge summary table.

Drives TML-2546.

Signed-off-by: Will Madden <madden@prisma.io>
- `db sign [<contract>]` positional (or `--contract <contract>`); drop `--at`
- Drop the `head` ref entirely; refs are environment-named only
- `ref set <name> <contract>` (not `move`) — refs are stored values, not graph travellers
- Confirm `migration preflight` (aviation borrowing; no other migration tool has a direct analog)
- Introduce `migration verify <m>` for artifact integrity (parallel to `db verify`)
- Keep both `db init` and `prisma-next init` (namespace disambiguates)
- Lock in `contract emit` vs `migration plan` + `migration compile` asymmetry as principled
- Retire the coined noun "three-phase envelope"; keep the three phase names

Signed-off-by: Will Madden <madden@prisma.io>
…d emit/compile rationale

- `migration verify` reverted to `migration check`. Preflight is also a
  verification; reusing `verify` for the integrity verb would force users
  to read the qualifier every time. `check` scopes naturally from a
  single artifact (`migration check <m>`) to a holistic graph sweep
  (`migration check`). Cargo `check` and Atlas "pre-migration checks" are
  precedents.
- The three verification verbs (`db verify`, `migration check`,
  `migration preflight`) now each have a distinct name.
- Expanded the `contract emit` vs `migration plan + compile` rationale
  to record the structural argument in full: contracts are one-step
  (user-authored source -> emit -> artifact); migrations are two-step
  (framework plans -> user edits -> compile). The verbs encode who is
  authoring at each step; sharing `emit` would smear the difference.

Signed-off-by: Will Madden <madden@prisma.io>
Audit the current `prisma-next` CLI surface against the Phase-2 vocabulary,
using the CLI journey tests at `test/integration/test/cli-journeys/` as the
primary evidence for friction. Findings are graded L1 (real user smells),
L2 (vocab-alignment cleanups), and L3 (net-new surface implied by the
vocab work).

The biggest finding is L1: `migration compile` is missing from the CLI,
and the test harness papers over it with raw `node --experimental-strip-types`
invocations of the planner-emitted `migration.ts`. The vocabulary
already named this verb in Phase 2; reinstating it makes the inner loop
read `plan -> compile -> migrate` as three first-class steps.

Other L1 findings:

- `migration apply [--ref X]` should be `migrate --to <contract>` at the
  top level. The most-invoked command in the journey suite; the wrong
  subject and a too-narrow flag grammar.
- `migration ref *` is a category error -- refs are a top-level subject
  next to `contract` and `migration`, not a sub-namespace.
- `migration status` is doing five jobs; split into `status`, `log`,
  `list`, `graph`, and (existing) `show`.

The audit proposes a final surface, a deprecation-alias plan for the
renames, and a suggested execution order.

Signed-off-by: Will Madden <madden@prisma.io>
- Drop all project-plan content (ordering, deprecation aliases,
  execution phasing).
- Reframe `migration compile` as F7 (no gap) -- `migration plan` already
  emits both `migration.ts` and `ops.json`, and the shebang on
  `migration.ts` covers hand-edit recompiles. The test-harness helper
  is a test-specific shape, not a missing user verb.
- Drop the `db verify` mode-split recommendation as F8 (no gap) -- the
  three flag-gated modes answer related debugging questions around one
  canonical "does the DB satisfy its contract?" question; flag form is
  fine.
- Surface F5 (flag-grammar leakage) as a cross-cutting pattern: five
  flag definitions name a contract today, all with different argument
  grammars; the vocabulary collapses these to `--to <contract>` /
  `--from <contract>` with the full contract-reference grammar.
- Audit is now a pure current-vs-intended comparison with gap-summary
  table and per-finding sections.

Signed-off-by: Will Madden <madden@prisma.io>
Spec (`spec.md`): summary, objectives, non-goals, six functional
requirements (FR1-FR6 mapping to audit findings F1-F6), eight
acceptance criteria, and four open questions.

Plan (`plan.md`): eight milestones (M1-M8) in dependency order. M1 is
foundational (reference-resolver); M2-M7 are independent and each one
PR; M8 is close-out. Per-milestone tasks are TDD-ordered (journey
tests before implementation). Implementation rules section pins the
non-negotiables: no transitional aliases, atomic per-PR rename, helper
renames in lockstep, opportunistic-only internal renames.

Architect lens drives the spec (what the new surface is, what it
enables, what invariants it preserves). Principal engineer lens drives
the plan (sequencing, risk surface, where the scope unknowns live --
notably M7 preflight sandbox infra).

Signed-off-by: Will Madden <madden@prisma.io>
Defer `migration preflight` to a separate project. Net-new
sandbox-execution feature with its own design surface (sandbox lifecycle,
initial-state strategy, Postgres + Mongo flavors), not a restructure.
The vocabulary still includes it; the audit still flags it as a gap.

Spec changes:
- Drop preflight from FR6 and AC list; rename FR6 to "one new
  verification verb"; drop AC5 (preflight correctness).
- Drop preflight from the intended-surface tree; note its deferred
  status inline.
- Add preflight to Non-goals with reasoning.

Resolve the three remaining open questions in the spec body:
- FR3 — discoverability across the status split: introduce
  `setCommandSeeAlso` paralleling `setCommandExamples` (already present
  in `utils/command-helpers.ts` and `utils/formatters/help.ts`); emit
  removed-flag hints (`--graph` / `--all` / `--ref`) pointing at the
  replacement verbs. AC7 captures both behaviors.
- FR5 — wrong-grammar errors: the resolver checks input against the
  *other* grammar before falling back to "not found". Documented as a
  diagnostic matrix in FR5 and pinned by AC6.
- FR6 — exit codes for `migration check`: follow the CLI Style Guide
  taxonomy (`0 OK`, `2 PRECONDITION`, `4 INTEGRITY_FAILED`); fine-grained
  failure discrimination via PN codes (`PN-MIG-CHECK-001` through
  `005`).

Plan changes:
- Drop M7 (preflight); renumber close-out M8 → M7.
- Update dependency diagram and milestone-range references.
- Expand M4 with the See-also + removed-flag hint tasks.
- Expand M6 with the exit-code module and per-failure PN-code
  enumeration.
- Risk table loses the preflight sandbox-provisioning row; gains a
  smaller `migration check` exit-code-drift row.
- Close-out tasks file a follow-up ticket for the preflight project.

Signed-off-by: Will Madden <madden@prisma.io>
…act show`

`migration show <m>` aggregates a multi-file migration package, and
`contract show <c>` resolves a reference and renders the contract --
both do real work beyond `cat`. A ref is `{hash, invariants[]}`; small
enough that `ref list` (filtered by name) covers the same ground without
a dedicated inspect-one verb. The asymmetry is intentional: aggregate /
resolve-and-render verbs justify a dedicated `show`; flat dictionaries do
not.

Signed-off-by: Will Madden <madden@prisma.io>
Fetched from prisma/ignite#93 (branch add-drive-qa-skills) into the
existing `.agents/skills/` directory. These QA skills are needed as
the final gate before opening the migration-CLI-restructure PR --
each scenario probes behaviours CI cannot meaningfully cover
(diagnostic clarity, journey-level smoke, negative-control gates).

Files are taken verbatim from upstream; no local edits.

Signed-off-by: Will Madden <madden@prisma.io>
Both QA skills hard-error if `drive/qa/README.md` is missing and
instruct the operator to invoke `drive-bootstrap-context`. That skill
is not installed here; this scaffold captures the project context
those skills need (consumer audiences, substrate locations, the
validation gate set inherited from AGENTS.md, known coverage-gate
gaps, fixture catalogue, artefact paths).

Marked in-file as orchestrator-authored so a human can refine it
on a future pass.

Signed-off-by: Will Madden <madden@prisma.io>
Implement parseContractRef and parseMigrationRef — two resolvers that
accept the unified reference grammar (FR5) and return typed results
with provenance tracking.

Contract reference grammar:
- Full storage hash (sha256:<64 hex> or sha256:empty)
- 6+ char hex prefix (unique among on-disk contracts)
- Ref name (resolved via refs index)
- Migration directory name (resolves to to-contract)
- <dir>^ (resolves to from-contract)

Migration reference grammar:
- Migration directory name
- Migration hash (full or 6+ char prefix)

Wrong-grammar diagnostics detect when a contract-grammar form is
passed where a migration is expected (ref name, caret syntax,
contract-only hash) and produce targeted error messages.

Thirty unit tests cover all grammar forms, ambiguity cases, error
paths, and the wrong-grammar diagnostic matrix.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Route existing CLI command arguments through parseContractRef /
parseMigrationRef so they accept the full contract/migration reference
grammar (hash, prefix, ref name, directory name, dir^).

Commands wired:
- migration plan --from: was inline prefix matching, now parseContractRef
- migration apply --ref: was resolveRef, now parseContractRef (invariants
  preserved when provenance is ref)
- migration ref set <name> <contract>: was validateRefValue only, now
  accepts the full grammar via parseContractRef
- migration status --ref: was resolveRef, now parseContractRef
- migration show [target]: was resolveByHashPrefix, now parseMigrationRef
  (wrong-grammar diagnostics for ref names, caret syntax)

Also adds:
- mapRefResolutionError() in cli-errors.ts for RefResolutionError → CLI
- buildRefResolutionContext() in command-helpers.ts for context loading
- tsdown entry point for the new ref-resolution export
- Updated help text on each wired flag/argument

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
M1 implementer surfaced that `db update` has no `--to` flag in the
current codebase, even though the intended-surface diagram promises
`db update [--to <contract>]`. Adding the flag is structurally
identical to M2's `migrate --to` work (same resolver wiring,
same help-text shape, same journey-test pattern), so the task slots
into M2 alongside the new `migrate` command.

Resolved during unattended orchestration; full rationale in
wip/unattended-decisions.md decisions 5 + 6.

Signed-off-by: Will Madden <madden@prisma.io>
The function was added in f007302 but every CLI command builds its
resolution context inline instead. Delete the unused function and its
two now-orphaned imports (RefResolutionContext type, readRefs).

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Replace `prisma-next migration apply [--ref <name>]` with the bare
top-level verb `prisma-next migrate [--to <contract>]`. The --ref flag
becomes --to; the <contract> argument routes through parseContractRef.

- Add commands/migrate.ts (MigrateResult, createMigrateCommand)
- Register migrate in cli.ts; remove migrationApplyCommand registration
- Delete commands/migration-apply.ts
- Rename runMigrationApply -> runMigrate in journey-test-helpers.ts
- Update all 20 journey test call sites (--ref -> --to where applicable)
- Update CLI package tests (tamper, invariants, json-shapes)
- Update mongo integration tests
- Update package.json exports and tsdown/vitest configs

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
When --to is provided, db update resolves the contract reference via
parseContractRef, loads the matching end-contract.json from the
migration graph, and uses it as the target contract instead of the
auto-resolved emitted contract. When --to is omitted, behavior is
unchanged.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Replace all references to `migration apply` with `migrate` in the
subsystem documentation. The command synopsis now shows
`prisma-next migrate --to <contract>` and the narrative text uses
the bare verb throughout.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Fix two test regressions from the verb rename:
- migration-invariants.test.ts: --ref -> --to for createMigrateCommand
- help.snapshot.test.ts: update db update snapshot for new --to flag

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The subprocess CLI invocation in harness.ts still used the old
`prisma-next migration apply` command. Update to `prisma-next migrate`.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Fix 9 user-visible strings (F2) and ~10 internal comments/URLs (F3)
that still told users to run the removed `prisma-next migration apply`.

User-visible (F2):
- migration-status.ts: 7 hint/summary/diagnostic strings now reference
  `prisma-next migrate` / `prisma-next migrate --to <ref>`
- migration-plan.ts: 2 "Next:" hints now reference `prisma-next migrate`

Internal (F3):
- migration-status.ts, command-helpers.ts, migration-plan.ts,
  migrations.ts: comments updated from migration-apply → migrate
- help.ts: URL map entry renamed from `migration apply` to `migrate`
- migration-cli.ts, contract-space-seed-phase.ts: stale comments updated

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
wmadden added 23 commits May 18, 2026 17:23
The previous shape of `executeMigrationShowCommand` called
`buildContractSpaceAggregate` (which enforces a layout-integrity
check that fires `PN-MIG-5001` when an extension is declared but its
migrations directory has not been materialised) BEFORE
`parseMigrationRef`. Any input — wrong-grammar OR a valid migration
directory name — was therefore gated by the aggregate layout check.
A user with a declared-but-unmigrated extension never reached the
wrong-grammar diagnostic that AC6 promises.

Reorder execution: resolve the app-space target through
`parseMigrationRef` (or path-form / latest-leaf) first, then build
the aggregate to enumerate extension spaces. The aggregate-loader
still runs on the no-target path (so extension-space enumeration
keeps its layout-integrity coverage), but a wrong-grammar input
short-circuits to the resolver diagnostic the user asked for.

Add a journey test (test/integration/test/cli-journeys/
migration-show-reachability.e2e.test.ts) that reproduces the
canonical demo state (extensionPacks: [pgvector] with no
migrations/pgvector/ dir) and asserts the resolver diagnostic
reaches the user.

TML-2546

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

F-2: per-migration `migration check <m>` used to run only the
hash-recomputation (PN-001) and file-existence (PN-002) checks. The
within-migration snapshot-consistency check (PN-005, comparing
metadata.to against end-contract.json.storageHash) was implemented
only on the graph-wide code path, so a corruption that the graph-wide
check correctly catches reported `ok: true` in per-migration mode —
a false negative on a documented integrity check.

Lift the check into a shared `checkSnapshotConsistency` helper called
from both branches. Same on-disk drift now produces the same failure
regardless of how the user invoked check.

F-8: the `where` field on check failures used three different shapes
across PN codes — absolute path for PN-001 from the loader catch
block (via MigrationToolsError.details.dir), short directory name
for PN-001/PN-003/PN-005 from the per-package loops, and a labelled
"ref \"name\"" for PN-004. Normalise to a cwd-relative path
consistently:

- PN-001 (HASH_MISMATCH): `migrations/<space>/<dir>/migration.json`
  (the hash being verified is stored there).
- PN-002 (MANIFEST_INCOMPLETE): the specific missing file path,
  e.g. `migrations/<space>/<dir>/migration.json` or `ops.json`.
- PN-003 (ORPHAN_MIGRATION): the migration directory.
- PN-004 (DANGLING_REF): the ref file `migrations/<space>/refs/<name>.json`.
- PN-005 (EDGE_MISMATCH): the migration directory (drift spans two
  files inside it).

Add a per-migration adversarial test that pins the F-2 fix —
parallels the graph-wide PN-005 test and asserts the per-migration
branch reports the same code for the same on-disk corruption.

The existing migration-check tests only assert `failures[].pnCode`,
not `where`, so the F-8 normalisation is observable from --json
output without breaking any existing assertion.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The root help output came up in QA as F-3: the top-level command
listing read as `contract, db, migration, migrate, ref, init`, which
puts `init` at the bottom even though it is the first verb a new
user runs, and lets `migrate` land between the `migration` namespace
and the `ref` namespace, breaking the subject-grouping rhythm.

The spec opens with an intended-surface diagram that lists the
surface in a specific reading order — verbs first (`init`,
`migrate`), then subject namespaces (`contract`, `db`, `migration`,
`ref`). That order is what introduces the CLI to a reader; the help
output should match.

Reorder by consolidating the `program.addCommand(...)` calls into a
single block at the end of the registration section, in the spec's
order. Each command's body still builds in its own paragraph; only
the addCommand sequence moves. No behaviour change beyond the
display order.

Note on the orchestrator round-prompt: the round task lists target
order as `db family, migration family, migrate, ref, then init`,
which contradicts the spec's diagram (and the QA finding that
flagged init-at-the-bottom as the problem). I matched the spec
because both the QA runner's observation and the spec's own
diagram agree on init-first; the round bullet appears to be a typo
sketch. Surfaced in the return report.

TML-2546

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

The QA round flagged `migrate --help`'s `--to` description as
listing four of the five forms — hash, prefix, ref name, migration
dir name — and missing `<dir>^` and the `./path` filesystem form.
The same trimmed wording lived on five other `<contract>`-accepting
sites: `db sign --contract`, `ref set` (positional), `migration plan
--from`, `db update --to`, and `migration status --to`. `migration
status --from` had no grammar mention at all.

Reproduce the full grammar across every help string, matching the
glossary's contract-reference table verbatim: "hash, prefix, ref
name, migration dir name, <dir>^, or ./path". `migration status
--from` now references the same grammar plus its purpose-specific
behaviour (offline path computation when supplied).

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The domain doc said hash prefixes accept 8+ chars; the glossary and
the implementation (HEX_PREFIX_PATTERN at packages/.../refs/types.ts)
say 6+. The QA round flagged the drift as F-6.

Implementation is canonical (changing it would surprise existing
scripts that pass 6- or 7-char prefixes). Update the domain doc's
contract-reference grammar table and the ambiguity-rule example to
match the implementation.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The output-format dispatch in `executeMigrationGraphCommand`'s action
handler checked `flags.json` before `options.dot`. `parseGlobalFlags`
auto-enables `flags.json` when stdout is non-TTY (per CLI Style
Guide § JSON Semantics), so a user running
`prisma-next migration graph --dot | dot -Tsvg > graph.svg` piped
JSON into GraphViz, which then errored. The bug shipped because no
test exercised `--dot` in non-TTY mode.

Reverse the precedence: explicit format flags (`--dot`) win over the
auto-JSON default. Add a journey test that pins the precedence with
both directions of assertion — `--dot` produces DOT, bare `migration
graph` in the same non-TTY mode still produces JSON. Also extend the
`runMigrationGraph` journey helper to accept the same `options`
shape (with `isTTY`) other helpers already accept, so the test can
opt into the non-TTY reproduction.

TML-2546

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

The QA round flagged the original recipe (F-5): editing
migration.json's `to` field invalidates the recomputed
`migrationHash`, which makes the package loader throw PN-001
(HASH_MISMATCH) BEFORE the PN-005 within-migration snapshot-
consistency check has a chance to fire. The recipe was always
wrong from PN-005's perspective and the script even anticipated
this in its own "Failure modes" list.

Switch the recipe to mutate `end-contract.json`'s
`storage.storageHash` instead. That keeps the manifest hash valid
and drives the drift specifically between `metadata.to` and the
recorded snapshot — exactly what PN-005 was designed to detect.

Also extend step 4 (per-migration check) with a note that it
verifies the F-2 fix in this round (per-migration mode used to be
a false-negative on PN-005). Update the Restore step to checkout
end-contract.json instead of migration.json.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
F-9 from the QA round: the pre-flight's "git status must show a
clean tree" check was too strict given the orchestrator's working
shape. Two items are typically uncommitted at handoff and confused
the QA runner mid-script:

- `M projects/migration-domain-model/plan.md` — the round's task
  list amendment.
- `M wip/unattended-decisions.md` — the orchestrator's decision
  log.

The runner judged "I'll proceed under the assumption these are
intentional" and was correct, but the script gave no guidance.
Document the two known items explicitly, instruct the runner to
treat their presence as clean-equivalent, and call out that any
OTHER uncommitted change is a finding worth surfacing before
scenarios start. Offer `git stash push` as the strictly-clean
alternative.

Renumber the pre-flight steps (added one) and split tooling-version
checks out from the git-status check for clarity.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The previous commit extended the `--to <contract>` description on
`db update` to list all five contract-reference forms (F-4). The
help.snapshot test pins the rendered help output, so the new
wording flows through into a snapshot delta. Update the snapshot
to match.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The M7 R3 fix moved the aggregate-loader call to after
parseMigrationRef, which restored wrong-grammar diagnostic
reachability. But valid migration references were still gated by
the aggregate loader. A user with a declared-but-unmigrated
extension hit PN-MIG-5001 even for a known-good migration
directory name — the verb was still effectively unreachable for
its primary purpose.

Restructure migration-show into two paths:

- Explicit target (positional argument): read appMigrationsDir
  directly, resolve through parseMigrationRef, render the single
  matched migration. No aggregate. No layout check. Mirrors the
  pattern used by migration list, migration graph, and migration
  check, which all read appMigrationsDir without ever building
  the aggregate.
- No target: build the aggregate so we can enumerate every loaded
  extension space and render the latest migration per space. The
  layout-integrity check is appropriate at this entry point
  because the verb is asking the framework to report on every
  declared space.

Functionally: migration show <dir> in canonical demo state now
returns the migration details; the no-arg form still flags layout
violations via the aggregate-loader path.

Extend the journey test with a happy-path assertion against the
same unmigrated-extensions fixture. The wrong-grammar assertion
stays. Both pin distinct properties of the verb on the same
fixture state.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The QA round flagged two patterns in tests added during M7 R3:

- `AC6` in the migration-show-reachability JSDoc.
- `F-N regression` prefixes (F-1, F-2, F-7) in JSDoc and inline
  comments across the three new tests.

Both pattern classes are durable-file-incompatible per the
workspace doc-maintenance rule: AC IDs and F-numbers come from the
project's spec / QA artefacts under `projects/migration-domain-
model/`, which is a transient directory that will be deleted under
TML-2553. Tests are durable files; references to transient IDs go
stale on deletion.

Rewrite the JSDoc on each test to state the property being pinned
in its own words ("wrong-grammar diagnostics on `migration show`
must reach the user even in unmigrated-extensions state", etc.).
Drop the `F-N regression` inline comments — the body already
explains the bug context the comment was prefixed with, no
information is lost.

The migration-show-reachability test's JSDoc gets the AC6 fix as
part of the broader rewrite that accompanies the new happy-path
assertion (already in the previous commit, `4fde15f75`).

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
Three leaks caught by the M7 R4 reviewer that the R3/R4 sweeps
missed:

- migration-show.ts:292 — "spec FR3" attribution (introduced by my
  own R4 JSDoc rewrite). Rewritten to describe the constraint
  itself ("contradicts what an offline read-only verb should
  require") without naming a spec section.
- migration-show-reachability.e2e.test.ts:143 — same pattern, same
  fix: replace "the spec FR3 offline-by-design framing" with a
  property-statement that stands on its own.
- migration-show-reachability.e2e.test.ts:2 — JSDoc opener referred
  to "documented as offline and read-only in the spec"; rephrased
  to "an offline read-only verb" (the property without the spec
  attribution).
- migration-graph-dot.e2e.test.ts:44 — "Reproduce the F-7 scenario"
  reference that the R3 sweep missed. Rephrased to "Reproduce the
  non-TTY DOT regression scenario" plus a concrete description of
  what the regression looks like to a user (pipe-style invocation
  produces JSON, pipe-receiver errors).

While reworking the F-7 reference, also dropped the stale
duplicate runMigrationGraph call that survived from R3's first
test iteration — it ran the same command with default isTTY=true
just before the real reproduction with isTTY=false. The duplicate
wasted time and the leftover comment was misleading.

Self-check gate (the rg pattern from .cursor/rules/doc-maintenance)
returns zero hits on all three files after the rewrites.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
The F8 fix moved aggregate-loader enumeration into the no-target
branch of `migration show`. That's the legitimate place for the
PN-MIG-5001 layout-integrity check to fire: when the user asks for
every loaded space's latest migration, missing extension-space
directories are a real signal worth surfacing. But nothing pinned
the property. A future simplification — removing the aggregate
build, or downgrading the check from error to warn — could let the
verb silently miss the unmigrated extension.

Add a third assertion to migration-show-reachability against the
same `setupUnmigratedExtensionsState` fixture: bare
`prisma-next migration show --json` exits non-zero with
`code: "PN-MIG-5001"` and a `why` that names the unmigrated
extension (`pgvector`).

The test file now pins three distinct properties of the verb in
unmigrated-extensions state:

1. Wrong-grammar input → resolver diagnostic reaches the user.
2. Valid app-space target → migration details returned.
3. No-target → aggregate-loader layout-integrity check fires.

Self-check gate (the rg pattern from the doc-maintenance rule)
returns zero hits on the file after the addition.

TML-2546

Signed-off-by: Will Madden <madden@prisma.io>
…5-18)

Second QA pass after M7 R3-R5 folded in all 9 system findings + 5
reviewer-derivative findings from the first pass. Verdict: ✅
Pass-with-follow-ups (1 📝 Follow-up about pre-flight fixture residue).

Every prior-run finding (F-1 through F-9) verified holding:
- F-1: migration show now reachable for wrong-grammar AND valid-target
  inputs in canonical demo state. End-to-end behavior verified.
- F-2: per-migration migration check <m> now detects PN-005 via the
  shared checkSnapshotConsistency helper. End-to-end verified.
- F-3 through F-9: help reorder, help-text completeness across 6
  commands, hash-prefix length docs aligned, --dot precedence fix,
  where field normalisation across 5 PN codes, script corruption recipe
  + pre-flight clarifications all confirmed live.

Project is observably ready for the orchestrator's push + CI gate.

Signed-off-by: Will Madden <madden@prisma.io>
The M7 plan grew several rounds beyond R1 in response to user direction
and post-round signal:

- R2: preserve the project's modeling work (domain.md + inspirations)
  in forward-compatible docs/design/ paths; not a wholesale framework
  adoption.
- R3: fold all 9 QA-pass-1 findings (2 ⚠️ Highs + 7 📝 Follow-ups)
  into a single implementation round per the small-PR policy rather
  than ticketing them.
- R4: close R3 residuals (F-1 happy-path slice, transient-ID leaks
  introduced/missed during R3's sweep).
- R5: close R4 residuals (more transient-ID leaks introduced by R4's
  own rewrites) and pin the no-target layout-integrity check as a
  regression guard. Introduces a pre-commit self-check protocol.

Captured each round's scope as it was dispatched so a future reader
sees the actual execution narrative, not only the original plan.

Signed-off-by: Will Madden <madden@prisma.io>
The reference resolvers used post-hoc non-null assertions (`matches[0]!`,
`candidates[0]!`, `migMatches[0]!`) after length checks. Biome's
noNonNullAssertion fires on these, and CI runs biome with
--error-on-warnings.

Switched to destructure-and-narrow so the property access is
TypeScript-clean without an assertion: pull the first element out, then
guard with `length === N && first !== undefined`. The undefined guard is
logically redundant given the length check but satisfies the lint rule
without suppressing it.

No behavior change; 486 unit tests pass.

Signed-off-by: Will Madden <madden@prisma.io>
The new migration-check command is exercised end-to-end through
adversarial fixture journey tests covering all five PN-MIG-CHECK-*
codes, but the CLI package's unit suite doesn't import it directly so
the per-package coverage report sees 0% on migration-check.ts.

Mirrors the existing M9-era warningOnly entries (TML-2521 family):
90-day expiry, points the recovery work at TML-2552 alongside the
other residual internal renames.

Signed-off-by: Will Madden <madden@prisma.io>
The field was introduced to forward-compat the canonicalization algorithm, but canonicalization-rule changes are always breaking — the new ruleset produces different bytes for the same logical contract, so every consumer must re-emit anyway. The version stamp gave us nothing actionable that re-emit-on-break does not already give us, and it imposed a confusing dual surface on the marker (a real hash plus a co-stored ruleset version).

Drops the term from the migration domain model (both the durable `docs/design/10-domains/migration/README.md` and the project-local `domain.md` mirror), and rewrites ADR 010 to describe canonicalization-rule changes as breaking-by-design rather than versioned, removing the matching `prisma-next recanonicalize` tool the version stamp was meant to drive.

Code-side retirement (contract type, SQL + Mongo marker, runner/verify paths, dependent ADRs 042/100/029/025/096) is tracked separately under TML-2559.

Refs: TML-2546, TML-2559
Signed-off-by: Will Madden <madden@prisma.io>
The modelling work resolved on `migration plan --advance <ref>` as the
canonical authoring path: producing the migration package and advancing
the named ref are one act, committed in one PR (the "freeze + promise"
verb). `ref set` is reserved as the rarely-used direct-write escape
hatch. The restructure project shipped the rest of the modelled surface
but did not implement `--advance` — `migration-plan.ts` exposes
`--config`, `--name`, `--from` only.

Adds a "Follow-up tasks" section to the project spec naming this gap
explicitly, pointing at TML-2560 (the implementation ticket against
`[PN] May: Migrations`) and recording the scope when implemented (flag,
resolver wiring, ref-write integration, refusal semantics, journey-test
coverage, glossary cross-reference) so the bridge between the modelling
docs and the shipped CLI is auditable rather than implicit.

Refs: TML-2546, TML-2560
Signed-off-by: Will Madden <madden@prisma.io>
Captures the workflows the migration verb taxonomy was designed around,
grouped by user posture (authoring, operating, reading, adopting,
recovering). Each journey names the persona, the question being asked,
the verb sequence, and the e2e test that exercises it end-to-end.

The journeys consolidate two streams of source material: the load-bearing
journeys identified during the modelling discussion (bootstrap, dev inner
loop, plan-and-promise, status landing, migrate-to-ref, CI gating, CD
execution) and the journey-shaped e2e tests under
`test/integration/test/cli-journeys/` (brownfield adoption, production
adoption, rollback, divergence reconciliation). Pathological / single-
feature regression scenarios (drift edge cases, resolver internals,
single-verb integration probes) are deliberately excluded — they live in
the test suite but are not load-bearing as user stories.

Cross-link added from the domain README so the catalog is discoverable
from the canonical entry point. Adoption-ergonomics concern (brownfield
adoption is currently 5 verbs; target is 1–2) is flagged inline with a
pointer to TML-2561 for the follow-up work.

Refs: TML-2546, TML-2561
Signed-off-by: Will Madden <madden@prisma.io>
- ADR 208: update section heading --ref -> --to (consistent with body)
- Migration System.md: fix broken fragment links to #contract-references-and-migration-references
- migration/README.md: add language tag to unlabeled fenced code block
- migration/README.md: resolve "migration" definition ambiguity — consistently means on-disk artifact
- ref.ts: update help text from "contract hash" to "contract reference"
- journey-tests/02f-merge-preview.md: fix success criteria --ref -> --to
- prisma-next-quickstart/SKILL.md: fix "migration plan + apply" -> "migration plan + migrate"
- prisma-next-migration-review/SKILL.md: fix CI snippet --ref -> --to
- db-sign-contract-arg.e2e.test.ts: remove inaccurate error-path claim from docblock
- .husky/pre-commit: pass --no-stash to work around symlink issue in worktree

Signed-off-by: Will Madden <madden@prisma.io>
db-update: fail fast when --to ref resolves but no matching bundle exists,
  instead of silently applying the default emitted contract
migration-check: return a CheckFailure when end-contract.json is unparseable
  (JSON.parse errors were previously swallowed)
migration-graph: use null instead of EMPTY_CONTRACT_HASH when contract read
  fails, so consumers can distinguish "unknown" from "at root"
migration-log: return a structured error when findPath returns null, rather than
  collapsing an unreachable marker to an empty applied list
migration-plan: fail fast when --from resolves to a hash with no on-disk
  predecessor bundle, preventing fromContract from staying null for non-root hashes
migration-status: clear allMarkers when --from offline override is active, so
  live DB markers cannot contaminate offline results; also guard activeRefName
  before calling summarizeRefDistance to prevent "ref undefined" summaries
removed-verb-redirects.test.ts: replace __dirname with import.meta.url (ESM)

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

- migration/README.md: remove non-existent commands (migration compile,
  migration preflight, contract show, contract diff) from command inventory
  and safety class tables
- migration/README.md: add text language tag to diagram code blocks
- migration/user-journeys.md: fix npm init -> pnpm init
- migration/user-journeys.md: add bash language tag to all unlabeled command
  code blocks

Signed-off-by: Will Madden <madden@prisma.io>
@wmadden wmadden force-pushed the tml-2546-review-migration-cli-commands-and-vocabulary branch from fdfa6fd to a1469b3 Compare May 18, 2026 15:23
@wmadden wmadden merged commit b395397 into main May 18, 2026
8 of 9 checks passed
@wmadden wmadden deleted the tml-2546-review-migration-cli-commands-and-vocabulary branch May 18, 2026 15:24
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.

1 participant