From 3cdd07d18b8f8d434ac820a7772313b1e2c3d916 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 14:37:10 +0200 Subject: [PATCH 01/68] docs: add the Prisma ORM 8 docs audit and restructure proposal Personas, reader journeys, the mental model, the proposed information architecture, the change list, the naming rule, the corrections slice plan, two ORM briefs, and the page-by-page audit findings behind #8236, #8237, and #8238. Shared for discussion; not site content. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 17 ++ docs/orm-docs-audit/audit/AREAS.md | 24 ++ docs/orm-docs-audit/audit/INSTRUCTIONS.md | 74 +++++++ docs/orm-docs-audit/audit/builders.md | 70 ++++++ docs/orm-docs-audit/audit/contract.md | 60 +++++ docs/orm-docs-audit/audit/extras.md | 112 ++++++++++ docs/orm-docs-audit/audit/gaps.md | 66 ++++++ docs/orm-docs-audit/audit/migrations-cli.md | 66 ++++++ docs/orm-docs-audit/audit/orm-client.md | 63 ++++++ docs/orm-docs-audit/audit/start-guides.md | 60 +++++ .../brief-db-ref-on-adoption.md | 53 +++++ docs/orm-docs-audit/brief-skills-opt-out.md | 47 ++++ docs/orm-docs-audit/changes.md | 205 ++++++++++++++++++ docs/orm-docs-audit/ia.md | 178 +++++++++++++++ docs/orm-docs-audit/journeys.md | 147 +++++++++++++ docs/orm-docs-audit/mental-model.md | 112 ++++++++++ docs/orm-docs-audit/naming.md | 37 ++++ docs/orm-docs-audit/personas.md | 33 +++ docs/orm-docs-audit/slice-corrections.md | 83 +++++++ 19 files changed, 1507 insertions(+) create mode 100644 docs/orm-docs-audit/README.md create mode 100644 docs/orm-docs-audit/audit/AREAS.md create mode 100644 docs/orm-docs-audit/audit/INSTRUCTIONS.md create mode 100644 docs/orm-docs-audit/audit/builders.md create mode 100644 docs/orm-docs-audit/audit/contract.md create mode 100644 docs/orm-docs-audit/audit/extras.md create mode 100644 docs/orm-docs-audit/audit/gaps.md create mode 100644 docs/orm-docs-audit/audit/migrations-cli.md create mode 100644 docs/orm-docs-audit/audit/orm-client.md create mode 100644 docs/orm-docs-audit/audit/start-guides.md create mode 100644 docs/orm-docs-audit/brief-db-ref-on-adoption.md create mode 100644 docs/orm-docs-audit/brief-skills-opt-out.md create mode 100644 docs/orm-docs-audit/changes.md create mode 100644 docs/orm-docs-audit/ia.md create mode 100644 docs/orm-docs-audit/journeys.md create mode 100644 docs/orm-docs-audit/mental-model.md create mode 100644 docs/orm-docs-audit/naming.md create mode 100644 docs/orm-docs-audit/personas.md create mode 100644 docs/orm-docs-audit/slice-corrections.md diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md new file mode 100644 index 00000000000..792005a9d2e --- /dev/null +++ b/docs/orm-docs-audit/README.md @@ -0,0 +1,17 @@ +# Prisma ORM 8 docs audit + +Working documents behind the Prisma ORM 8 docs corrections (prisma/web #8236, #8237, #8238) and the proposed restructure. Written September 2026 against `@prisma/orm-postgres@8.0.0-rc.9`; source paths refer to the prisma/orm monorepo at that tag (`packages/`, `docs/releases/`, `examples/`, `skills/prisma-8/`) and to prisma/create-prisma. Site paths are relative to `apps/docs/content/docs/`. + +Read in this order: + +1. `personas.md` — who reads the ORM docs: the Newcomer, the Upgrader, the Builder, the Agent. +2. `journeys.md` — ten jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. +3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. +4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. +5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B, shipped), new pages (C), ORM changes (D). Leads with the suggested order. +6. `naming.md` — the "Prisma ORM" naming rule. +7. `slice-corrections.md` — how the shipped corrections were sliced, and the decisions taken. +8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md` — two ORM changes handed to other agents. +9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. + +Prose is a draft throughout; the structure and the cited facts are what has been verified. diff --git a/docs/orm-docs-audit/audit/AREAS.md b/docs/orm-docs-audit/audit/AREAS.md new file mode 100644 index 00000000000..361243012b6 --- /dev/null +++ b/docs/orm-docs-audit/audit/AREAS.md @@ -0,0 +1,24 @@ +# Audit areas and page lists + +Site paths are relative to `apps/docs/content/docs/`. + +## orm-client +orm/index.mdx, orm/core-concepts.mdx, orm/fundamentals/{reading-data,writing-data,relations-and-joins,advanced-queries,transactions}.mdx, orm/reference/{index,orm-client,transactions-and-runtime,error-reference}.mdx + +## builders +orm/reference/{sql-query-builder,pipeline-builder,raw-queries}.mdx, orm/extensions/using-extensions.mdx, orm/middleware/{how-middleware-works,authoring-custom-middleware,built-in-lints,built-in-budgets,built-in-cache}.mdx + +## contract +orm/contract-authoring/{the-data-contract,the-contract-artifact,psl-syntax,typescript-schema-builder,capabilities}.mdx, orm/data-modeling/{index,relational-databases,mongodb}.mdx, cli/{contract-emit,contract-infer}.mdx + +## migrations-cli +orm/migrations/*.mdx (6), cli/{index,global-flags,configuration,error-reference,init,orm-init,skills,dev,git}.mdx, cli/db-{init,update,migrate,sign,verify,schema}.mdx, cli/migration-{new,plan,ref,show,status}.mdx. Platform commands (auth, branch, bucket, deploy, feedback, postgres, project, service, telemetry) out of scope. + +## start-guides +(index)/{index,getting-started}.mdx, (index)/prisma-orm/{index,create-prisma}.mdx, (index)/prisma-orm/quickstart/{postgresql,mongodb}.mdx, (index)/prisma-orm/add-to-existing-project/{postgresql,mongodb}.mdx, (index)/prisma-postgres/quickstart/prisma-orm.mdx, guides/index.mdx, guides/upgrade-prisma-orm/{postgresql,mongodb}.mdx, guides/switch-to-prisma-orm/*.mdx (3), guides/database/*.mdx (3) + +## gaps +Part 1: guides/frameworks/*.mdx (10), guides/deployment/*.mdx (6), guides/runtimes/*.mdx (2), guides/integrations/{github-actions,vercel-deployment,ai-sdk}.mdx. Part 2: reverse audit of skills/prisma-8/ and docs/glossary.md and the public export maps against the whole ORM 8 site. + +## extras +(index)/full-stack-tutorial.mdx, ai/tools/skills.mdx, cli/telemetry.mdx, plus the targeted gap questions from the first session's gaps brief (RLS, expression indexes, Postgres extensions, JSON filtering, Decimal, SQLite, Vite plugin, @@control, soft delete, read replicas, await using, streaming, native provider, docs/reference/*, extension packages). diff --git a/docs/orm-docs-audit/audit/INSTRUCTIONS.md b/docs/orm-docs-audit/audit/INSTRUCTIONS.md new file mode 100644 index 00000000000..fa0b1f3f928 --- /dev/null +++ b/docs/orm-docs-audit/audit/INSTRUCTIONS.md @@ -0,0 +1,74 @@ +# Audit instructions (shared by every area agent) + +You are auditing the Prisma ORM docs site against the Prisma 8 monorepo at rc.9. The goal is a list of things on the site that are wrong, out of date, or missing, with evidence. + +## Where things are + +Work only inside the docs worktree. Do not edit any file except your own output file. Put scratch files in `wip/docs-audit/audit/scratch-/`. + +- Docs site source: `apps/docs/content/docs/` (this worktree is the `prisma/web` repo). Cite site paths relative to that directory, for example `orm/fundamentals/reading-data.mdx:42`. Prisma ORM 8 pages are under `orm/` (not `orm/v6`, `orm/v7`), `(index)/prisma-orm/`, `(index)/getting-started.mdx`, `cli/` (not `cli/v7`), and the ORM parts of `guides/`. +- The monorepo (the truth) is checked out at rc.9 under `wip/prisma-src/`. Inside it: `packages/` for source, `docs/releases/v8.0.0-rc.*.md` and `docs/releases/v0.1[5-7].0.md` for what changed and when, `docs/glossary.md` for terms, `skills/prisma-8/` for the shipped agent skill (`SKILL.md` plus `references/*.md`). The skill is well maintained and a good second source, but it uses `@internal/*` import paths that users must read as `@prisma/orm-postgres/*`; do not report that, it is known. +- The public package: `packages/9-public/@prisma/orm-postgres/package.json` lists the real export paths users import. +- create-prisma source (what the scaffold generates): `wip/create-prisma-src/`. +- Worked examples that compile against rc.9: `wip/prisma-src/examples/`. + +## How to work + +- Read every page in your area in full. Do not skim headings. +- For every API name, method, flag, command, config key, file path, import path, type name, and error code on a page, check it exists in the source with that name and shape. Grep `packages/` and `skills/prisma-8/references/`. Check `docs/releases/` for renames. +- For every code sample, ask: would this typecheck and run on rc.9? You do not need to run it, but you must be able to point at the source that says yes or no. +- Verify before reporting. A finding must cite a file in the monorepo or a release note. If you cannot find evidence either way, report it under "Unverified" with what you looked for. +- Also look the other way: what does the source or skill support in your area that the site never mentions? Report those under "Missing". +- The product is called "Prisma ORM"; do not report pages that say "Prisma 8", that is a known site-wide naming issue. +- Do not report the items already known (list below). Do not report prose style, tone, or the "written for AI" complaint. Do not report `@internal/*` in the skill. + +## Already known, do not re-report + +- `.take()`/`.skip()` should be `.limit()`/`.offset()` (renamed rc.7). +- `createCount`/`updateCount`/`deleteCount` should be `createAndCount` etc. (renamed 0.17). +- The existing-project PostgreSQL page uses `db.orm.User` and `db.sql.user` instead of `db.orm.public.User` / `db.sql.public.user`. +- `@db.*` attributes were removed in 0.17; `psl-syntax.mdx` still shows `String @db.Uuid`. +- `orm/index.mdx` says SQLite is planned; it ships as `@prisma/orm-sqlite`. +- The upgrade guide is pinned to rc.6 / rc.4. +- `db sign` does not set the `db` ref, so `migration plan` after adoption plans from empty. +- No page covers: a Prisma 7 to 8 API mapping, model/result types (`Models`, `Shape<>`, in open PRs), `createMany`/`skipDuplicates`, `firstOrThrow`, atomic increment, case-insensitive filters, editor setup, RLS outside Supabase, functional indexes, pg_trgm, money/Decimal, the skills opt-out on getting-started pages, the npm `latest` tag / release status. +- `DATABASE_URL` from `.env` vs the environment is inconsistent across getting-started pages; `db.connect()` vs `db.runtime()` is used interchangeably; `db.ts` is imported but never shown on getting-started pages; Node version claims differ. + +## Output + +Write your findings to `wip/docs-audit/audit/.md` (the area name is given in your prompt). Use exactly this structure. Markdown, no hard-wrapped lines, plain English, no invented jargon. + +``` +# Audit: + +Pages read: + +## Breaks copy-paste +Things a user copies that fail: wrong name, removed API, wrong flag, wrong path, wrong import. + +- `:` — — — evidence: `` + +## Misleading +True-ish statements that lead the user wrong: stale defaults, changed behaviour, wrong claims about what is supported. + +- (same format) + +## Missing +Things the source or skill supports in this area that the site never mentions, or that a user in this area would need and cannot find. + +- — evidence it exists: `` — where on the site it belongs + +## Unverified +Things that looked wrong but you could not confirm either way. + +- `:` — — + +## Skill vs site +Places where the shipped skill (`skills/prisma-8/references/`) and the site disagree, beyond the items above. Say which one matches the source. + +- (same format) +``` + +Keep each bullet to the facts. Line numbers are from the site file. When one defect repeats across many lines, give the count and the first line, not every line. + +When finished, return a two-paragraph summary: how many findings in each section, and the three most serious. diff --git a/docs/orm-docs-audit/audit/builders.md b/docs/orm-docs-audit/audit/builders.md new file mode 100644 index 00000000000..f5f76a774e9 --- /dev/null +++ b/docs/orm-docs-audit/audit/builders.md @@ -0,0 +1,70 @@ +# Audit: builders + +Pages read: `orm/reference/sql-query-builder.mdx`, `orm/reference/pipeline-builder.mdx`, `orm/reference/raw-queries.mdx`, `orm/extensions/using-extensions.mdx`, `orm/middleware/how-middleware-works.mdx`, `orm/middleware/authoring-custom-middleware.mdx`, `orm/middleware/built-in-lints.mdx`, `orm/middleware/built-in-budgets.mdx`, `orm/middleware/built-in-cache.mdx` + +## Breaks copy-paste + +- `orm/reference/sql-query-builder.mdx:147` (and about 30 more on this page: 218, 230, 244, 278, 308, 330, 375, 405, 415, 425, 444, 480, 512, 545, 620, 632, 667, 689, 690, 711, 788, 821, 833, 857, 897, 947, 956, 981, 1003) — `const rows = await runtime.execute(plan)` reads rows from `execute()` — since rc.2 `runtime.execute(plan)` resolves `Promise` (`{ affectedRows }`); rows come from `runtime.query(plan)`, which returns `AsyncIterableResult`. Every row-returning example on the page is wrong at the type level and at runtime — evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `docs/releases/v8.0.0-rc.2.md` ("Runtime row queries and non-returning writes are separate calls"), `examples/prisma-8-demo/src/queries/get-users.ts:5`. +- `orm/reference/sql-query-builder.mdx:977-981` — "Run a plan with `runtime.execute(plan)` … It resolves to an array of rows (`Row[]`)" — `execute()` is the non-returning write call; `query()` is the row call, and it resolves to `AsyncIterableResult` (awaitable to an array, or `for await`) — evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`. +- `orm/reference/raw-queries.mdx:42` (also 57, 74, 90, 112, 126) — `const rows = await runtime.execute(plan)` — same defect; must be `runtime.query(plan)` — evidence: as above, plus `examples/prisma-8-demo/src/queries/raw-sql-demo.ts:36`. +- `orm/extensions/using-extensions.mdx:86` — `await db.runtime().execute(plan)` for a similarity search — the demo this is copied from uses `db.runtime().query(plan)` — evidence: `examples/prisma-8-demo/src/queries/similarity-search.ts:14`. +- `orm/middleware/built-in-cache.mdx:49` — `const users = await db.runtime().execute(plan)` — must be `.query(plan)`; the cache middleware only acts on the query lifecycle (`interceptQuery`), so a cached read through `execute()` would neither return rows nor be cached — evidence: `examples/prisma-8-demo/src/queries/get-users-cached.ts:26`, `packages/3-extensions/middleware-cache/src/cache-middleware.ts:238-243`. +- `orm/reference/pipeline-builder.mdx:117` (and about 50 more on this page, every `db.execute(plan)`), `orm/reference/pipeline-builder.mdx:122-126` — "`db.execute(plan)` is the client-level executor" — the Mongo client has no `execute` method; its surface is `orm`, `query`, `raw`, `contract`, `enums`, `context`, `connect()`, `runtime()`, `close()`. Plans run through `(await db.runtime()).query(plan)`; note `runtime()` returns a Promise on Mongo. The rc.2 note says explicitly "the row-executing `db.execute` facade method is gone" — evidence: `packages/3-extensions/mongo/src/runtime/mongo.ts:28-39`, `docs/releases/v8.0.0-rc.2.md`, `examples/mongo-demo/test/query-builder-writes.test.ts:57`. +- `orm/reference/pipeline-builder.mdx:126` — "`runtime.execute(plan)` is the equivalent lower-level call" — on Mongo `runtime.execute()` also returns `Promise`; the row call is `runtime.query()` — evidence: `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-99`. +- `orm/reference/raw-queries.mdx:146-147` (and every `db.execute(...)` in the MongoDB section: 167, 181, 191, 208, 221, 231, 235, 257-259, 271, 283) — `db.execute(plan)` — does not exist; see above. Write plans (`insertOne`, `deleteMany`, `findOneAndUpdate`) also run through `runtime.query(plan)` and yield their result envelope as the single row — evidence: `examples/mongo-demo/test/query-builder-writes.test.ts:50-60, 84-87`. +- `orm/reference/raw-queries.mdx:121` — ``db.raw`now()`.returns('pg/timestamptz@1')`` — `db.raw` is a lane object with one key; the tag is ``db.raw.sql`...` ``. Calling `db.raw` as a template tag throws — evidence: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:153-166` (`RawLane = { readonly sql: RawTagFor }`), `packages/3-extensions/postgres/src/runtime/postgres.ts:63` (`readonly raw: RawLane`), `examples/prisma-8-demo/src/queries/raw-query-demo.ts:35`. +- `orm/middleware/how-middleware-works.mdx:39-73`, `orm/middleware/authoring-custom-middleware.mdx:152-160` — "There are five hooks": `beforeCompile`, `beforeExecute`, `intercept`, `onRow`, `afterExecute` — there is no `intercept` hook. Since rc.2 the lifecycle is split by operation: row queries run `beforeCompile → beforeQuery → interceptQuery → onRow → afterQuery`; non-returning writes run `beforeCompile → beforeExecute → interceptExecute → afterExecute`. A middleware object with an `intercept` key is an excess-property type error and is never called — evidence: `packages/2-sql/5-runtime/src/middleware/sql-middleware.ts:28-128`, `docs/releases/v8.0.0-rc.2.md` ("Runtime middleware splits the same way, into `beforeQuery` / `interceptQuery` / `afterQuery` and `beforeExecute` / `interceptExecute` / `afterExecute` … There is no operation discriminator, compatibility alias, or generic fallback hook"). +- `orm/middleware/authoring-custom-middleware.mdx:31-46, 107-129` — the query logger implements only `afterExecute` and reads `result.rowCount` — `afterExecute` fires only for `runtime.execute()` (non-returning writes). Every ORM read, every ORM `create` (which returns rows), and every SQL-builder `query()` goes through `afterQuery`, so the logger as written never logs the two queries the page shows at lines 95-99. Also `AfterExecuteResult` has no `rowCount` field (it carries `stats.affectedRows`), so line 41 is a type error. The shipped equivalent uses `afterQuery` — evidence: `packages/1-framework/1-core/framework-components/src/execution/runtime-middleware.ts:114-126` (`AfterQueryResult.rowCount` vs `AfterExecuteResult.stats`), `packages/2-sql/5-runtime/src/middleware/sql-middleware.ts:88-128`, `examples/prisma-8-demo/src/prisma/slow-query-warning.ts:24`. +- `orm/middleware/authoring-custom-middleware.mdx:56-58, 157`, `orm/middleware/how-middleware-works.mdx:53-61` — `beforeExecute(plan)` as the place to validate or block a query — `beforeExecute` runs only on the execute (non-returning write) path. To block reads a middleware needs `beforeQuery`; the built-ins register the same function under both names — evidence: `packages/2-sql/5-runtime/src/middleware/lints.ts:176-181` (`beforeQuery: beforeOperation, beforeExecute: beforeOperation`), `packages/2-sql/5-runtime/src/middleware/budgets.ts:118-137`. +- `orm/middleware/built-in-lints.mdx:68` — "The options type also accepts `unindexedPredicate`" — `LintsOptions.severities` has exactly five keys (`selectStar`, `noLimit`, `deleteWithoutWhere`, `updateWithoutWhere`, `readOnlyMutation`); `unindexedPredicate` is an excess-property type error — evidence: `packages/2-sql/5-runtime/src/middleware/lints.ts:13-23`. + +## Misleading + +- `orm/reference/raw-queries.mdx:19` ("There is no way to run a bare raw SQL string on its own"), `orm/reference/raw-queries.mdx:130` ("`db.raw` is not a way to execute a standalone raw SQL statement") — whole-query raw SQL exists since rc.2: ``db.raw.sql`SELECT ...`.returnsRow({ col: 'pg/text@1', ... }).build()`` produces a plan for `runtime.query()`, and ``db.raw.sql`UPDATE ...`.affectedCount().build()`` produces one for `runtime.execute()`. Row-returning raw queries interpolate into other raw templates as subqueries and CTEs — evidence: `docs/releases/v8.0.0-rc.2.md` ("Whole-query raw SQL replaces the classic `$queryRaw` / `$executeRaw` use case"), `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:120-150`, `examples/prisma-8-demo/src/queries/raw-query-demo.ts`. +- `orm/reference/raw-queries.mdx:95`, `orm/reference/sql-query-builder.mdx:925` — "Bare-scalar interpolation is currently broken … the codec inferer emits unversioned codec ids (`pg/int4`)" — the Postgres raw codec inferer emits versioned ids (`pg/int4@1`, `pg/int8number@1`, `pg/float8@1`, `pg/int8@1`, `pg/text@1`, `pg/bool@1`, `pg/bytea@1`); the source comment says "The ids are versioned because that is how the codec registry keys them" — evidence: `packages/3-targets/6-adapters/postgres/src/core/adapter.ts:112-140`. +- `orm/reference/sql-query-builder.mdx:588-590, 621, 633, 668, 691-692` — "`COUNT()` … `SUM()` / `AVG()` over an integer column decode as JavaScript strings … Call `Number(...)`" — since rc.1 aggregates in both the ORM and the SQL builder resolve through the contract's `AggregateTypes`, and since rc.2 `count()`, integer `sum()`, and integer `avg()` return `number` (throwing `RUNTIME.DECODE_FAILED` outside the safe range); lossless `countBigInt()`, `sumBigInt()`, `avgDecimal()` sit beside them. The string-decoding advice describes pre-rc.1 behaviour — evidence: `docs/releases/v8.0.0-rc.1.md` ("`contract.d.ts` gains an `AggregateTypes` block that both the ORM and the SQL builder resolve result types from"), `docs/releases/v8.0.0-rc.2.md` ("The default aggregates are JavaScript numbers again"), `packages/2-sql/4-lanes/sql-builder/src/expression.ts:145-200`, `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:146-192`. +- `orm/middleware/built-in-budgets.mdx:46, 48` — "`severities.latency` … not read by the middleware in v0.14; latency behavior follows the runtime mode" — it is read: default is `'warn'`, and a latency overrun blocks when `severities.latency === 'error'` or the runtime is in strict mode — evidence: `packages/2-sql/5-runtime/src/middleware/budgets.ts:97, 113-125`. +- `orm/middleware/built-in-budgets.mdx:45, 48, 54, 74`, `orm/middleware/authoring-custom-middleware.mdx:203` — repeated references to "permissive mode" as a reachable state — the `postgres(...)` client never forwards a `mode`, so a Postgres runtime is always `'strict'` (`mode ?? 'strict'`) and every "warn in permissive mode" path is unreachable from the public client. Only `mongo(...)` accepts `mode` — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:86-94, 276-282` (options and `PostgresRuntimeImpl` construction pass only `verifyMarker` and `middleware`), `packages/2-sql/5-runtime/src/sql-runtime.ts:187`, `packages/3-extensions/mongo/src/runtime/mongo.ts:44`. +- `orm/middleware/built-in-cache.mdx:32, 79` — "`beforeExecute` hooks still run before a cache hit … `afterExecute` still fires" — the cache implements `interceptQuery`, `onRow`, `afterQuery`; the hooks that run around a hit are `beforeQuery` and `afterQuery` — evidence: `packages/3-extensions/middleware-cache/src/cache-middleware.ts:238-243`, `examples/prisma-8-demo/src/prisma/db.ts:16-22`. +- `orm/middleware/how-middleware-works.mdx:65, 73, 78`, `orm/middleware/authoring-custom-middleware.mdx:158, 192` — "Return `{ rows }` from `intercept`" and "`afterExecute` receives `result.rowCount`" — `interceptQuery` returns `{ rows }`, `interceptExecute` returns `{ stats }`; `afterQuery` carries `rowCount`/`completed`/`source`/`latencyMs`, `afterExecute` carries `stats.affectedRows`/`completed`/`source`/`latencyMs` — evidence: `packages/1-framework/1-core/framework-components/src/execution/runtime-middleware.ts:93-136`. +- `orm/middleware/built-in-lints.mdx:72-77` — "Raw SQL … `lints` falls back to text heuristics for raw plans … Control the fallback with `fallbackWhenAstMissing`" — a whole-query raw plan from `db.raw.sql` has an AST of kind `'raw-query'`; for it the structural rules are skipped and the text heuristics always run, regardless of `fallbackWhenAstMissing`. That option only matters when `plan.ast` is absent entirely — evidence: `packages/2-sql/5-runtime/src/middleware/lints.ts:100-104, 155-168`. +- `orm/reference/sql-query-builder.mdx:14` — "PostgreSQL is supported today" for the SQL builder — SQLite ships as a public package with its own adapter (including a raw codec inferer) — evidence: `packages/9-public/@prisma/orm-sqlite/package.json`, `packages/3-targets/6-adapters/sqlite/src/core/adapter.ts`. +- `orm/reference/pipeline-builder.mdx:96` — "Passing an unknown root throws synchronously: `Error: Unknown root …`. This is an `Error`, not a `TypeError`" — it is a structured ORM error with code `ORM.MODEL_UNKNOWN`; users should match on the code — evidence: `packages/2-mongo-family/5-query-builders/query-builder/src/state-classes.ts:646`. +- `orm/reference/sql-query-builder.mdx:906-917` — "The complete built-in set is fixed … Aggregate: `count`, `sum`, `avg`, `min`, `max`" — the aggregate helpers are not a fixed list; they are derived from the contract's aggregate map, which on PostgreSQL also carries `countBigInt`, `sumBigInt`, `avgDecimal`, and `count()` has a zero-argument form — evidence: `packages/2-sql/4-lanes/sql-builder/src/expression.ts:183-200`, `packages/3-targets/3-targets/postgres/src/core/aggregates.ts`, `docs/releases/v8.0.0-rc.2.md`. + +## Missing + +- Whole-query raw SQL lane (``db.raw.sql`...`.returnsRow(spec)`` / `.affectedCount()`, raw subqueries and CTEs by interpolating a `RawRowQuery`, and the `.returns` column-ref record added in rc.5) — evidence it exists: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts`, `docs/releases/v8.0.0-rc.2.md`, `docs/releases/v8.0.0-rc.5.md`, `examples/prisma-8-demo/src/queries/raw-query-demo.ts` — belongs on `orm/reference/raw-queries.mdx` (it currently says the opposite). +- `runtime.query(plan)` vs `runtime.execute(plan)` (rows vs `{ affectedRows }`), and `tx.query` / `tx.execute` inside `db.transaction(...)` — evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `packages/3-extensions/postgres/src/runtime/postgres.ts:346-372` — belongs under "Compiling and executing" on `orm/reference/sql-query-builder.mdx`. +- The two middleware lifecycles (`beforeQuery`/`interceptQuery`/`onRow`/`afterQuery` and `beforeExecute`/`interceptExecute`/`afterExecute`), `interceptExecute` returning `{ stats }`, `AfterExecuteResult.stats.affectedRows`, and the `params: SqlParamRefMutator` third argument on both before-hooks — evidence: `packages/2-sql/5-runtime/src/middleware/sql-middleware.ts` — belongs on `orm/middleware/how-middleware-works.mdx` and `orm/middleware/authoring-custom-middleware.mdx`. +- `ctx.signal` (per-operation `AbortSignal`, `RUNTIME.ABORTED { phase }`) on the middleware context — evidence: `packages/1-framework/1-core/framework-components/src/execution/runtime-middleware.ts:53-59` — belongs in "The context object" on `orm/middleware/authoring-custom-middleware.mdx`. +- `MongoMiddleware` (`familyId?: 'mongo'`) from `@prisma/orm-mongo/family-runtime`, and the `mode: 'strict' | 'permissive'` option on `mongo(...)` — evidence: `packages/2-mongo-family/7-runtime/src/mongo-middleware.ts:45-46`, `packages/3-extensions/mongo/src/runtime/mongo.ts:44-48`, `examples/mongo-demo/src/db.ts:2` — belongs on `orm/middleware/authoring-custom-middleware.mdx` step 5. +- `createInMemoryCacheStore` (exported, lets you share one store between clients or set your own `clock`) and the `middleware.cache.hit` / `middleware.cache.miss` / `middleware.cache.store` debug log events — evidence: `packages/3-extensions/middleware-cache/src/exports/index.ts`, `packages/3-extensions/middleware-cache/src/cache-middleware.ts:262, 275, 305` — belongs on `orm/middleware/built-in-cache.mdx`. +- Lossless aggregates `countBigInt()`, `sumBigInt()`, `avgDecimal()` and zero-argument `count()` on `fns` — evidence: `docs/releases/v8.0.0-rc.2.md`, `packages/3-targets/3-targets/postgres/src/core/aggregates.ts` — belongs under "Built-in functions" on `orm/reference/sql-query-builder.mdx`. +- `fns.cosineSimilarity` from pgvector (alongside `cosineDistance`) — evidence: `packages/3-extensions/pgvector/src/types/operation-types.ts:17-32` — belongs on `orm/extensions/using-extensions.mdx` step 5. +- `db.prepare(declaration, (sql, params) => plan)` prepared statements; `limit()`/`offset()` accept a prepared bind site (`PaginationValue`) — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:67-70`, `packages/2-sql/4-lanes/sql-builder/src/types/shared.ts:63-64`, `docs/releases/v8.0.0-rc.2.md` ("Prepared statements split by their declared result") — belongs on `orm/reference/sql-query-builder.mdx`. +- Driver-free static client (`@prisma/orm-postgres/static`, `@prisma/orm-mongo/static`) exposing the SQL builder, `raw`, and `enums` without a connection — evidence: `packages/9-public/@prisma/orm-postgres/package.json` (`./static`), `docs/releases/v0.15.0.md` ("Client-safe static surface") — belongs under "Entry points" on `orm/reference/sql-query-builder.mdx`. +- `raw` is a reserved storage namespace (`ORM.NAMESPACE_RESERVED`) — evidence: `docs/releases/v8.0.0-rc.2.md` — belongs on `orm/reference/raw-queries.mdx`. +- `RUNTIME.MISSING_EXTENSION_PACK` is the error raised when the contract needs an extension the client did not register — evidence: `packages/2-sql/5-runtime/src/sql-context.ts:229-232` — belongs under "Capabilities" on `orm/extensions/using-extensions.mdx:101`, which describes the failure without naming the code. +- `runtime.query()` returns `AsyncIterableResult`, so SQL-builder and raw plans can be streamed with `for await` — evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-313` — belongs under "Streaming vs. collecting" on `orm/reference/sql-query-builder.mdx:1008`, which sends users to the ORM client instead. + +## Unverified + +- `orm/reference/sql-query-builder.mdx:589, 936` — a raw `EXTRACT(...)` annotated `.returns('pg/int4@1')` "still decodes as a string" — I could not find where a raw expression's declared codec is or is not applied on the decode path; given rc.2 made codec ids in raw fragments contract-checked, the claim needs re-testing against rc.9. +- `orm/reference/pipeline-builder.mdx:190-194` — "`_id` equality inside `match()` never matches any document" — the only `f._id.eq(...)` tests in the source check plan shape in the contract-free builder (`packages/2-mongo-family/5-query-builders/query-builder/test/contract-free-collection.test.ts:37-147`); no live test confirms or refutes the claim. +- `orm/reference/pipeline-builder.mdx:128, 346` — a `lookup()` sub-document's `_id` "comes back as a raw driver `ObjectId`" — `docs/releases/v0.15.0.md` says reshaping reads decode through codecs; I found no source for lookup sub-document decoding either way (`pipeline-result-shape.ts` has no lookup handling). +- `orm/reference/pipeline-builder.mdx:937` — pipeline `insertMany` result shown as `{ insertedIds: { '0': …, '1': … } }` — the declared `InsertManyResult.insertedIds` is `ReadonlyArray` (`packages/2-mongo-family/4-query/query-ast/src/result-types.ts:16`); I could not confirm which shape the pipeline builder path yields on rc.9. +- `orm/reference/raw-queries.mdx:245-263` — raw `findOneAndUpdate` "always uses the driver's `'before'` default", so the first upsert call returns an empty result — the wrapper does pass `returnDocument` as `undefined` (`packages/2-mongo-family/5-query-builders/orm/src/raw-collection.ts:81-88`), but I could not find where the wire layer resolves an undefined `returnDocument`. +- `orm/extensions/using-extensions.mdx:76` — "If `db init` reports a contract-space layout violation … run `migration plan` once: it writes the extension's baseline migration under `migrations//`" — I searched `packages/2-sql/3-tooling` and `packages/3-extensions/postgres` for "layout violation" and "contract-space" and found no such message; only `skills/prisma-8/references/contract.md:53` describes the `migrations//` layout. +- `orm/extensions/using-extensions.mdx:116` — "ParadeDB and Supabase are experimental" — neither README nor either public `package.json` carries an experimental marker. The ParadeDB `key_field`-only restriction is confirmed (`packages/3-extensions/paradedb/README.md:9`). +- `orm/reference/sql-query-builder.mdx:917` — "`ilike` is registered by the Postgres adapter for textual columns" as an `fns` helper — I found no `ilike` operation contributed to the SQL builder's function bag in `packages/3-targets/6-adapters/postgres` or `packages/3-targets/3-targets/postgres`; `ilike` exists on the ORM field proxy (`skills/prisma-8/references/queries-postgres.md`). + +## Skill vs site + +- `skills/prisma-8/references/queries-postgres.md:255-300` and `skills/prisma-8/references/queries.md:144, 149` use `db.runtime().execute(plan)` to read rows; `skills/prisma-8/references/queries-mongo.md` uses `(await db.runtime()).execute(plan)`. The site does the same. Both are wrong: the source uses `query()` for rows (`packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-99`, `examples/prisma-8-demo/src/queries/*.ts`, `examples/mongo-demo/test/query-builder-writes.test.ts`). +- `skills/prisma-8/references/queries-postgres.md:392, 415` and `queries.md:143` spell the raw lane ``db.raw.sql`…` ``; the site (`orm/reference/raw-queries.mdx:121`) uses ``db.raw`…` ``. The skill matches the source (`packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:164-166`). +- `skills/prisma-8/references/queries.md:143` says whole-query raw SQL exists with `.returnsRow()` / `.affectedCount()`; the site (`orm/reference/raw-queries.mdx:19, 130`) says there is no way to run a standalone raw statement. The skill matches the source. +- `skills/prisma-8/references/runtime.md` ("What Prisma Next doesn't do yet") says lints and budgets must be imported from `@internal/sql-runtime` because the facade has no middleware subpath; the site imports them from `@prisma/orm-postgres/family-runtime`. The site matches the source: the export map has `./family-runtime` and the demo imports from it (`packages/9-public/@prisma/orm-postgres/package.json`, `examples/prisma-8-demo/src/prisma/db.ts:3`). +- `skills/prisma-8/references/queries-postgres.md:258` shows `db.sql.user.insert({ email })` with a single object; the site (`orm/reference/sql-query-builder.mdx:725`) says `insert()` always takes an array. The site matches the source (`packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts:122-123`, `rows: ReadonlyArray<...>`). +- `skills/prisma-8/references/queries.md:146` says there is no streaming surface; the site (`orm/reference/sql-query-builder.mdx:1008`) says streaming exists on the ORM client's `AsyncIterableResult`. The source returns `AsyncIterableResult` from `runtime.query()` on both the ORM and SQL-builder paths, so the site is closer, but neither says a SQL-builder plan can be streamed directly. +- `skills/prisma-8/references/runtime.md` ("Lints take `severities` (with the five keys above)") lists the five real lint severity keys; the site (`orm/middleware/built-in-lints.mdx:68`) adds a sixth, `unindexedPredicate`. The skill matches the source (`packages/2-sql/5-runtime/src/middleware/lints.ts:13-23`). diff --git a/docs/orm-docs-audit/audit/contract.md b/docs/orm-docs-audit/audit/contract.md new file mode 100644 index 00000000000..45a3e3cd08c --- /dev/null +++ b/docs/orm-docs-audit/audit/contract.md @@ -0,0 +1,60 @@ +# Audit: contract + +Pages read: `orm/contract-authoring/the-data-contract.mdx`, `orm/contract-authoring/the-contract-artifact.mdx`, `orm/contract-authoring/psl-syntax.mdx`, `orm/contract-authoring/typescript-schema-builder.mdx`, `orm/contract-authoring/capabilities.mdx`, `orm/data-modeling/index.mdx`, `orm/data-modeling/relational-databases.mdx`, `orm/data-modeling/mongodb.mdx`, `cli/contract-emit.mdx`, `cli/contract-infer.mdx` + +## Breaks copy-paste + +- `orm/contract-authoring/typescript-schema-builder.mdx:66` (also 165, 167, 241, 247) — `defineContract({ extensionPacks: { pgvector } }, ...)` — the option is `extensions: { pgvector }`; `extensionPacks` was renamed in 0.17 and "the old key fails loudly", so the PostgreSQL contract on this page does not build — evidence: `wip/prisma-src/docs/releases/v0.17.0.md` ("`extensionPacks` config key renamed to `extensions` — in ... the TS builder ..."), `wip/prisma-src/packages/3-extensions/postgres/src/contract/define-contract.ts` (`readonly extensions?: Extensions`), `wip/prisma-src/packages/2-sql/2-authoring/contract-ts/README.md` (`extensions: { pgvector }`). The config-side `extensions: [pgvector]` at line 256 is correct. + +## Misleading + +- `orm/contract-authoring/the-contract-artifact.mdx:49` (also 81, 98, 119, 121) — hashes shown as `"sha256:…"` and `StorageHashBase<"sha256:9f49…">` — content hashes are bare hex since 0.17 and "loaders reject the prefixed form"; emitted files carry `StorageHashBase<'8abaa…'>` with no prefix — evidence: `wip/prisma-src/docs/releases/v0.17.0.md` ("Content hashes are bare hex"), `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.d.ts:38-43`, `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.json` (`"profileHash": "3916f…"`). +- `orm/contract-authoring/the-contract-artifact.mdx:100` (also 111) — contract.json top-level key `"extensionPacks": {}` — the emitted key is `extensions` (renamed 0.17, and it is inside the hashed bytes); emitted files also carry `meta` and a `_generated` notice block the page's outline omits — evidence: `wip/prisma-src/docs/releases/v0.17.0.md`, `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.json` (top-level keys: `schemaVersion, targetFamily, target, profileHash, roots, domain, storage, execution, capabilities, extensions, meta, _generated`). +- `orm/data-modeling/relational-databases.mdx:81` — "The mirror field on the other model (`profile Profile?` on `User`) is not supported yet" — a bare optional model-typed field with no `@relation` is accepted as the 1:1 back side (it only requires the FK to be unique, else `PSL_NON_UNIQUE_BACKRELATION`) — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/test/interpreter.relations.test.ts:78` ("accepts a bare model-typed optional field with no @relation as the 1:1 back side"), `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/psl-relation-resolution.ts:462`, `wip/prisma-src/docs/releases/v0.16.0.md` ("A singular back-relation over a non-unique foreign key is rejected at emit"). +- `orm/data-modeling/relational-databases.mdx:192` — "pass the discriminator value explicitly when you create through a variant ... it is not filled in automatically yet" — creating through the variant-narrowed collection (`db.orm.public.Task.variant('Bug').create({...})`) injects the discriminator automatically; the page never mentions `.variant()` at all and instead points at `db.orm.public.Bug` — evidence: `wip/prisma-src/packages/3-extensions/sql-orm-client/src/collection.ts:406` ("Insert under a variant — discriminator is injected automatically"), `wip/prisma-src/examples/prisma-8-demo/src/orm-client/collections.ts:48`, `wip/prisma-src/skills/prisma-8/references/queries-mongo.md:22`. +- `orm/data-modeling/relational-databases.mdx:463` — "Referential actions ... are covered in the relations reference as it lands" (implies they are not available) — `onDelete`/`onUpdate` with `NoAction`, `Restrict`, `Cascade`, `SetNull` are parsed and lowered today — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/psl-relation-resolution.ts:19-22`, `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts:1255`, `wip/prisma-src/skills/prisma-8/references/contract.md:92-99`. +- `orm/data-modeling/index.mdx:159` — scalar table lists `Json` as "Arbitrary JSON value" — on PostgreSQL `Json` binds to native `json` since 0.17 and `Jsonb` is the separate scalar for `jsonb` (which is what the TS builder's `field.json()` and value objects use); the table never mentions `Jsonb`, `Decimal`, or `Bytes` — evidence: `wip/prisma-src/docs/releases/v0.17.0.md` ("`Json` re-binds to native `json` storage, with a new `Jsonb` scalar"), `wip/prisma-src/packages/3-targets/6-adapters/postgres/src/exports/control.ts:15` (`valueObjectStorageType: 'Jsonb'`), `wip/prisma-src/packages/3-targets/3-targets/postgres/src/core/authoring.ts:721-727` (`json` preset emits `pg/jsonb@1`). +- `orm/contract-authoring/psl-syntax.mdx:173-181` — the "Named types" section teaches `types { Uuid = String @db.Uuid }` as the way to get a `uuid` column (the `@db.Uuid` part is the known item) — the replacement is that `Uuid` is a built-in type name in type position and needs no alias: `id Uuid @id @default(uuid())`; the page should show an alias over a real type (for example `ShortName = VarChar(35)`) — evidence: `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.prisma` (`id Uuid @id @default(uuid())`), `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("Resolve Postgres native storage types from bare names and constructor calls in type position (`Char`, `VarChar`, `Numeric`, `Uuid`, ...)"). +- `cli/contract-infer.mdx:16` (also 23) — usage and option table present `--db` as required — `--db` falls back to `db.connection` from `prisma.config.ts`; only when neither is set does the command fail — evidence: `wip/prisma-src/packages/1-framework/3-tooling/cli/src/orm/contract/infer.ts` (`const dbConnection = args.flags.db ?? ctx.config.db?.connection`). +- `orm/contract-authoring/typescript-schema-builder.mdx:169` — "The MongoDB builder is simpler: it exports `field`, `model`, and `rel` directly, and its `defineContract` takes a single definition object" — the Mongo builder also exports `index`, `valueObject`, `member`, `enumType`, and `defineContract` has the same factory overload as PostgreSQL — evidence: `wip/prisma-src/packages/3-extensions/mongo/src/exports/contract-builder.ts`, `wip/prisma-src/packages/3-extensions/mongo/src/contract/define-contract.ts` (overload 2, "factory form"). + +## Missing + +- Native PostgreSQL types in type position (`Uuid`, `VarChar(255)`, `Char`, `Numeric`, `Inet`, `SmallInt`, `Real`, `Timestamp`, `Timestamptz`, `Date`, `Time`, `Timetz`, `Json`, `Jsonb`, `BigIntNumber`, `UnboundedInt`) — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md`, `wip/prisma-src/docs/releases/v0.17.0.md` — belongs on `psl-syntax.mdx` (Models and fields / Named types) and the scalar table on `data-modeling/index.mdx`. +- `@@index` options: `expression:`, `where:` (partial), `unique:`, `type:`/`options:`, and `name:` vs `map:` naming; `@@unique([...])` composite uniques — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("`@@index` parameter surface"), `wip/prisma-src/skills/prisma-8/references/contract.md:101-108` — belongs on `psl-syntax.mdx` (Models and fields). The relational page's agent prompt asks for a composite unique, but no page shows the syntax. +- `@@check(expression:, name: | map:)` hand-written CHECK constraints and the `sql.checkConstraint` capability (present in the demo's emitted capabilities but absent from the page's excerpt) — evidence: `wip/prisma-src/skills/prisma-8/references/contract.md:269-290`, `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.json` (`"checkConstraint": true`) — belongs on `psl-syntax.mdx` and `capabilities.mdx`. +- `@noCheck` / `@noCheck(membership)` / `@noCheck(elementNotNull)` to waive generated CHECK constraints on enum and list columns (TS: `.noCheck(...)`) — evidence: `wip/prisma-src/skills/prisma-8/references/contract.md:265`, `wip/prisma-src/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts:294` — belongs on `psl-syntax.mdx` (Enums). +- Scalar lists (`String[]`) are supported on PostgreSQL and rejected only on targets without `sql.scalarList` (SQLite); the data-modeling overview shows `tags String[]` but `psl-syntax.mdx` never says lists exist, which database supports them, or that list columns get a generated not-null-element CHECK — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/psl-field-resolution.ts:497-500`, `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.json` (`"scalarList": true`) — belongs on `psl-syntax.mdx`. +- `@@control(managed | tolerated | external | observed)` per-model control policy and `defaultControlPolicy` — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("Model-level control policy"), `wip/prisma-src/skills/prisma-8/references/contract.md:333-346` — belongs on `psl-syntax.mdx` and `the-contract-artifact.mdx`. +- `namespace { ... }` blocks for non-default PostgreSQL schemas, and cross-contract-space relation targets (`supabase:auth.AuthUser`) — evidence: `wip/prisma-src/packages/1-framework/2-authoring/psl-parser/src/parse.ts:502`, `wip/prisma-src/skills/prisma-8/references/contract.md:292-331` — belongs on `psl-syntax.mdx`. The artifact page says everything is "grouped by namespace" without saying how to author one. +- `native_enum` blocks (real `CREATE TYPE ... AS ENUM`) with `@@map` for the Postgres type name, and the TS `nativeEnum(...)` / `pg.enum(handle)` helpers, as the alternative to `@@type`-coded enums — evidence: `wip/prisma-src/packages/3-targets/3-targets/postgres/src/core/authoring.ts` (`keyword: 'native_enum'`), `wip/prisma-src/packages/3-extensions/postgres/src/contract/native-enum.ts` — belongs on `psl-syntax.mdx` (Enums) and `typescript-schema-builder.mdx` (Enums). +- `@@rls`, `policy_select` / `policy_insert` / `policy_update` / `policy_delete` / `policy_all` blocks and `role` blocks in PSL; `rlsEnabled`, `policy*`, `role` handles in the TS builder — evidence: `wip/prisma-src/packages/3-targets/3-targets/postgres/src/core/authoring.ts:121-125`, `wip/prisma-src/packages/3-extensions/postgres/src/exports/contract-builder.ts` — belongs on `psl-syntax.mdx` / `typescript-schema-builder.mdx` (RLS outside Supabase is a known site-wide gap; the authoring syntax is the part that belongs in this area). +- The `@default(...)` generator surface: `uuid(4)`, `uuid(7)`, `cuid(2)`, `ulid()`, `nanoid()`, `nanoid()`, `dbgenerated("...")`, and that `cuid()` is rejected with a hint to use `cuid(2)` — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("Supported `@default(...)` surface") — belongs on `psl-syntax.mdx` (Models and fields). +- Timestamp presets `temporal.createdAt()` / `temporal.updatedAt()` in PSL type position, and that Prisma 7's `@updatedAt` is rejected (`PSL_UNSUPPORTED_FIELD_ATTRIBUTE` with a hint) — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("Supported timestamp authoring surface") — belongs on `psl-syntax.mdx`; the TS page shows `field.temporal.updatedAt()` but the PSL page has no way to express an updated-at field. +- `onDelete` / `onUpdate` on `@relation` and `@relation("Name")` disambiguation when several relations join the same two models — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/psl-relation-resolution.ts:19-22`, `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md` ("Matching may use `@relation("Name")`") — belongs on `relational-databases.mdx` and `psl-syntax.mdx` (Relations). +- Extension types inline in field position (`embedding pgvector.Vector(length: 1536)?`) without a `types {}` alias, and the `PN-CLI-4011`-style "missing extension" failure mode is now a dotted structured code — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md`, `wip/prisma-src/docs/releases/v0.17.0.md` — belongs on `psl-syntax.mdx` (Extension types). +- TS builder field helpers beyond the four listed: `field.int()`, `field.bigint()`, `field.float()`, `field.decimal()`, `field.boolean()`, `field.bytes()`, `field.dateTime()`, `field.id.uuidv7String()`, `field.id.nanoid({ size })`, `field.uuidNative()` / `field.id.uuidv4Native()` / `field.id.uuidv7Native()`, `type.BigIntNumber()`, `type.UnboundedInt()`; and that scalar helpers exist only inside the factory callback (outside it only `field.column`, `field.generated`, `field.namedType`) — evidence: `wip/prisma-src/packages/3-targets/3-targets/postgres/src/core/authoring.ts:679-793`, `wip/prisma-src/packages/2-sql/2-authoring/contract-ts/README.md` ("Helper Notes") — belongs on `typescript-schema-builder.mdx` (Fields). +- TS builder model-level features: `.attributes(({ fields, constraints }) => ({ id, uniques }))` for composite keys and uniques, `constraints.index(...)` under `.sql({ indexes })`, `check(...)` under `.sql({ checks })`, `.noCheck()`, `rel.belongsTo(...).sql({ fk })`, and the root-level `foreignKeyDefaults` / `naming` options — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-ts/README.md` ("Constraint Placement", "Indexes", "Foreign Key Defaults"), `wip/prisma-src/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts:1207-1215` — belongs on `typescript-schema-builder.mdx` (Storage mapping). The page shows no way to declare a composite primary key in TypeScript. +- Mongo TS builder: `valueObject(...)` + `field.valueObject(Address)` for embedded documents, `index({...}, { unique })` and `collectionOptions`, `field.vector()`, `enumType`/`member`, and discriminator polymorphism via `base` / `discriminator` / `variants` — evidence: `wip/prisma-src/packages/2-mongo-family/2-authoring/contract-ts/README.md` — belongs on `typescript-schema-builder.mdx`; the MongoDB tab cannot express the embedded `Address` the PSL tab on `psl-syntax.mdx` shows. +- Mongo PSL index syntax beyond `@@index([f])`: sort order per field (`@@index([createdAt(sort: Desc), authorId])`), `@@unique`, `@@textIndex`; and that per-index `collation`, `partialFilterExpression`, `wildcardProjection` need the TS builder — evidence: `wip/prisma-src/examples/mongo-demo/src/contract.prisma`, `wip/prisma-src/packages/2-mongo-family/2-authoring/contract-psl/README.md` — belongs on `mongodb.mdx` / `psl-syntax.mdx` (MongoDB tab). +- `contract infer` is SQL-only (fails with `CONTRACT.INFER_UNSUPPORTED` on MongoDB), its default output is `contract.prisma` next to the emitted `contract.json`, and it captures indexes, `@@check` (as `map:`), `@@rls` and policy blocks, and 1:1 relations from unique indexes — evidence: `wip/prisma-src/packages/1-framework/3-tooling/cli/src/orm/contract/infer.ts`, `wip/prisma-src/packages/1-framework/3-tooling/cli/src/orm/contract/paths.ts`, `wip/prisma-src/docs/releases/v0.17.0.md` ("`contract infer` reaches full fidelity") — belongs on `cli/contract-infer.mdx` (What to review). +- The config `output` option on `ormConfig({ contract, output })` (a directory; `contract.json` and `contract.d.ts` land there instead of next to the source), which `create-prisma` sets to `./src/prisma/generated` for TypeScript authoring — evidence: `wip/prisma-src/packages/3-extensions/postgres/src/config/define-config.ts` (`join(options.output, 'contract.json')`), `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs` — belongs on `typescript-schema-builder.mdx` (Point the config at the contract file) and `cli/contract-emit.mdx`. +- The Vite plugin that re-emits on save (`@prisma/orm-postgres/vite-plugin-contract-emit`) as the alternative to running `contract emit` by hand — evidence: `wip/prisma-src/packages/9-public/@prisma/orm-postgres/package.json` (`./vite-plugin-contract-emit`), `wip/prisma-src/skills/prisma-8/references/contract.md:12` — belongs on `cli/contract-emit.mdx` / `the-contract-artifact.mdx` (Version control). +- `contract emit` prints the three hashes and returns them in `--json` (`storageHash`, `executionHash`, `profileHash`, `outDir`, `files`) — evidence: `wip/prisma-src/packages/1-framework/3-tooling/cli/src/orm/contract/emit.ts` (`EmitDocument`) — belongs on `cli/contract-emit.mdx` (Options / `--json`). +- Querying polymorphic variants with `.variant('Bug')` (narrows reads and injects the discriminator on create), on both SQL and Mongo — evidence: `wip/prisma-src/packages/3-extensions/sql-orm-client/src/collection.ts:395-410`, `wip/prisma-src/skills/prisma-8/references/queries-mongo.md:57` — belongs on `relational-databases.mdx` and `mongodb.mdx` (Polymorphic sections). +- `AddressInput` alongside `AddressOutput`, plus `FieldOutputTypes`, `TypeMaps`, `QueryOperationTypes`, `AggregateTypes` in `contract.d.ts` — evidence: `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.d.ts` — belongs on `the-contract-artifact.mdx` (Inside `contract.d.ts`), which only shows the output type. + +## Unverified + +- `orm/data-modeling/relational-databases.mdx:192` — "Variants appear as their own models in queries (`db.orm.public.Bug` ...)" — the runtime facet enumerates every model in `domain.namespaces[ns].models`, which includes variants, so the property resolves; I could not confirm that creating through it (rather than through `.variant('Bug')`) sets the discriminator, or that the site's `{ title, severity, type: "bug" }` shape is accepted there. Checked `wip/prisma-src/packages/3-extensions/sql-orm-client/src/orm.ts:155-185`, `storage-resolution.ts:42-48`, and the demo, which only ever uses `.variant(...)`. +- `orm/data-modeling/relational-databases.mdx` (whole page) — the default referential action when `onDelete` is omitted; the skill says `Restrict` but I could not find the default in the interpreter or planner. Checked `psl-relation-resolution.ts`, `interpreter.ts:1255-1304`, and grepped the postgres target and sql family for a fallback. +- `orm/contract-authoring/the-contract-artifact.mdx:142-145` — `postgres({ contractJson })` with no `url`; the runtime accepts `url?` and the demo omits it, so a connection presumably comes from `db.connect(...)` or `prisma.config.ts`; how the URL is resolved is outside this area. Checked `wip/prisma-src/packages/3-extensions/postgres/src/runtime/postgres.ts:88,312`. + +## Skill vs site + +- `orm/data-modeling/mongodb.mdx:126-148` and `psl-syntax.mdx:281` show `@@discriminator` / `@@base` in PSL for MongoDB; the skill says these attributes "are SQL-only" and Mongo polymorphism needs the TS builder (`contract.md:221`). The site matches the source: the Mongo attribute registry includes both, and `examples/mongo-demo/src/contract.prisma` uses them — evidence: `wip/prisma-src/packages/2-mongo-family/2-authoring/contract-psl/README.md`, `wip/prisma-src/examples/mongo-demo/src/contract.prisma`. +- `orm/data-modeling/index.mdx:167` shows `tags String[]`; the skill (`contract.md:123`) and the contract-psl README say scalar lists "are rejected by the SQL interpreter". The site matches the source: lists are gated on `sql.scalarList`, which PostgreSQL declares — evidence: `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/src/psl-field-resolution.ts:497`, `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.json`. +- `typescript-schema-builder.mdx:66` uses `extensionPacks`; the skill (`contract.md:51,386`) uses `extensions: { pgvector }`. The skill matches the source — evidence: `wip/prisma-src/packages/3-extensions/postgres/src/contract/define-contract.ts`, `wip/prisma-src/docs/releases/v0.17.0.md`. +- The site's config samples use `definePrismaConfig({ orm: ormConfig({...}) })`; the skill (`contract.md:47,164-170`) still shows the flat `defineConfig({ contract, extensions })` from `@internal/postgres/config` as the whole file. The site matches the source: the flat shape was removed in rc.4 and every example and the create-prisma template use the envelope — evidence: `wip/prisma-src/docs/releases/v8.0.0-rc.4.md` ("The deprecated config fallbacks are gone"), `wip/prisma-src/examples/prisma-8-demo/prisma.config.ts`, `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs`. +- The skill (`contract.md:28,62-66`) routes on `PN-CLI-4002` / `PN-CLI-4003` / `PN-CLI-4011`; those codes were replaced by dotted structured codes in 0.17. Neither the site nor the skill lists the current codes for a failed emit — evidence: `wip/prisma-src/docs/releases/v0.17.0.md` ("Every published error is a structured envelope with a dotted code"). +- `psl-syntax.mdx:302` declares the pgvector type via a `types {}` alias with a positional argument (`pgvector.Vector(1536)`); the skill (`contract.md:179`) writes it inline on the field with a named argument (`pgvector.Vector(length: 1536)`). Both forms are accepted; the demo uses the site's spelling — evidence: `wip/prisma-src/examples/prisma-8-demo/src/prisma/contract.prisma`, `wip/prisma-src/packages/2-sql/2-authoring/contract-psl/README.md`. diff --git a/docs/orm-docs-audit/audit/extras.md b/docs/orm-docs-audit/audit/extras.md new file mode 100644 index 00000000000..1aeeb54ed26 --- /dev/null +++ b/docs/orm-docs-audit/audit/extras.md @@ -0,0 +1,112 @@ +# Audit: extras + +Pages read: `(index)/full-stack-tutorial.mdx`, `ai/tools/skills.mdx`, `cli/telemetry.mdx` (in full). Also consulted for cross-checks: `cli/skills.mdx`, `cli/init.mdx`, `cli/configuration.mdx`, `orm/extensions/using-extensions.mdx`, `orm/data-modeling/index.mdx`, `orm/reference/transactions-and-runtime.mdx`, `orm/fundamentals/reading-data.mdx`, `guides/database/multiple-databases.mdx`. + +Sources used: `wip/create-prisma-src/` (what the `hono` scaffold generates), `wip/prisma-src/packages/1-framework/3-tooling/cli/` (orm init, migration plan, telemetry hooks), `wip/prisma-src/packages/1-framework/3-tooling/cli-telemetry/`, `wip/prisma-src/skills/`, `wip/prisma-src/docs/Telemetry.md`, `wip/prisma-src/docs/reference/*`, and the packages named per finding. The `skills sync` and `telemetry status|enable|disable` command implementations are not in the ORM monorepo (`skills sync` appears only in a test name; `telemetryCommandGroup` is imported from the external `@prisma/cli-engine` package in `packages/1-framework/3-tooling/cli/src/orm/cli.ts:4`), so claims about those commands' exact behaviour are checked against `skills/README.md` and `docs/Telemetry.md` only. + +## Breaks copy-paste + +- `ai/tools/skills.mdx:102` — says `orm init --skip-skills` skips skill installation — no such flag exists. `orm init` takes `--target`, `--authoring`, `--schema-path`, `--write-env`, `--probe-db`, `--strict-probe`, `--skip-install`, `--keep-previous-facade` and does not touch skills at all — evidence: `packages/1-framework/3-tooling/cli/src/orm/init.ts:92-110`; `packages/1-framework/3-tooling/cli/src/commands/init/skill-sources.ts:1-5` ("Skills setup belongs to the family-level `prisma init` command; the only skill work left in `orm init` is deleting the retired directories"); `skills/README.md` ("`prisma orm init` does not touch them"). +- `ai/tools/skills.mdx:111-112` — lists `prisma-next-upgrade` and `prisma-8-extension-upgrade` as installable Prisma 8 skills — both names are retired; only one skill, `prisma-8`, ships, and upgrading is a branch inside it (`references/upgrade-app.md`, `references/upgrade-extension.md`). A user running `npx skills add ... --skill prisma-next-upgrade` gets nothing, and `prisma init` actively deletes directories with those names — evidence: `wip/prisma-src/skills/` contains only `prisma-8/`; `skills/README.md` ("One installable skill"); `packages/1-framework/3-tooling/cli/src/commands/init/skill-sources.ts:24-38` (`RETIRED_SKILL_NAMES` includes `prisma-next-upgrade` and `prisma-8-extension-upgrade`). + +## Misleading + +- `(index)/full-stack-tutorial.mdx:193-203` — shows the scaffold's `User` model with `createdAt DateTime @default(now())` and `updatedAt temporal.updatedAt()`, and tells the user to "add one line" — the `hono` scaffold's contract is written by `prisma orm init` and actually contains `createdAt TimestamptzString @default(now())` and `updatedAt temporal.updatedAtString()`. Both spellings are valid PSL, but the user's file will not match the page, and the two store different runtime types (`Temporal` object vs. string) — evidence: `packages/1-framework/3-tooling/cli/src/commands/init/templates/code-templates.ts:171-193` (`starterSchemaPslPostgres`); `wip/create-prisma-src/src/tasks/prisma-setup/commands.ts:50-63` (create-prisma runs `orm init --schema-path src/prisma/contract.prisma`); `packages/2-sql/2-authoring/contract-psl/README.md:18,70` (both `DateTime @default(now())` and `temporal.updatedAt()` are valid). +- `(index)/full-stack-tutorial.mdx:51` and `:28` — say the scaffold "added the `postinstall` hook that keeps [skills] current" and that `init` repairs it — create-prisma adds a `skills:sync` npm script (`prisma skills sync || exit 0`) and runs `prisma init --yes` once; it does not write a `postinstall` hook. Whether the family-level `prisma init` adds one cannot be checked in the ORM monorepo — evidence: `wip/create-prisma-src/src/tasks/install.ts:56`; `wip/create-prisma-src/src/tasks/prisma-setup/commands.ts:65-72`. +- `ai/tools/skills.mdx:102` — "Projects scaffolded with `create-prisma` or `orm init` install them automatically" — `create-prisma` does (it runs the family-level `prisma init --yes`), `orm init` does not — evidence: `wip/create-prisma-src/src/tasks/prisma-setup/commands.ts:65-72`; `packages/1-framework/3-tooling/cli/src/commands/init/skill-sources.ts:1-5`. +- `ai/tools/skills.mdx:114` — "`orm init` applies this pinning for you" (pinning `npx skills add ...#v`) — `orm init` does not install skills from GitHub at all; the version match comes from the skill shipping inside the installed `@prisma/orm-*` tarball and `prisma skills sync` copying it — evidence: `skills/README.md` (Install and Versioning sections); `packages/9-public/@prisma/orm-postgres/package.json` (`"files": ["dist", "skills"]`, `prepack` runs `sync-package-skills.ts`). +- `ai/tools/skills.mdx:105` and `:19-20` — present `npx skills add prisma/prisma/skills` as the way to add Prisma 8 skills to an existing project — the monorepo README calls that "interoperability, not the recommended path: nothing keeps a copy installed this way up to date", and the recommended path is `prisma init` / `prisma skills sync`, which the page only mentions in passing at line 36 — evidence: `skills/README.md` ("Manual fallback — install from GitHub"). +- `ai/tools/skills.mdx:114` — "The two upgrade skills are intentionally unpinned; the latest revision covers every prior transition" — there are no separate upgrade skills; the per-transition instructions live under `prisma-8/upgrading/app/upgrades/-to-/` inside the single skill, and "The version you upgrade *to* carries the instructions" — evidence: `skills/README.md`; `wip/prisma-src/skills/prisma-8/upgrading/`. +- `guides/database/multiple-databases.mdx` (whole page, e.g. `:63`, `:109`) — sits in the non-versioned `guides/` tree and is the only ORM 8 page matching "multiple databases", but it is a Prisma 7 guide (`@prisma/client@7.10.0`, `schema.prisma`, `PrismaClient`). A Prisma 8 user searching for multi-database or replica guidance lands on v7 instructions with no banner — evidence: `guides/database/multiple-databases.mdx:63,93,109`; ORM 8 has no multi-database routing (`skills/prisma-8/references/runtime.md:323`). +- `cli/telemetry.mdx:9` — "Telemetry is on by default" with no mention that CI environments never send events and never see the first-run notice, so a user reading only this page may add opt-out env vars to CI unnecessarily. Not wrong, but incomplete — evidence: `packages/1-framework/3-tooling/cli/src/orm/telemetry/reporting.ts:75-78`; `docs/Telemetry.md` ("CI environments"). + +## Missing + +Ranked by how likely a user is to need it, most likely first. Items marked (known) are in the instructions' already-known list but are included here because the task asked for evidence for each. + +1. Telemetry: how to opt out without the CLI, and what is sent — `cli/telemetry.mdx` never mentions `DO_NOT_TRACK=1` or `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file (`~/.config/prisma-next/config.json` / `%APPDATA%\prisma-next\config.json`, `enableTelemetry` field), that CI is always silent, the first-run stderr notice, that `telemetry` itself sends nothing, that the preference is per-user not per-project, agent detection via `@vercel/detect-agent` / `AI_AGENT`, or the event fields. Note the field list in `docs/Telemetry.md` is itself stale: the rc.9 sender also reports `exitCode` ("No outcome data" in the doc is no longer true) — evidence: `packages/1-framework/3-tooling/cli-telemetry/src/gating.ts:62-72`, `user-config.ts:23-51`, `payload.ts:101-116`, `enrich.ts:205-223`; `packages/1-framework/3-tooling/cli/src/orm/telemetry/reporting.ts:24-31,75-92`; `docs/Telemetry.md` — belongs on `cli/telemetry.mdx`. +2. Row level security and policies on plain Postgres (known) — supported without Supabase: PSL `policy_select` / `policy_insert` / `policy_update` / `policy_delete` / `policy_all` blocks with `target`, `roles`, `using`, `withCheck`, `permissive = false`, `@@map`; `@@rls` on the model; roles declared as contract entities; TS builder `policySelect` … `policyAll`, `rlsEnabled(Model)`, `role('name')` from `@prisma/orm-postgres/contract-builder`; `contract infer` captures live policies; the planner emits `ENABLE ROW LEVEL SECURITY` and `CREATE POLICY` — evidence: `packages/3-extensions/postgres/src/contract/rls.ts` (role, enablement and policy handles), `packages/3-targets/3-targets/postgres/src/core/postgres-rls-policy.ts`, `postgres-rls-enablement.ts`, `postgres-role.ts`, `migrations/operations/rls.ts`, `psl-infer/infer-policy-blocks.ts`; `skills/prisma-8/references/contract.md:378`; `skills/prisma-8/references/supabase.md` ("Contract: FK into auth.users + RLS policies") — the site only mentions RLS in error codes (`orm/reference/error-reference.mdx:382-392,436`) — belongs in `orm/contract-authoring/` (a "Row level security" page) with a note that the Supabase pack only supplies the roles. +3. Expression (functional) and partial indexes (known) — `@@index(expression: "lower(email)", name: "users_email_lower")`, `@@index([...], where: "...")`, `unique:`, `type:` (btree, hash, gin, gist, spgist, brin) and `options:`, `name:` vs `map:`; TS builder `constraints.index({ expression, ... })` — evidence: `packages/2-sql/1-core/contract/src/ir/sql-index.ts:12-26,45-60`; `packages/3-targets/3-targets/postgres/src/core/index-types.ts`; `skills/prisma-8/references/contract.md:101-108` — the site shows only `@@index([cols])` (`orm/contract-authoring/psl-syntax.mdx:97,137`; `orm/reference/orm-client.mdx:161-162`) — belongs on `orm/contract-authoring/psl-syntax.mdx`. +4. `@@control()` and `defaultControlPolicy` — a model can declare `managed`, `tolerated`, `external`, or `observed` to say whether Prisma owns its DDL; a contract-wide default goes on `prismaContract(path, { defaultControlPolicy })` — evidence: `packages/2-sql/2-authoring/contract-psl/README.md:104`; `packages/2-sql/2-authoring/contract-psl/src/interpreter.ts:341`, `psl-field-resolution.ts:418-422`; `packages/9-public/@prisma/orm-postgres/package.json` export `./contract/apply-specifier-default-control-policy`; `skills/prisma-8/references/contract.md:333-346` — no ORM 8 page contains `@@control` — belongs on `orm/contract-authoring/psl-syntax.mdx` and `orm/migrations/how-migrations-work.mdx`. +5. Vite plugin — `@prisma/orm-postgres/vite-plugin-contract-emit` exports `prismaVitePlugin('prisma.config.ts', { debounceMs, logLevel })`, re-emits the contract on save in `vite dev` (Vite 7 and 8 only; no build-time emit; no Next.js / Webpack / esbuild / Rollup / Turbopack plugin) — evidence: `packages/9-public/@prisma/orm-postgres/package.json` (`"./vite-plugin-contract-emit"`); `packages/1-framework/3-tooling/vite-plugin-contract-emit/`; `skills/prisma-8/references/build.md` — the only site hits for "vite" are TanStack's own Nitro plugin (`guides/frameworks/tanstack-start.mdx:86`) — belongs in `orm/contract-authoring/` or a new "Build tools" page, and in `guides/frameworks/tanstack-start.mdx`. +6. `Decimal` (known) — PSL `Decimal` maps to Postgres `numeric` with optional `precision` (1..1000) and `scale` params; runtime value is a decimal string (`CANONICAL_NUMERIC_TEXT`); `@default` accepts numeric text; aggregates: `sum` over `numeric` returns a decimal `string | null`, `avgDecimal(field)` gives an exact decimal string, `sumBigInt` / `countBigInt` for integers, and `count()` / `sum` over integers throw `RUNTIME.DECODE_FAILED` past 2^53-1 — evidence: `packages/3-targets/3-targets/postgres/src/core/codecs.ts:121-175,547`; `codec-type-map.ts:73`; `default-normalizer.ts:18,221`; `psl-infer/infer-enum-blocks.ts:19`; `skills/prisma-8/references/queries-postgres.md:233-255,386,407` — `orm/data-modeling/index.mdx:152-160` omits `Decimal` from the scalar table and `:182` says to store money as integer minor units; nothing documents `avgDecimal` / `sumBigInt` / the overflow error — belongs on `orm/data-modeling/index.mdx` and `orm/fundamentals/advanced-queries.mdx` (aggregates). +7. SQLite target (known) — `@prisma/orm-sqlite` ships at rc.9 with `sqlite(...)` runtime, `[Symbol.asyncDispose]`, and its own capability limits (no `checkConstraint`, no `scalarList`, no `enums`, no `lateral`, no `avgDecimal`); the skill routes to it throughout — evidence: `packages/9-public/@prisma/orm-sqlite/package.json`; `packages/3-extensions/sqlite/src/runtime/sqlite.ts:85,354`; `skills/prisma-8/references/runtime.md:333`, `queries-postgres.md:255`, `contract.md` (`@@check` on SQLite) — site mentions are only `orm/reference/error-reference.mdx:598`, `cli/skills.mdx:38` and capability examples in `orm/contract-authoring/capabilities.mdx:46-70`; there is no getting-started, quickstart, or runtime section for SQLite — belongs in `(index)/prisma-orm/quickstart/`, `orm/reference/transactions-and-runtime.mdx`, `orm/index.mdx`. +8. Enabling a Postgres extension that has no pack (`pg_trgm`, `citext`, …) (known) — the migration authoring API has a structured `createExtension('')` op (renders `CREATE EXTENSION IF NOT EXISTS`), so a user can add it to a hand-written or edited `migration.ts`; there is no contract-level "requires extension" declaration, and no `pg_trgm` pack ships even though `docs/reference/capabilities.md:97-103` reserves a `pg_trgm` capability namespace — evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/op-factory-call.ts:1443-1465` (`CreateExtensionCall`, `renderTypeScript` → `createExtension("...")`); `migrations/operations/dependencies.ts:7-22`; `packages/3-extensions/` has no `pg_trgm` — the site only mentions `CREATE EXTENSION` for packs that ship their own migration (`orm/extensions/using-extensions.mdx:76`) — belongs on `orm/migrations/editing-a-migration.mdx`. +9. Streaming is cursor-backed on Postgres — the site documents `for await` over `.all()` (`orm/fundamentals/reading-data.mdx:280-313`) but never says the Postgres driver reads through a server-side cursor in batches (`pg-cursor`, `cursorBatchSize`) nor that the serverless client takes `cursor` options; the skill wrongly says "No `.stream()` cursor today" — evidence: `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:24,374-384`, `named-cursor.ts`; `packages/3-extensions/postgres/src/runtime/postgres-serverless.ts:31` (`PostgresServerlessCursorOptions`); `packages/2-sql/5-runtime/src/sql-runtime.ts:387-399` — belongs on `orm/fundamentals/reading-data.mdx` and `orm/reference/transactions-and-runtime.mdx`. +10. `create-prisma` flags used by the tutorial — the tutorial uses `create ... --template hono --provider postgres --yes`, and `--authoring`, `--package-manager`, `--deploy`, `--workspace`, `--force`, `--json`, `--verbose` also exist; the tutorial says "Answer the prompts for contract authoring style and package manager" without naming the flags that skip them — evidence: `wip/create-prisma-src/src/index.ts:39-86` — belongs on `(index)/full-stack-tutorial.mdx:45` (one line) and `(index)/prisma-orm/create-prisma.mdx`. + +## Unverified + +- `(index)/full-stack-tutorial.mdx:213` — "a Composer deploy never sets the `db` ref that `migration plan` chains from by default" — Composer is not in the ORM monorepo, so this cannot be checked. What is verifiable: `--from` accepts "hash, prefix, ref name, migration dir name, `^`, `@empty`, or `./path`" (`packages/1-framework/3-tooling/cli/src/orm/migration/plan.ts:204-208`), so `--from _init` is a valid spelling, and the directory format is `_` (`packages/1-framework/3-tooling/migration/src/io.ts:456-470`). +- `(index)/full-stack-tutorial.mdx:218` — the shown DDL `ALTER TABLE "public"."user" ADD COLUMN "role" text DEFAULT 'member' NOT NULL` — the column is rendered through `renderColumnDdl` → `contractFree.col(name, type, { notNull, default })` (`packages/3-targets/3-targets/postgres/src/core/migrations/column-ddl-rendering.ts:64-78`); I did not trace the final clause ordering inside `contractFree.col`, so the exact text is unconfirmed. Table name `user` is consistent with the known `db.sql.public.user` item. +- `ai/tools/skills.mdx:19,102` and `cli/skills.mdx:9,48-54` disagree with each other and with the monorepo on the agent directory list. `ai/tools/skills.mdx` says Claude Code, Cursor, Codex, Windsurf (matches `skills/README.md` and `packages/1-framework/3-tooling/cli/src/commands/init/skill-sources.ts:44-49`: `.claude`, `.cursor`, `.agents`, `.windsurf`). `cli/skills.mdx:53`, `cli/init.mdx:29`, `cli/configuration.mdx:94` say `claude`, `cursor`, `agents`, `devin` (matches the create-prisma scaffold's `prisma.config.ts`, `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs`: `agents: ["claude", "cursor", "agents", "devin"]`). The `skills sync` implementation is not in the monorepo, so I cannot say which list is current; one of the two pages is wrong. +- `ai/tools/skills.mdx:19,102` — links "prisma/prisma" text to `https://github.com/prisma/orm`, and the install command is `npx skills add prisma/prisma/skills` — `skills/README.md` uses `prisma/prisma/skills`, but `packages/9-public/@prisma/orm-postgres/package.json` `repository.url` is `https://github.com/prisma/orm.git`. Could not determine which GitHub path the `skills` CLI must be given. +- `cli/telemetry.mdx` — the rc.9 first-run notice points users to `https://prisma-next.dev/docs/cli/telemetry` (`packages/1-framework/3-tooling/cli/src/orm/cli.ts:47`; `reporting.ts:24-31`), not to this page's URL. Source-side issue, noted because users will arrive from that link. + +## Skill vs site + +- `skills/prisma-8/references/queries.md:146` says "Streaming large result sets. No `.stream()` cursor today" and recommends holding a `pg.Client` to stream; the site (`orm/fundamentals/reading-data.mdx:280-313`) says `for await` over `.all()` streams without buffering. The source matches the site: `collection.ts:998-1022` exposes the async-iterable read terminal and the Postgres driver iterates via `pg-cursor` (`packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:374-384`). The skill is stale. +- `skills/prisma-8/references/runtime.md:11,135-158,315,322` tells users to import `createTelemetryMiddleware` from `@internal/middleware-telemetry`; no such package exists in the rc.9 tree (only comments and old plan docs mention it). The site's "Three middleware ship with Prisma 8 today" (`orm/middleware/how-middleware-works.mdx:82`: lints, budgets, cache) matches the source (`packages/2-sql/5-runtime/src/middleware/{lints,budgets}.ts`, `packages/3-extensions/middleware-cache/`). The skill is stale; also `runtime.md` never mentions the cache middleware the site documents. +- `skills/prisma-8/references/contract.md:25,29,49` uses `cipherstash.EncryptedString(...)` as a canonical extension example; no cipherstash package exists in the rc.9 tree (`wip/prisma-src/CHANGELOG.md:1040` records `@prisma-next/extension-cipherstash` being dropped in favour of CipherStash's own `@cipherstash/prisma-next`, `README.md:82`). The site does not mention cipherstash, which is correct. +- `skills/prisma-8/references/contract.md:179` writes `pgvector.Vector(length: 1536)`; the site (`orm/extensions/using-extensions.mdx`) and `examples/prisma-8-demo/src/prisma/contract.prisma:4` use positional `pgvector.Vector(1536)`. The examples compile against rc.9, so the site matches. +- `skills/prisma-8/SKILL.md` and `skills/README.md` describe one skill (`prisma-8`) synced from installed packages by `prisma init` / `prisma skills sync`; `ai/tools/skills.mdx:100-114` describes three skills installed by `orm init` from GitHub. The source matches the skill (see Breaks copy-paste and Misleading above). +- `docs/Telemetry.md` says "No outcome data. Phase 1 does not collect success/failure, exit code"; the rc.9 sender includes `exitCode` (`packages/1-framework/3-tooling/cli-telemetry/src/payload.ts:115`, `enrich.ts:222`; `reporting.ts:86-99` fires from `onSettled` with `summary.exitCode`). The monorepo doc is stale; the site says nothing either way. + +## Part 2: targeted gap questions + +Each item: is it supported at rc.9, where the evidence is, and whether the ORM 8 part of the site documents it. Site greps covered `orm/` (not v6/v7), `cli/` (not v7), `(index)/prisma-orm/`, `(index)/getting-started.mdx`, `guides/` (not v7). + +### Supported and undocumented (these are the Missing items above) + +- Row level security outside Supabase — supported (Missing item 2). Site: no page; only error codes. +- Expression and functional indexes — supported (Missing item 3). Site: none. +- Enabling `pg_trgm` and other extensions from a migration — supported via `createExtension()` op in `migration.ts`; not declarable in the contract (Missing item 8). Site: none beyond packs that ship their own migration. +- `Decimal` precision and scale, `@default` on Decimal, aggregate return types — supported (Missing item 6). Site: `Decimal` is not even in the scalar table (`orm/data-modeling/index.mdx:152-160`). +- SQLite target — ships (Missing item 7). Site: `orm/index.mdx:36` still says planned (known); no runtime or quickstart coverage. +- Vite plugin — ships (Missing item 5). Site: none. +- `@@control` policies — supported (Missing item 4). Site: none. +- Streaming — supported and documented; the cursor mechanics are not (Missing item 9). + +### Supported and documented + +- `await using` on the client — `[Symbol.asyncDispose]` on the Postgres, SQLite, Mongo, Supabase and serverless clients (`packages/3-extensions/postgres/src/runtime/postgres.ts:73,381`, `sqlite/src/runtime/sqlite.ts:85,354`, `mongo/src/runtime/mongo.ts:40,237`, `supabase/src/runtime/supabase.ts:111,491`, `postgres-serverless.ts:181`). Site: `orm/reference/transactions-and-runtime.mdx:148-164,328-343` documents it, including the block-scope warning that matches `skills/prisma-8/references/runtime.md:318`. +- Streaming results — `for await` over `.all()` / `.createAll()` / update / delete terminals (`packages/3-extensions/sql-orm-client/src/collection.ts:998-1022,1313-1329,1932-1947,2100-2113`). Site: `orm/fundamentals/reading-data.mdx:280-313`, including the "read once" rule. + +### Not supported at rc.9 + +- Filtering on JSON columns by path or containment — not supported. The `jsonb` codec declares only the `equality` trait, so the ORM `where` shorthand allows whole-value `eq` / `in` on a `Json` field and nothing else; the SQL builder has no JSON path, `->>`, or `@>` functions (`packages/3-targets/3-targets/postgres/src/core/codecs.ts:1417-1421`; no `json` hits in `packages/2-sql/4-lanes/sql-builder/src/` or `packages/3-targets/3-targets/postgres/src/core/ast/`). The only JSON-aware builder pieces are `jsonObject` / `jsonArrayAgg` used internally for includes (`sql-orm-client/src/where-binding.ts:72-75`). Instead: use `db.raw.sql\`...\`` or `fns.raw` in a builder `.select(...)` (`skills/prisma-8/references/queries.md:143`), or `@prisma/orm-extension-arktype-json` for typed storage (not filtering). Site: `orm/data-modeling/index.mdx:159` lists `Json` with no note on filter limits — worth a one-line "Misleading by omission" fix there. +- Soft delete, model validations, lifecycle callbacks — not supported (`skills/prisma-8/references/contract.md:392-394`). Instead: `deletedAt DateTime?` plus explicit filters or a middleware; validate with arktype in app code; use middleware for hooks. Site: no ORM 8 page claims these exist (the `validation` / `callback` grep hits are unrelated uses of the words). +- Custom `Collection` subclasses — not a supported extension point. `Collection` is exported as a type-level surface from `@prisma/orm-postgres/orm-client` (`packages/3-extensions/sql-orm-client/src/exports/index.ts:1`), but the implementation is a `CollectionImpl` class with private `#clone` / `#createSelf` methods (`collection.ts:216,2434-2495`) that cannot be subclassed to add behaviour. Instead: wrap queries in plain functions or write middleware. Site: nothing claims otherwise. +- Read replicas and multi-database routing — not supported (`skills/prisma-8/references/runtime.md:323`; `grep -ri replica packages/` finds only the Mongo replica-set note in `packages/1-framework/3-tooling/cli/src/commands/init/templates/env.ts:44-47` and the cache store). Instead: construct one client per database in separate `db.ts` modules and pick in app code. Site: `guides/database/multiple-databases.mdx` is the only match and is a v7 guide (see Misleading). +- Prisma Composer and a Prisma Postgres native provider — absent from the ORM monorepo. No `@prisma/composer*` code or `prisma+postgres://` handling exists under `packages/` (`grep -ri composer packages/` hits one test; `grep -ri 'prisma+postgres\|accelerate' packages/` hits nothing). Prisma Postgres is reached through the ordinary `pg` driver with a `postgres://` URL (`packages/9-public/@prisma/orm-postgres/package.json` dependencies: `pg`). The scaffold wires Composer's `service.load().database.client` ahead of `DATABASE_URL` (`wip/create-prisma-src/templates/create/_shared/src/prisma/db.ts.hbs`). Instead: nothing needed; the site's Composer coverage lives outside the ORM section and could not be audited against source. +- `pg_trgm` as an extension pack — no pack ships (`packages/3-extensions/`: arktype-json, middleware-cache, paradedb, pgvector, postgis, supabase, plus the postgres / sqlite / mongo façades and sql-orm-client). Instead: `createExtension('pg_trgm')` in a migration plus `@@index(..., type: "gin", ...)` for the index; there are no trigram operators in the builder, so similarity queries go through `db.raw`. + +### Extension packages vs site + +| Package | Public name | Site coverage | +| --- | --- | --- | +| `3-extensions/pgvector` | `@prisma/orm-extension-pgvector` (`/control`, `/pack`, `/runtime`, `/column-types`, `/codec-types`, `/operation-types`) | Worked example throughout `orm/extensions/using-extensions.mdx`; correct | +| `3-extensions/postgis` | `@prisma/orm-extension-postgis` (adds `/geojson`) | Catalog row only (`orm/extensions/using-extensions.mdx:111`) plus error codes; no page for the `Geometry` type or its 7 operations | +| `3-extensions/paradedb` | `@prisma/orm-extension-paradedb` (`/index-types`, `/operation-types`) | Catalog row only (`:112,116`); `key_field`-only caveat matches the README | +| `3-extensions/supabase` | `@prisma/orm-extension-supabase` (`/pack`, `/runtime`, `/contract`; no `/control`) | Catalog row only (`:113`). The page's generic 5-step recipe (import `.../control`, pass to `postgres({ extensions })`) does not work for this package: it is wired via `extensions: [supabasePack]` from `/pack` and the client is built with `supabase()` from `/runtime` (`packages/9-public/@prisma/orm-extension-supabase/package.json`; `skills/prisma-8/references/contract.md:348-367`, `supabase.md`). Report this as Misleading on `orm/extensions/using-extensions.mdx` | +| `3-extensions/arktype-json` | `@prisma/orm-extension-arktype-json` (`arktypeJson(schema)` column factory) | Catalog row only (`:114`); `arktypeJson` never shown | +| `3-extensions/middleware-cache` | `@prisma/orm-extension-middleware-cache` | Dedicated page `orm/middleware/built-in-cache.mdx`; correct | +| lints, budgets (no own package) | `@prisma/orm-postgres/family-runtime` | Dedicated pages `orm/middleware/built-in-lints.mdx`, `built-in-budgets.mdx`; import path matches `packages/0-shared/publish-surface/src/shells.ts:219` | +| cipherstash | none at rc.9 (dropped; see `CHANGELOG.md:1040`) | Correctly absent | +| telemetry middleware | none at rc.9 | Correctly absent (the skill still names it) | + +One more site-side issue from that inventory: every catalog row links to `github.com/prisma/orm/tree/main/packages/3-extensions/#readme`, and those READMEs instruct `pnpm add @internal/extension-`, a private name users cannot install (`packages/3-extensions/pgvector/README.md`, `paradedb/README.md`, `postgis/README.md`). The site's package names are right; its links lead to wrong install commands. + +### Monorepo reference docs vs site + +Written from the sub-agent's report (docs under `wip/prisma-src/docs/`). Only user-facing facts are listed; `mongodb-feature-support-priorities.md`, `mongodb-idioms.md`, `mongodb-primitives-reference.md`, `mongodb-user-journey.md`, `mongodb-user-promise.md`, and `framework-gaps.md` are internal planning or contributor docs and describe intent, not shipped behaviour; treat their claims as unverified unless the source confirms them. + +- `Serverless Deployment Guide.md` — two facades: `postgres()` (long-lived, cursors disabled) and `postgresServerless()` (per-request, cursors enabled by default); `await using runtime = await db.connect({ url })`; Cloudflare Hyperdrive as the tested path (`nodejs_compat`, `wrangler hyperdrive create`, `WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_*`); migrations run on Node against the origin URL, never through Hyperdrive; one runtime per `connect()` and no crossing runtimes inside a transaction; Workers isolate memory is 128 MiB so `limit()` is the memory cap; bundle about 254 KiB gzipped. Production caveat at lines 97 and 274: against real Hyperdrive the default cursor path hangs (`Protocol Error: Unexpected protocol code: C`, SQLSTATE 58000, request killed at 30 s with Cloudflare error 1101), workaround `cursor: { disabled: true }`. None of this is on the site; the only Cloudflare guide is Prisma 7. The guide's own import paths are `@internal/postgres/*`; the public path is `@prisma/orm-postgres/serverless`. +- `Supported Versions.md` — Node 24, Bun 1.2, Deno 2.0, PostgreSQL 15, MongoDB 8.0, TypeScript 5.9 (optional peer), `tsconfig` must set `moduleResolution: "bundler"` and `strict: true`, `prisma orm init --merge-tsconfig`, ESM-only with no CommonJS. Site: Bun guide says 1.1; PostgreSQL floor stated nowhere; ESM-only and `strict` stated nowhere; `--merge-tsconfig` does not exist in `orm/init.ts` at rc.9 (doc is stale there); the upgrade guide presents `module: nodenext` as the example setting; the doc's Node 24 disagrees with the scaffold's `^22.18.0 || >=24.11.0`. +- `reference/integer-representation-types.md` — `BigInt` (default, `bigint`), `BigIntNumber` (`number`, guarded to 2^53-1), Postgres-only `UnboundedInt`; PSL and TS authoring; the aggregate result matrix per column type; SQLite has no `avgDecimal`. Site documents only the runtime errors, never the types as features. +- `reference/aggregate-descriptor-guide.md` — Postgres contributes `count`, `countBigInt`, `sum`, `sumBigInt`, `avg`, `avgDecimal`, `min`, `max`; `min`/`max` output the input's own type (site says numeric-only); the aggregate map lives in `contract.d.ts` only. +- `reference/codec-authoring-guide.md` — two user-facing caveats buried in a contributor doc: `pg/geometry@1` is exempt from the canonical JSON round-trip guarantee (PostGIS users, no warning on the site), and float codecs need `extra_float_digits >= 1` on the session with nothing enforcing it; `NaN` and infinities are rejected by `sql/float@1`, accepted by `pg/numeric@1`. +- `reference/postgres-native-enums.md` — why a contract `enum` is a CHECK constraint (no in-transaction `ADD VALUE`, no remove or reorder, full-table rewrite on retype); externally managed native enums are supported; self-managed native enums get `ADD VALUE` only from `migration plan`. Site states the CHECK fact and nothing else; `orm-client.mdx:478` documents native-enum ordering without ever saying how to get one. +- `reference/capabilities.md` — disagrees with `orm/contract-authoring/capabilities.mdx` on where `lateral` / `returning` / `jsonAgg` live (`sql.*` vs `postgres.*`), on pack key nesting (`pgvector.cosine` vs `postgres.pgvector.cosine`), on the error code (`E_CAPABILITY_MISSING` vs the site's `ORM.CAPABILITY_MISSING`), and on whether capabilities are negotiated at connect time or fixed at emit time. The site's keys (`sql.scalarList`, `postgres.distinctOn`) do not appear in the doc. Unverified which is current; check `packages/3-targets/3-targets/postgres/src` for the real key strings before touching the site page. The handover notes that `docs/architecture docs/subsystems/` is stale; `docs/reference/` may be too. +- `reference/Mongo Pipeline Builder.md` — the doc is older than the site: it shows `mongoQuery()` from an internal path (site: `db.query.from(...)`), bare single-operation updaters (site says they must return an array and names "older internal material" as the source of the mistake), and `build()` executing (site: terminals return a plan). Site is closer to the source; add `merge()`'s `on` / `whenMatched` / `whenNotMatched` keys and the `null` row type on find-and-modify terminals. +- `mongodb-user-promise.md` claims cascade / restrict / setNull referential integrity for MongoDB as the "strongest differentiator"; `grep onDelete packages/2-mongo-family` (non-test) is empty, so it is not implemented at rc.9. Same doc says budgets and lints work on Mongo; the site says `familyId: 'sql'` and that matches the source. diff --git a/docs/orm-docs-audit/audit/gaps.md b/docs/orm-docs-audit/audit/gaps.md new file mode 100644 index 00000000000..dff1ea2ff6b --- /dev/null +++ b/docs/orm-docs-audit/audit/gaps.md @@ -0,0 +1,66 @@ +# Audit: gaps + +Pages read: guides/frameworks/astro.mdx, guides/frameworks/elysia.mdx, guides/frameworks/hono.mdx, guides/frameworks/nestjs.mdx, guides/frameworks/nextjs.mdx, guides/frameworks/nuxt.mdx, guides/frameworks/react-router-7.mdx, guides/frameworks/solid-start.mdx, guides/frameworks/sveltekit.mdx, guides/frameworks/tanstack-start.mdx, guides/deployment/docker.mdx, guides/deployment/cloudflare-workers.mdx, guides/deployment/cloudflare-d1.mdx, guides/deployment/turborepo.mdx, guides/deployment/pnpm-workspaces.mdx, guides/deployment/bun-workspaces.mdx, guides/runtimes/bun.mdx, guides/runtimes/deno.mdx, guides/integrations/github-actions.mdx, guides/integrations/vercel-deployment.mdx, guides/integrations/ai-sdk.mdx. For the reverse audit: `skills/prisma-8/SKILL.md`, every file in `skills/prisma-8/references/`, `docs/glossary.md`, and the `exports` maps of every package under `packages/9-public/@prisma/`. + +Verification sources for the Prisma 8 framework and runtime pages were the create-prisma templates under `wip/create-prisma-src/templates/create/` and its CLI source under `wip/create-prisma-src/src/`, since those pages document what the scaffold generates. + +## Breaks copy-paste + +Ten of the twenty-one pages in this area are Prisma ORM 7 content sitting under a Prisma ORM 8 path. Every install command, config file, schema block, CLI command, and query on them is Prisma 7. None of them has a copy under `guides/v7/` (`guides/v7/` only contains `frameworks/` and `runtimes/`, and neither `react-router-7` nor `solid-start` is in `guides/v7/frameworks/`), so the Prisma 7 content has no v7 home either. One bullet per page; the count is of distinct Prisma 7 constructs on that page. + +- `guides/frameworks/react-router-7.mdx:49` (12 constructs, through line 647) — `npm install prisma@7.10.0 …`, `@prisma/client@7.10.0 @prisma/adapter-pg`, `npx prisma init --output`, `generator client { provider = "prisma-client" }`, `prisma migrate dev`, `prisma generate`, `prisma db seed`, `prisma studio`, `new PrismaClient({ adapter })`, `prisma.user.findMany()`, `findUnique({ where })`, `create({ data })` — Prisma ORM 8 installs `@prisma/orm-postgres` and `prisma`, scaffolds with `prisma orm init` or `create-prisma`, emits with `contract emit`, applies with `db init` / `db update` / `migration plan` + `db migrate`, and queries through `db.orm.public.User.…`; there is no `generate`, `migrate dev`, `db seed`, or `studio` command — evidence: `packages/1-framework/3-tooling/cli/src/orm/{contract,db,migration}/` (the complete command set: `contract emit|infer`, `db init|update|sign|verify|schema`, `migration plan|new|show|status|list|log|graph|check`, `migrate`), `create-prisma-src/src/tasks/install.ts:47-58` (the scripts a scaffold gets), `skills/prisma-8/references/quickstart.md:387-391` (no Studio, no push-style sync), `skills/prisma-8/references/migrations.md:488` (no `db seed` equivalent). +- `guides/frameworks/solid-start.mdx:70` (11 constructs, through line 322: `import { User, Post } from "./generated/prisma/client"`) — same Prisma 7 flow as above — same evidence. +- `guides/deployment/docker.mdx:69` (10 constructs, through line 519) — `prisma@7.10.0`, `@prisma/client@7.10.0`, `prisma init --output`, generator block, `require("./generated/prisma_client/client")`, `"db:deploy": "npx prisma migrate deploy && npx prisma generate"` (line 201), `prisma migrate dev`, `prisma generate`, `npx prisma studio --port 5555` (line 519), and the Alpine `musl` engine note at line 347 — Prisma ORM 8 has no query engine binary to download; the Postgres runtime is the `pg` driver in-process, deployment runs `contract emit` at build time and `db migrate` (or `db init`) at start, and there is no Studio — evidence: `packages/3-extensions/postgres/README.md:8-10` (façade-owned `pg.Pool` / `pg.Client`), `skills/prisma-8/references/build.md:421-435` (`prebuild` emit), `skills/prisma-8/references/migrations.md:487` (run `db migrate` from the deploy pipeline). +- `guides/deployment/cloudflare-workers.mdx:49` (9 constructs, through line 344) — `prisma@7.10.0`, `runtime = "cloudflare"` generator field (line 106), `prisma migrate dev`, `prisma generate`, per-request `new PrismaClient({ adapter })` (line 243), `prisma.user.create({ data })`, `prisma.user.count()` — the Prisma ORM 8 per-request surface is `@prisma/orm-postgres/serverless`: `postgresServerless({ contractJson })` at module scope and `await using runtime = await db.connect({ url })` inside `fetch` — evidence: `packages/9-public/@prisma/orm-postgres/package.json` export `./serverless`, `packages/3-extensions/postgres/README.md:41-60,126-136`. Lines 416 and 418 already link to `/guides/v7/frameworks/hono` and `/orm/v7/...`, confirming the page is v7 content. +- `guides/deployment/cloudflare-d1.mdx:40` (9 constructs, through line 264) — `npx prisma@7.10.0 init --datasource-provider sqlite`, `@prisma/adapter-d1`, `runtime = "cloudflare"`, `prisma migrate diff --from-empty` / `--from-local-d1` (lines 180, 223), `prisma generate`, `new PrismaD1(env.DB)`, `prisma.$disconnect()` — Prisma ORM 8's SQLite target is `@prisma/orm-sqlite` (`sqlite({ contractJson, path })`); there is no D1 driver in the public package set and no `migrate diff` command — evidence: `packages/9-public/@prisma/` directory listing (no `adapter-d1` or D1 driver), `packages/9-public/@prisma/orm-sqlite/package.json` exports, `skills/prisma-8/references/runtime.md:285-296`, CLI command list above. +- `guides/deployment/turborepo.mdx:68` (10 constructs, through line 359) — `prisma@7.10.0`, `@prisma/client@7.10.0`, `prisma init`, generator block, `db:generate`/`db:migrate`/`db:deploy` scripts (`prisma generate`, `prisma migrate dev`, `prisma migrate deploy`), `npx turbo run db:migrate -- --name init`, "In Prisma 7, `migrate dev` no longer runs `prisma generate`" (line 231), `new PrismaClient`, `prisma.user.findFirst()` — Prisma ORM 8's shared package holds `prisma.config.ts`, `src/prisma/contract.prisma`, the emitted `contract.json` / `contract.d.ts`, `db.ts`, and `migrations/app/`; the scripts are `contract:emit`, `db:update`, `migration:plan`, `migrate` — evidence: `skills/prisma-8/references/quickstart.md:127-159` (canonical layout), `create-prisma-src/src/tasks/install.ts:47-58`. +- `guides/deployment/pnpm-workspaces.mdx:43` (10 constructs, through line 305) — `catalogs: prisma: 7.10.0`, `pnpm dlx prisma@7.10.0 init` (line 110), generator block, `prisma generate`/`migrate dev`/`migrate deploy`/`studio` scripts, `new PrismaClient({ adapter })`, `prisma.user.findFirst({ select })` — same as the Turborepo bullet — same evidence. +- `guides/deployment/bun-workspaces.mdx:61` (11 constructs, through line 224) — `prisma@7.10.0`, `@prisma/client@7.10.0`, `prisma init`, generator block, `prisma db seed` script (line 131), `prisma.user.createMany({ data, skipDuplicates: true })` (lines 198-204), `prisma.$disconnect()`, `seed: "bun prisma/seed.ts"` under `migrations` in `prisma.config.ts` (line 224) — Prisma ORM 8 has no `db seed` and no `seed` config key; the bulk insert is `createAll`; a seed is an ordinary script that imports `db` (the scaffolds put it at `src/prisma/seed.ts` and use `upsert` with `conflictOn`) — evidence: `skills/prisma-8/references/migrations.md:488`, `create-prisma-src/templates/create/_shared/src/prisma/seed.ts.hbs`, `skills/prisma-8/references/queries-mongo.md:327` (`createAll`). +- `guides/integrations/github-actions.mdx:46` (9 constructs, through line 445) — `prisma@7.10.0`, `@prisma/client@7.10.0`, `prisma init --output`, generator block, `seed:` in `prisma.config.ts` (line 120), `prisma migrate dev`, `prisma generate`, and the CI steps `npx prisma generate` + `npx prisma db push` (lines 424-427, 442) — the Prisma ORM 8 CI shape is `prisma contract emit`, then `prisma db init --db $URL` for a fresh database (or `migration status --to --db $URL --json` as the check and `db migrate --to --db $URL` to apply); there is no `db push` — evidence: `skills/prisma-8/references/migration-review.md:172-197`, `skills/prisma-8/references/quickstart.md:390`, CLI command list above. +- `guides/integrations/ai-sdk.mdx:56` (10 constructs, through line 392) — `prisma@7.10.0`, `@prisma/client@7.10.0`, `prisma init --output`, generator block, `prisma migrate dev`, `prisma generate`, `new PrismaClient({ adapter })`, `prisma.session.upsert({ where, update, create })` (line 320), `prisma.message.create({ data })` (line 357), `prisma.message.findMany({ orderBy: { createdAt: "asc" } })` (line 392), `npx prisma studio` (line 627) — Prisma ORM 8 spells these `db.orm.public.Session.upsert({ create, update, conflictOn })`, `db.orm.public.Message.create({ … })`, `db.orm.public.Message.orderBy((m) => m.createdAt.asc()).all()` — evidence: `skills/prisma-8/references/queries-postgres.md:196-219,345-377`, `create-prisma-src/templates/create/_shared/src/prisma/seed.ts.hbs` (`conflictOn`). +- All ten pages above: `prisma.config.ts` written as `defineConfig({ schema, migrations: { path }, datasource: { url: env("DATABASE_URL") } })` from `prisma/config` (first at `react-router-7.mdx:125`) — the Prisma ORM 8 config is `definePrismaConfig({ orm: ormConfig({ contract: "./src/prisma/contract.prisma", db: { connection: process.env.DATABASE_URL! } }) })` with `definePrismaConfig` from `prisma/config` and `defineConfig as ormConfig` from `@prisma/orm-postgres/config` — evidence: `create-prisma-src/templates/create/_shared/prisma.config.ts.hbs`, `packages/3-extensions/postgres/src/config/define-config.ts`. +- `guides/runtimes/bun.mdx:161` (also in the agent prompt at line 33) — replace the `build` script with `esbuild src/server.ts --bundle --platform=node --format=esm --outfile=dist/server.mjs` — the minimal scaffold's `build` is `tsdown`, driven by a generated `tsdown.config.ts` whose entry is `{ server: "src/index.ts" }`; `esbuild` is not a dependency the scaffold installs, so `bun run build` fails with a missing `esbuild` binary unless it happens to be hoisted from a transitive dependency; the change that matches the scaffold is editing `entry` in `tsdown.config.ts` to `src/server.ts` — evidence: `create-prisma-src/templates/create/minimal/package.json.hbs` (`"build": "tsdown"`), `create-prisma-src/templates/create/_shared/tsdown.config.ts.hbs`, `create-prisma-src/src/templates/render-create-template.ts:25-30`, `create-prisma-src/src/constants/dependencies.ts` (no `esbuild` entry). + +## Misleading + +- `guides/runtimes/bun.mdx:96` (also lines 99 and 152; `guides/frameworks/hono.mdx:154`; `guides/frameworks/elysia.mdx:125`; `guides/frameworks/nestjs.mdx:138`) — teardown is written as `await db.runtime().close()` — the client's teardown method is `await db.close()` (idempotent, terminal, also wired to `Symbol.asyncDispose`); `runtime().close()` closes the inner `Runtime` without marking the client closed, and every other page on the site (`orm/reference/transactions-and-runtime.mdx:135,145`, `(index)/prisma-orm/add-to-existing-project/mongodb.mdx:115`) uses `db.close()` — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:72,374-383`, `skills/prisma-8/references/runtime.md:66-78,126-133`. +- `guides/runtimes/bun.mdx:11` — "Bun runs TypeScript directly, so there is no build step anywhere in the flow" — the same page requires `bun run build` before `deploy` (lines 156-176), and the scaffold's `dev` script is `tsx watch src/index.ts` for every non-Deno package manager, so `bun run dev` (line 104) starts a watcher that never exits rather than running the script once and printing the two lines shown; `bun src/index.ts` is the one-shot run — evidence: `create-prisma-src/templates/create/minimal/package.json.hbs` (`"dev": "tsx watch src/index.ts"` in the non-Deno branch), `create-prisma-src/src/constants/dependencies.ts:57-63` (`tsx` installed for the minimal template). +- `guides/frameworks/nestjs.mdx:88-92` (repeated in the agent prompt at line 31) — tells the reader to add `@Inject(UsersService)` and `@Inject(PrismaService)` when `GET /users` returns 500 — the scaffold already emits both explicit injection tokens, so the note describes a state the template no longer produces — evidence: `create-prisma-src/templates/create/nest/src/users.controller.ts.hbs:7`, `create-prisma-src/templates/create/nest/src/users.service.ts.hbs:8`. +- `guides/frameworks/astro.mdx:27` — "Node.js 24 or later" (same on `nestjs.mdx:17`, `nextjs.mdx:17`, `nuxt.mdx:27`, `sveltekit.mdx:27`, `tanstack-start.mdx:27`, `hono.mdx:17`; 7 pages) — the scaffolds declare `"engines": { "node": "^22.18.0 || >=24.11.0" }` and create-prisma itself refuses anything below 22.18, so Node 22.18+ works and Node 24.0 to 24.10 does not — evidence: `create-prisma-src/templates/create/minimal/package.json.hbs`, `create-prisma-src/templates/create/hono/package.json.hbs`, `create-prisma-src/src/utils/node-version.ts:17-20`. (The known-issue list mentions differing Node claims on the getting-started pages; these are the framework pages.) +- `guides/runtimes/deno.mdx:142` — "The generated ORM tasks currently use the Deno-compatible Prisma 8 ORM CLI entry point. The consolidated `npm:prisma@latest` CLI still loads Node-only credential storage under Deno" — create-prisma now generates every Deno task against the consolidated CLI (`deno run -A --env-file=.env npm:prisma@latest db init` and so on); the separate entry point is gone — evidence: `create-prisma-src/src/constants/dependencies.ts:26-31` (`PRISMA_DENO_CLI_PACKAGE = PRISMA_PLATFORM_CLI_PACKAGE`, "The former `prisma-next` fallback is frozen"), `create-prisma-src/src/tasks/install.ts:25-45`. +- `guides/runtimes/deno.mdx:93-99` — the sample response shows only `email` and `name` per user — the generated `listUsers` (which the page itself prints at lines 108-127) returns `id`, `email`, `username`, `name`, and `createdAt` — evidence: `create-prisma-src/templates/create/_shared/src/prisma/users.ts.hbs`. +- `guides/frameworks/astro.mdx:78` — "`db:init` applies your schema (`src/prisma/contract.prisma`)" (same on `nestjs.mdx:66`, `nextjs.mdx:65`, `nuxt.mdx:76`, `sveltekit.mdx:75`, `tanstack-start.mdx:74`, `bun.mdx:62`; 7 pages) while the same pages say to "answer the prompts for contract authoring style" — with `--authoring typescript` the source is `src/prisma/contract.ts` and the emitted `contract.json` / `contract.d.ts` land under `src/prisma/generated/`, which no page mentions — evidence: `create-prisma-src/templates/create/_shared/prisma.config.ts.hbs`, `create-prisma-src/templates/create/_shared/src/prisma/db.ts.hbs` (`./generated/contract.json` when `authoring === "typescript"`). +- `guides/frameworks/astro.mdx:39` — "Then run `npx prisma@latest init` in `my-astro-app` so the Prisma agent skills are installed" (same step in every framework and Bun agent prompt; 9 pages) — create-prisma already runs `prisma init --yes` after scaffolding for every package manager except Deno, so the step repeats work the scaffold did; harmless but it suggests the scaffold leaves skills uninstalled — evidence: `create-prisma-src/src/tasks/prisma-setup/commands.ts:56-62`. +- `guides/integrations/vercel-deployment.mdx:18` — the only pointer for deploying your own Prisma ORM app to Vercel goes to `/orm/v7/prisma-client/deployment/serverless/deploy-to-vercel`, and line 629 says the demo templates use "Prisma ORM" without saying which major — under the Prisma 8 guides this sends readers to Prisma 7 instructions; there is no Prisma 8 Vercel deployment path on the site (see Missing). + +## Missing + +- A Prisma ORM 8 deployment guide for any host: Docker, Cloudflare Workers, Vercel, and the three monorepo pages are all Prisma 7 (see above), and nothing under `orm/`, `cli/`, or `(index)/prisma-orm/` mentions Docker, Workers, Lambda, or edge (`grep -i "cloudflare|workers|edge|lambda|docker"` finds nothing there). What a Prisma 8 deploy needs is documented in the source: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, and the per-request façade for edge runtimes — evidence: `skills/prisma-8/references/build.md:421-435`, `skills/prisma-8/references/migrations.md:487`, `packages/3-extensions/postgres/README.md:8-10,41-60` — belongs under `guides/deployment/`. +- `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })`, `await using runtime = await db.connect({ url })`, a fresh `pg.Client` per request, no `orm` / `runtime()` / `transaction()` on that façade, `cursor: { disabled: true }`) — the site never mentions it (`serverless` has zero hits under `orm/`, `cli/`, `(index)/prisma-orm/`) — evidence: `packages/9-public/@prisma/orm-postgres/package.json` export `./serverless`, `packages/3-extensions/postgres/src/exports/serverless.ts`, `packages/3-extensions/postgres/README.md:41-60,126-136` — belongs in `orm/reference/transactions-and-runtime.mdx` and a Prisma 8 Cloudflare Workers guide. +- The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (`prismaVitePlugin('prisma.config.ts', { debounceMs, logLevel })`, Vite 7 and 8, dev-server only, plus the `"prebuild": "prisma contract emit"` pattern for `vite build`, Next.js, Webpack, esbuild, Rollup, and Turbopack) — zero hits on the site — evidence: `packages/9-public/@prisma/orm-postgres/package.json` export `./vite-plugin-contract-emit`, `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`, `skills/prisma-8/references/build.md` — belongs in `orm/contract-authoring/the-contract-artifact.mdx` and the Vite-based framework guides (SvelteKit, Astro, Nuxt, TanStack Start), which currently tell readers to run `npm run contract:emit` by hand. +- The Supabase extension end to end: `@@rls` on a model, `policy_select` / `policy_insert` / `policy_update` / `policy_delete` / `policy_all` blocks with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, the async `supabase({ contractJson, url, jwksUrl | jwtSecret })` factory, role binding with `await db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()` returning a `RoleBoundDb`, the `asServiceRole().supabase` admin root, the session-pooler requirement (never port 6543), the one-time `GRANT` for `auth.*` reads, and the `SUPABASE.JWT_INVALID` / `SUPABASE.CONFIG_INVALID` errors — the site has one table row (`orm/extensions/using-extensions.mdx:113`) and the two error codes; `@@rls`, `policy_`, `asUser`, `jwksUrl`, and `RoleBoundDb` have zero hits — evidence: `packages/9-public/@prisma/orm-extension-supabase/package.json` (exports `./contract`, `./pack`, `./runtime`), `skills/prisma-8/references/supabase.md`, `skills/prisma-8/references/contract.md:309-331,348-367` — belongs as a page under `orm/extensions/` and a guide under `guides/` (the known-issue list covers RLS outside Supabase; this is RLS with Supabase). +- Control policy: `@@control(managed | tolerated | external | observed)` on a model and `defaultControlPolicy` in the config, and what each policy does to planned DDL and `db verify` — zero hits on the site (`control policy` appears only in `guides/integrations/permit-io.mdx`) — evidence: `skills/prisma-8/references/contract.md:333-346`, `skills/prisma-8/references/migrations.md:501-503`, `packages/9-public/@prisma/orm-postgres/package.json` export `./contract/apply-specifier-default-control-policy` — belongs in `orm/contract-authoring/psl-syntax.mdx` and `orm/migrations/how-migrations-work.mdx`. +- Index and check-constraint options: `@@index(expression: …, name: …)`, `@@index([…], where: "…", name: …)`, `unique:`, `type:` / `options:`, `@@check(expression: …, name: | map: …)`, `@noCheck` / `@noCheck(membership)` / `@noCheck(elementNotNull)`, and the naming rule behind `name:` (wire name, `_<8 hex>`) versus `map:` (exact name, body compared byte for byte, warns `PN_EXACT_NAME_BODY_COMPARISON`) — `orm/contract-authoring/psl-syntax.mdx:97,137` shows only `@@index([authorId])`; `@@check`, `@noCheck`, and `wire name` appear only inside `orm/reference/error-reference.mdx` — evidence: `skills/prisma-8/references/contract.md:101-108,265-290`, `packages/2-sql/1-core/contract/src/index-naming.ts:72`, `docs/glossary.md` "Naming Mode" and "Wire Name" — belongs in `orm/contract-authoring/psl-syntax.mdx` (functional and partial indexes are also on the known-missing list; this bullet adds the syntax and the naming rule). +- CLI telemetry opt-out via environment: `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, and `"enableTelemetry": false` in the per-user config — `cli/telemetry.mdx` lists only `telemetry status|enable|disable`; `DO_NOT_TRACK` appears on the site only for create-prisma's own telemetry (`(index)/prisma-orm/create-prisma.mdx:98`) — evidence: `packages/1-framework/3-tooling/cli/src/orm/telemetry/reporting.ts:30-31`, `packages/1-framework/3-tooling/cli-telemetry/src/gating.ts:17-26` — belongs on `cli/telemetry.mdx`. +- The full set of package scripts create-prisma generates: besides `contract:emit`, `db:init`, and `db:update` the scaffold adds `db:verify`, `migration:plan`, `migrate`, `migration:status`, `migration:show`, `skills:sync`, `composer:dev`, `composer:deploy`, `deploy` (build + composer deploy), and `dev:composer` — only `db:init`, `db:update`, `contract:emit`, and one `migration:plan` mention exist on the site — evidence: `create-prisma-src/src/tasks/install.ts:25-70` — belongs on `(index)/prisma-orm/create-prisma.mdx` and in each framework guide's "Where things live". +- The `composer` section of `prisma.config.ts` (`composer: { configPath: "./prisma-composer.config.ts" }`) and the generated Composer files every scaffold ships: `prisma-composer.config.ts` (`defineConfig({ extensions: [prismaCloud(), nodeBuild(), nextjsBuild()], state: prismaState() })`), `src/prisma/composer.ts` (`dataContract(contractJson)`), and the `db.ts` pattern `service.load().database.client ?? postgres({ contractJson, url: process.env.DATABASE_URL })` with `import "temporal-polyfill/global"` — `cli/configuration.mdx` documents only the `orm` and `skills` sections, and no framework page shows the generated `db.ts` — evidence: `create-prisma-src/templates/create/_shared/prisma.config.ts.hbs`, `prisma-composer.config.ts.hbs`, `src/prisma/composer.ts.hbs`, `src/prisma/db.ts.hbs` — belongs on `cli/configuration.mdx` and the framework guides. +- Where the automatic seed lives: `src/prisma/seed.ts` (three users via `upsert({ create, update: {}, conflictOn: { email } })`, memoised) called from `src/prisma/users.ts` before every `listUsers` — the framework pages say "seeded automatically on the app's first query" without naming either file (only `nestjs.mdx:99` and `sveltekit.mdx:89` name `users.ts`; the Deno page names both) — evidence: `create-prisma-src/templates/create/_shared/src/prisma/seed.ts.hbs`, `users.ts.hbs` — belongs in each framework guide's "Where things live". +- PSL scalar names the starter contract and the aggregate types use: `TimestamptzString` (the starter `createdAt` column), `BigIntNumber`, `UnboundedInt` — `TimestamptzString` and `BigIntNumber` appear only in `orm/reference/error-reference.mdx`, `UnboundedInt` nowhere; `psl-syntax.mdx` uses `DateTime` throughout — evidence: `packages/1-framework/3-tooling/cli/src/commands/init/templates/code-templates.ts:180`, `skills/prisma-8/references/queries-postgres.md:405-417` — belongs in `orm/contract-authoring/psl-syntax.mdx` (see Unverified for the `DateTime` question). +- The public packages `@prisma/orm-toolchain` (CLI, emitter, config loader, language server, Vite plugin) and `@prisma/orm-framework` (target-agnostic contract, components, PSL parser and printer) are never named — evidence: `packages/9-public/@prisma/orm-toolchain/package.json`, `packages/9-public/@prisma/orm-framework/package.json` — belongs on `orm/reference/index.mdx` or `cli/index.mdx` wherever the package set is listed. +- A Prisma 8 CI workflow: `prisma migration status --to --db "$URL" --json`, failing the job on any `diagnostics[]` entry with `severity: "warn"`, then `prisma db migrate --to --db "$URL"`; `migration status` exits 0 on warnings, so exit-code checks alone miss `MIGRATION.DIVERGED`, `MIGRATION.MARKER_NOT_IN_HISTORY`, `CONTRACT.AHEAD`, and `MIGRATION.NO_MARKER` — the only CI guide (`guides/integrations/github-actions.mdx`) is Prisma 7 — evidence: `skills/prisma-8/references/migration-review.md:172-197` — belongs in a rewritten `guides/integrations/github-actions.mdx`. + +## Unverified + +- `HostedStateBootstrapError` and the `--name` recovery (every framework page's deploy section, `guides/runtimes/bun.mdx:33,186`, `cli/deploy.mdx:28`) — the Composer / deploy implementation is not in `wip/prisma-src` (`grep -rl HostedStateBootstrapError packages` is empty) and the Composer packages are not in the worktree, so the error name and behaviour could not be checked. +- `guides/runtimes/deno.mdx:29,65` — `npx create-db@latest --env .env --ttl 24h` — the `create-db` source is not in the worktree; flags not checked. +- `guides/runtimes/deno.mdx:17` "Deno 2.0 or later" and `guides/frameworks/elysia.mdx:17` "Bun 1.1 or later" — no engine constraint for Deno or Bun in `create-prisma-src` or `prisma-src`. +- `orm/contract-authoring/psl-syntax.mdx:39` and the framework guides' starter contract — the site writes `createdAt DateTime` while the rc.9 starter contract writes `createdAt TimestamptzString @default(now())` (`code-templates.ts:180`); I could not find the PSL scalar-name table in `packages/2-sql/2-authoring/contract-psl/src` by grep (`'DateTime'` and `TimestamptzString` have no hits there), so whether `DateTime` still parses is not confirmed. Another area owns `psl-syntax.mdx`. +- The scaffold pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` (`create-prisma-src/src/constants/dependencies.ts:9-11`, "Must match @prisma/composer-prisma-cloud's exact peerDependency") while this audit is against rc.9; whether the published `create-prisma@latest` has moved could not be checked offline. Any rc.9-only behaviour the framework pages describe would not hold on a fresh scaffold until it does. + +## Skill vs site + +- Skill `references/debug.md:306-338`, `contract.md:62-66`, `migrations.md:67-75` route on numeric codes `PN-CLI-4001…4020`, `PN-MIG-2001…2005`, `PN-RUN-3001…3030`, `PN-SCHEMA-0001`; no such string exists in rc.9 `packages/` (`grep -rn "PN-MIG-[0-9]\|PN-CLI-[0-9]\|PN-RUN-[0-9]" packages --include='*.ts'` is empty); the site's `orm/reference/error-reference.mdx` uses the dotted `DOMAIN.CODE` form only. Site matches the source; the skill is stale here. +- Skill `references/quickstart.md:125` says the marker is a `pn_meta_marker` row; the source writes `prisma_contract.marker` and so does the site (`orm/migrations/the-migration-graph.mdx`, `orm/reference/error-reference.mdx`) — evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/runner.ts:321-326`. Site matches the source. +- Skill `references/runtime.md:135-158` documents `createTelemetryMiddleware` from `@internal/middleware-telemetry`; no such package exists in `packages/` or `packages/9-public/@prisma/` (grep empty). The site does not mention it, which is correct. +- Skill `references/runtime.md:66-78` and `queries.md:107-127` end scripts with `await db.close()`; the site's Bun, Hono, Elysia, and NestJS guides use `db.runtime().close()` while `orm/reference/transactions-and-runtime.mdx:135,145` uses `db.close()`. The source defines `close()` on the client (`packages/3-extensions/postgres/src/runtime/postgres.ts:72,374`); the skill and the reference page match it, the four guides do not. +- Skill `references/build.md:466` says Next.js has no first-party build integration and needs a `prebuild` emit; the site's `guides/frameworks/nextjs.mdx:117` tells readers to run `npm run contract:emit` by hand after schema changes and never mentions `prebuild`. Both agree there is no plugin; the site omits the workaround the skill gives. diff --git a/docs/orm-docs-audit/audit/migrations-cli.md b/docs/orm-docs-audit/audit/migrations-cli.md new file mode 100644 index 00000000000..f5340752d6e --- /dev/null +++ b/docs/orm-docs-audit/audit/migrations-cli.md @@ -0,0 +1,66 @@ +# Audit: migrations-cli + +Pages read: orm/migrations/how-migrations-work.mdx, orm/migrations/generating-a-migration.mdx, orm/migrations/editing-a-migration.mdx, orm/migrations/applying-a-migration.mdx, orm/migrations/rollbacks-and-recovery.mdx, orm/migrations/the-migration-graph.mdx, cli/index.mdx, cli/global-flags.mdx, cli/configuration.mdx, cli/error-reference.mdx, cli/init.mdx, cli/orm-init.mdx, cli/skills.mdx, cli/dev.mdx, cli/git.mdx, cli/db-init.mdx, cli/db-update.mdx, cli/db-migrate.mdx, cli/db-sign.mdx, cli/db-verify.mdx, cli/db-schema.mdx, cli/migration-new.mdx, cli/migration-plan.mdx, cli/migration-ref.mdx, cli/migration-show.mdx, cli/migration-status.mdx + +Monorepo paths below are relative to `wip/prisma-src/`. `cli/src` means `packages/1-framework/3-tooling/cli/src`. + +## Breaks copy-paste + +- `orm/migrations/how-migrations-work.mdx:56-62` (also `generating-a-migration.mdx:74-80,85-86`, `editing-a-migration.mdx:63-66`) — the migration directory contains `start-contract.json`, `end-contract.json` and `*-contract.d.ts`, and `migration.ts` imports `./end-contract` — since 0.17 every contract snapshot lives once in `migrations/snapshots//contract.json` + `contract.d.ts`, and the rendered `migration.ts` imports `../../snapshots//contract.json` and `../../snapshots//contract` (types). The directory holds only `migration.ts`, `ops.json`, `migration.json` (plus `contract.prisma` in the examples). Copying the page's imports into a real migration fails to resolve — evidence: `docs/releases/v0.17.0.md:47`, `examples/prisma-8-demo/migrations/app/20260810T1108_add_post_engagement_counters/migration.ts:2-10`, `packages/1-framework/3-tooling/migration/src/space-layout.ts:55-66` +- `orm/migrations/the-migration-graph.mdx:130` — `migration ref set prod sha256:f9a41d7...` — hashes are bare hex since 0.17 and loaders reject the `sha256:` form; the ref parser only accepts a 64-hex hash, a 6+ hex prefix, a ref name, a migration dir, or `^`. Same stale prefix on every hash the pages print: `how-migrations-work.mdx:119-123`, `generating-a-migration.mdx:47,144-145`, `applying-a-migration.mdx:32`, `rollbacks-and-recovery.mdx:37-38`, `the-migration-graph.mdx:40` — evidence: `docs/releases/v0.17.0.md:45`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:14-24,56-62`, `examples/prisma-8-demo/migrations/app/20260810T1108_add_post_engagement_counters/migration.json` +- `orm/migrations/the-migration-graph.mdx:187-188` — `ref set prod @db` and `ref list` — the commands are `migration ref set` / `migration ref list` (the bare `ref` group was retired in rc.5), and `migration ref set` is offline: `@db` parses to an empty sentinel hash that is not a graph node, so it fails with `MIGRATION.HASH_NOT_IN_GRAPH` rather than reading the database marker — evidence: `docs/releases/v8.0.0-rc.5.md:9`, `cli/src/orm/cli.ts:104-106`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:46-52`, `cli/src/control-api/operations/ref.ts:104-118` +- `cli/orm-init.mdx:38` — `--skip-skills` — the flag was removed in rc.6 together with the skill install it opted out of; `orm init` no longer installs skills at all. The flag set is `--target`, `--authoring`, `--schema-path`, `--write-env`, `--probe-db`, `--strict-probe`, `--skip-install`, `--keep-previous-facade` — evidence: `docs/releases/v8.0.0-rc.6.md:29`, `cli/src/orm/init.ts:7-26` +- `cli/orm-init.mdx:53` — `CLI.INIT_SKILL_INSTALL_FAILED` — retired with the skill install (rc.6); no such code exists in the tree — evidence: `docs/releases/v8.0.0-rc.6.md:29`, grep of `packages/` for `INIT_SKILL_INSTALL_FAILED` returns nothing +- `orm/migrations/editing-a-migration.mdx:75-80` — `sql({ context: createExecutionContext(...) })` — `SqlOptions.rawCodecInferer` is a required field of `sql()`; the runtime passes `stack.adapter.rawCodecInferer`. As written the block does not typecheck, so `node migration.ts` fails before emitting `ops.json` — evidence: `packages/2-sql/4-lanes/sql-builder/src/runtime/sql.ts:11-19`, `packages/3-extensions/postgres/src/runtime/postgres-serverless.ts:136` +- `orm/migrations/the-migration-graph.mdx:117-118` — `git clone https://github.com/prisma/orm` then `cd prisma` — the clone directory is `orm` — evidence: `packages/9-public/@prisma/orm-postgres/package.json` repository url `https://github.com/prisma/orm.git` + +## Misleading + +- `orm/migrations/generating-a-migration.mdx:164-166`, `cli/migration-plan.mdx:11`, `orm/migrations/the-migration-graph.mdx:137` — "without `--from` or a `db` ref, `migration plan` plans from an empty database: a full CREATE-everything migration" — since rc.8 the command refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN` whenever migrations already exist on disk and names three exits (`migration ref set db `, `--from `, or the explicit opt-in `--from @empty`). Only an empty `migrations/app/` still plans from empty silently — evidence: `docs/releases/v8.0.0-rc.8.md:17`, `cli/src/utils/cli-errors.ts:428-475`, `cli/src/orm/migration/plan.ts:206` +- `orm/migrations/how-migrations-work.mdx:20-26`, `orm/migrations/generating-a-migration.mdx:157-161`, `orm/migrations/the-migration-graph.mdx:137`, `cli/index.mdx:70-73,86-92` — the pages present `db migrate --advance-ref db` as the way the `db` ref gets created, and every `db init` / `db update` example passes `--db "$DATABASE_URL"`. In the source `db init` and `db update` advance the `db` ref automatically when run without `--db`; passing `--db` suppresses that unless `--advance-ref` is also given. A user who follows the site's `db init --db ...` then `migration plan` then `db migrate --db ...` loop has no `db` ref, so the second `migration plan` hits `MIGRATION.PLAN_ORIGIN_UNKNOWN` — evidence: `cli/src/control-api/operations/ref-advancement.ts:19-28,116-130`, `skills/prisma-8/references/migrations.md:99-101`, `skills/prisma-8/references/migration-model.md:53-61` +- `orm/migrations/rollbacks-and-recovery.mdx:51,75` — "after a rollback the next `migration plan` fails with `MIGRATION.NO_TARGET` because the planner can no longer infer the latest state" — `migration plan` never infers a latest state: its origin is `--from`, else the `db` ref, else the rc.8 refusal above. `MIGRATION.NO_TARGET` is thrown by `findLeaf`, which `migration new` uses for its default `--from` and `migration ref set` uses for its suggestion text; `migration-plan.ts` does not call it — evidence: `packages/1-framework/3-tooling/migration/src/migration-graph.ts:505-518,544-550`, `cli/src/control-api/operations/migration-new.ts:143`, `cli/src/control-api/operations/ref.ts:115`, grep of `cli/src/control-api/operations/migration-plan.ts` for `findLeaf|findLatestMigration` returns nothing +- `orm/migrations/generating-a-migration.mdx:50,63`, `orm/migrations/applying-a-migration.mdx:34,37,65,68,113,116`, `orm/migrations/rollbacks-and-recovery.mdx:85,88` — the pages reproduce `prisma-cli migrate` / `prisma-cli migration status` hints and explain them as "the binary's own name for itself" — since rc.5 every hint uses the `{bin}` placeholder and the mounted path, so the output reads `prisma db migrate --to ...` / `prisma migration status`. The explanatory sentences are now wrong and the sample output is stale — evidence: `docs/releases/v8.0.0-rc.5.md:9`, `cli/src/orm/migration/status.ts:149`, `cli/src/utils/migrate-failure.ts:13` +- `orm/migrations/applying-a-migration.mdx:111`, `orm/migrations/rollbacks-and-recovery.mdx:83` — `(PN-RUN-3000)` in the failure output — the `PN-*` numeric codes were replaced by dotted codes in 0.17; runner failures surface as `MIGRATION.RUNNER_FAILED`, `MIGRATION.EXECUTION_FAILED`, `MIGRATION.PRECHECK_FAILED` or `MIGRATION.POSTCHECK_FAILED`. `cli/configuration.mdx:146` tells users to branch on the code, so the stale code matters — evidence: `docs/releases/v0.17.0.md:27`, `packages/1-framework/1-core/errors/src/execution.ts:255-275`, grep of `packages/` for `PN-RUN` returns nothing +- `orm/migrations/generating-a-migration.mdx:46` — `from: null` in the plan output — the CLI prints `from: (baseline)` for a null origin — evidence: `cli/src/orm/migration/plan.ts:24-31` +- `orm/migrations/how-migrations-work.mdx:44`, `orm/migrations/applying-a-migration.mdx:26,153` — `✔ Applied 1 migration(s) (3 operation(s)) across 1 contract space(s)` — the summary line is `Applied operation(s) across contract space[s]` (no migration count, no `(s)` on space), or `Database already matches contract ...` when nothing ran — evidence: `cli/src/orm/db/migration-blocks.ts:145-153` +- `orm/migrations/the-migration-graph.mdx:174` — "No baseline. You cannot yet adopt an existing database's history as a starting node without replaying it" — the planner emits an automatic baseline (`null → ref-hash`) plus the delta when the graph is empty and the `db` ref names a stored snapshot, and an explicit `--from @empty` plan at the deployed contract state is the supported retrofit; a baseline is never replayed against a marked database because the runner starts at the marker — evidence: `cli/src/control-api/operations/migration-plan.ts:369,505-545`, `skills/prisma-8/references/migration-model.md:75,139-150` +- `orm/migrations/the-migration-graph.mdx:139-142` — "two reserved tokens (`@contract`, `@db`) work anywhere a command accepts a contract reference" — there is a third, `@empty`, and `@db` is not accepted by the offline commands (`migration ref set`, see above); `migration plan --from` documents `@empty` but not `@db` — evidence: `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:14-24`, `cli/src/orm/migration/plan.ts:206` +- `cli/orm-init.mdx:78` — "the scaffolded `db.ts` reads `DATABASE_URL` from the process environment; your own scripts do not load `.env`, run them with `node --env-file=.env`" — the scaffolded `db.ts` starts with `import 'dotenv/config'`, so any script that imports it loads `.env` — evidence: `cli/src/commands/init/templates/code-templates.ts:324-345` +- `cli/orm-init.mdx:53` — "the `contract:emit` script it adds calls `prisma-cli`" — the script is `prisma contract emit` — evidence: `cli/src/commands/init/hygiene-package-scripts.ts:19` +- `cli/orm-init.mdx:44-49` — the "what it creates" list omits `prisma-next.md`, the quick-reference file the scaffold writes (and replaces on re-run, which is why re-running asks for consent) — evidence: `cli/src/orm/init-scaffold.ts:44-59` +- `cli/migration-plan.mdx:18`, `cli/index.mdx:88`, `cli/migration-new.mdx:16,32`, `orm/migrations/generating-a-migration.mdx:211` — hyphenated `--name add-users-table` / `split-name` / `add-orders-table` — the slug is lower-cased and every non-alphanumeric character becomes `_`, so the directory is `..._add_users_table`. The command runs; the directory name shown to the user differs from the flag — evidence: `packages/1-framework/3-tooling/migration/src/io.ts:456-476` +- `cli/error-reference.mdx:13,19` — "this page lists every code the CLI can emit" — the page carries only the platform and engine namespaces (`AUTH`, `CLI`, `INIT`, `SKILLS`, ...). None of the ORM command codes (`MIGRATION.*`, `CONTRACT.*`, `CONFIG.*`) appear, and the page does not link to `orm/reference/error-reference.mdx` where they belong — evidence: `cli/src/utils/cli-errors.ts` (codes such as `MIGRATION.PLAN_ORIGIN_UNKNOWN`, `MIGRATION.HASH_MISMATCH`, `CONFIG.DB_CONNECTION_REQUIRED`), `packages/1-framework/0-foundation/utils/src/structured-error.ts:90-91` (`docsUrl` base is `.../orm/v8/reference/error-reference`) + +## Missing + +- `--from @empty` and the `MIGRATION.PLAN_ORIGIN_UNKNOWN` refusal — evidence: `cli/src/utils/cli-errors.ts:428-475`, `cli/src/orm/migration/plan.ts:206` — belongs on `cli/migration-plan.mdx` (options and the origin paragraph) and `orm/migrations/generating-a-migration.mdx` +- Automatic `db` ref advancement by `db init` / `db update` when `--db` is omitted, and its suppression when `--db` is passed — evidence: `cli/src/control-api/operations/ref-advancement.ts:19-28` — belongs on `cli/db-init.mdx`, `cli/db-update.mdx`, `cli/migration-ref.mdx`, `orm/migrations/generating-a-migration.mdx#the-db-ref` +- The auto-baseline: on an empty graph with a `db` ref, `migration plan` writes two packages (`_baseline` and the delta) in one run — evidence: `cli/src/control-api/operations/migration-plan.ts:369,505-545` — belongs on `orm/migrations/generating-a-migration.mdx` and `cli/migration-plan.mdx` +- `db update` never plans `data`-class operations, so a change that needs a backfill fails and the user must switch to `migration plan` — evidence: `cli/src/control-api/operations/db-update.ts:17` (`allowedOperationClasses: ['additive', 'widening', 'destructive']`) versus `migrate.ts:283` and `migration-plan.ts:95` which include `'data'` — belongs on `cli/db-update.mdx` and `orm/migrations/rollbacks-and-recovery.mdx:103` +- `migration ref set` refusals: the target must be the `to` hash of an on-disk package (`MIGRATION.HASH_NOT_IN_GRAPH`, `MIGRATION.BUNDLE_NOT_FOUND_FOR_GRAPH_NODE`) and may not be the empty sentinel (`MIGRATION.REF_SET_EMPTY_SENTINEL`) — evidence: `cli/src/control-api/operations/ref.ts:112-124` — belongs on `cli/migration-ref.mdx` +- `migration new` default origin: with no `--from` it takes the single leaf reachable from the empty hash and fails with `MIGRATION.NO_TARGET` (cycles, i.e. after a rollback) or `MIGRATION.AMBIGUOUS_TARGET` (two branch tips); `--from` matches a package's `to` hash by prefix only (not refs or dir names); an identical from/to hash is refused unless `--from` is explicit — evidence: `cli/src/control-api/operations/migration-new.ts:131-155`, `packages/1-framework/3-tooling/migration/src/migration-graph.ts:505-530` — belongs on `cli/migration-new.mdx` and `orm/migrations/rollbacks-and-recovery.mdx` +- The `orm` config keys `migrations.dir` and `formatter` (`indent`, `newline`, used by `contract format`) — evidence: `packages/1-framework/1-core/config/src/config-types.ts:32-37,109-113`, `examples/prisma-8-demo/fixtures/showcase/prisma.config.ts:19-21` — belongs on `cli/configuration.mdx` +- Telemetry opt-out environment variables `PRISMA_NEXT_DISABLE_TELEMETRY=1` and `DO_NOT_TRACK=1` — evidence: `packages/1-framework/3-tooling/cli-telemetry/src` (grep), `skills/prisma-8/references/migrations.md:505-507` — belongs in the `cli/configuration.mdx` environment-variable table (check `cli/telemetry.mdx`, outside this area, for consistency) +- The `node migration.ts` self-emit CLI accepts `--dry-run` and `--config ` — evidence: `cli/src/migration-cli.ts:109-125` — belongs on `orm/migrations/editing-a-migration.mdx` +- The full set of Postgres migration factories on the `Migration` base class (`createIndex`, `dropIndex`, `addForeignKey`, `addUnique`, `addCheckConstraint`, `alterColumnType`, `setDefault`, `dropDefault`, `dropNotNull`, native enum create/drop/add-value, `installExtension`, RLS enable/disable and policy create/drop/rename) plus the free factories `createExtension`, `rawSql`, `foreignKey`, `unique`, `checkExpression`, `fn`, `lit` — evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`, `packages/3-targets/3-targets/postgres/src/exports/migration.ts` — the site shows only `createSchema`, `createTable`, `addColumn`, `setNotNull`, `dataTransform`, `rawSql`; a factory reference belongs beside `orm/migrations/editing-a-migration.mdx` +- `migration status --json` carries `diagnostics[]` (`MIGRATION.MARKER_NOT_IN_HISTORY`, `MIGRATION.MISSING_INVARIANTS`, `CONTRACT.UNREADABLE` verified in `cli/src/orm/migration/status-findings.ts`) with `severity` for CI to branch on; the process exits 0 on warn-level findings — belongs on `cli/migration-status.mdx` +- `orm init` exit codes `4` (scaffold written, install failed) and `5` (installed, contract emit failed) — evidence: `cli/src/orm/init.ts:29-31,114` — belongs on `cli/orm-init.mdx` +- `db migrate` refuses before any DDL with `MIGRATION.MARKER_MISMATCH` when the marker is not a graph node, and with `MIGRATION.PATH_UNREACHABLE` when no path exists — evidence: `cli/src/utils/cli-errors.ts` (both codes), `skills/prisma-8/references/migration-review.md:257-262` — `applying-a-migration.mdx:124` describes the behaviour without the codes; belongs on `cli/db-migrate.mdx` + +## Unverified + +- `cli/global-flags.mdx` (whole page), `cli/init.mdx` (whole page), `cli/skills.mdx` (allowlist including `@prisma/composer`, target directories, the staleness check and its suppression list), `cli/configuration.mdx:13,30,94` (`definePrismaConfig` from `prisma/config`; `defineConfig` from `@prisma/cli-engine` as an alias; the `agents` list) — all implemented in `@prisma/cli-engine` / the `prisma-cli` repo, which is not in the tree (`node_modules/@prisma/cli-engine` has no `dist`). What I could see: the monorepo scaffold imports `definePrismaConfig` from `@prisma/cli-engine` (`cli/src/commands/init/templates/code-templates.ts:304`) and the fixture imports `defineConfig` from `@prisma/cli-engine` (`examples/prisma-8-demo/fixtures/showcase/prisma.config.ts:1`), so both names exist there; `skills/` ship inside `@prisma/orm-postgres`, `@prisma/orm-sqlite`, `@prisma/orm-mongo` (`files` in each `package.json`) +- `cli/dev.mdx`, `cli/git.mdx` — platform commands; not in the monorepo +- `cli/db-migrate.mdx:9`, `orm/migrations/applying-a-migration.mdx:150` — "extensions alphabetically, then the app" — matches the command's own help (`cli/src/orm/migrate.ts:203-206`), but `packages/1-framework/3-tooling/migration/src/plan-all-spaces.ts:66-70` sorts every space id alphabetically, where `app` sorts before `pgvector`; I did not trace the apply-order code far enough to say which is right +- `orm/migrations/the-migration-graph.mdx:120` — `migration graph --config fixtures/showcase/prisma.config.ts --legend` from `examples/prisma-8-demo` — `migrations.dir` in a config is resolved against the working directory, not the config file (`cli/src/orm/migration/paths.ts:11-13`, comment in `cli/src/orm/define-command.ts`), which would point at the demo's own `migrations/` rather than the fixture's; but the fixture's own header comment gives the same invocation, so I could not tell whether it works +- `orm/migrations/editing-a-migration.mdx:95-102` — `db.public.user.update({ displayName: 'Anonymous' }).where(...)` — I verified the `sql()` builder root and the `select(...).where(...).limit(1)` check shape against `data-transform.ts:84-95`, but did not verify the mutation builder's `update(values).where(...)` signature (query-builder area) + +## Skill vs site + +- Transaction scope — `skills/prisma-8/references/migrations.md:48` says each Postgres migration runs in its own `BEGIN ... COMMIT`; `applying-a-migration.mdx:120,146` says the whole `db migrate` run is one transaction. The site matches the source: `execute()` issues one `BEGIN`, loops every space's plan (the concatenated path of edges), then one `COMMIT`/`ROLLBACK` — `packages/3-targets/3-targets/postgres/src/core/migrations/runner.ts:176-215,684-696` +- Destructive consent on `db update` — the skill (`migrations.md:33,146,470`) says pass `-y` to auto-accept; the site (`cli/db-update.mdx:30-36`) says type the database name or pass `--confirm `. The site matches the source: `cli/src/orm/db/update.ts:118-124,218-224`, `cli/src/orm/db/consent.ts`; the engine's `CLI.CONSENT_REQUIRED` entry on `cli/error-reference.mdx:147` also says `--yes` does not grant consent +- Error codes — the skill still uses `PN-MIG-2001`, `PN-MIG-2002/2003/2005`, `PN-RUN-3001`, `PN-RUN-3002` (`migrations.md:21,69-75`); the site uses `PN-RUN-3000`. Both are stale; the source has `MIGRATION.UNFILLED_PLACEHOLDER`, `MIGRATION.DATA_TRANSFORM_CONTRACT_MISMATCH`, `CONTRACT.MARKER_MISSING` ("Database not signed"), `CONTRACT.MARKER_MISMATCH` ("Hash mismatch"), `MIGRATION.RUNNER_FAILED` — `packages/1-framework/1-core/errors/src/migration.ts:19-20`, `.../execution.ts:17,34,267`, `docs/releases/v0.17.0.md:27` +- Factory call shape — the skill renders `addColumn('public', 'user', { name, typeSql, defaultSql, nullable })` and `setNotNull('public', 'user', 'name')` as free functions (`migrations.md:231-235,254-270`); the site renders `this.addColumn({ schema, table, column: col(...) })` and `this.setNotNull({ schema, table, column })`. The site matches the source and the rc.9 examples: `postgres-migration.ts:231,364`, `examples/prisma-8-demo/migrations/app/20260810T1108_add_post_engagement_counters/migration.ts:17-21` +- Contract snapshot imports — the skill imports `../../snapshots//contract.json` (`migrations.md:225,253`); the site imports `./end-contract.json`. The skill matches the source (see the first Breaks item) +- `migration show` with no argument — the skill runs `pnpm prisma migration show` bare (`migrations.md:189`); the site says `` is required (`cli/migration-show.mdx:16,23`). The site matches the source: the positional is `positional.string`, not optional — `cli/src/orm/migration/show.ts:3-6` +- `--from` grammar on `migration plan` — the skill lists `@contract | @db | @empty` (`migration-model.md:67`); the site lists neither on `cli/migration-plan.mdx:26` and only `^` on `generating-a-migration.mdx:153`. The parser accepts all three tokens (`contract-ref.ts:14-24`); the command's own brief names only `@empty` (`plan.ts:206`) diff --git a/docs/orm-docs-audit/audit/orm-client.md b/docs/orm-docs-audit/audit/orm-client.md new file mode 100644 index 00000000000..177db445a00 --- /dev/null +++ b/docs/orm-docs-audit/audit/orm-client.md @@ -0,0 +1,63 @@ +# Audit: orm-client + +Pages read: orm/index.mdx, orm/core-concepts.mdx, orm/fundamentals/reading-data.mdx, orm/fundamentals/writing-data.mdx, orm/fundamentals/relations-and-joins.mdx, orm/fundamentals/advanced-queries.mdx, orm/fundamentals/transactions.mdx, orm/reference/index.mdx, orm/reference/orm-client.mdx, orm/reference/transactions-and-runtime.mdx, orm/reference/error-reference.mdx + +## Breaks copy-paste + +- `orm/fundamentals/advanced-queries.mdx:39` (10 occurrences on this page: 39, 61, 75, 101, 123, 138, 177, 200, 218, 230), `orm/core-concepts.mdx:87`, `orm/fundamentals/reading-data.mdx:192`, `orm/fundamentals/relations-and-joins.mdx:73`, `orm/reference/transactions-and-runtime.mdx:96` (and 429-432, 741, 770) — `const rows = await db.runtime().execute(plan)` / `tx.execute(plan)` / `runtime.execute(plan)` used to read rows — since rc.2, `execute(plan)` returns `Promise<{ affectedRows }>` and rows come from `query(plan)`, which returns the `AsyncIterableResult`. Every row-reading example must call `.query(plan)`; only non-returning inserts, updates, and deletes stay on `.execute(plan)` (so `orm/fundamentals/transactions.mdx:60` is correct as written). `transactions-and-runtime.mdx:429-432` also calls `.toArray()` on an `execute` result, which is a stats promise — evidence: `packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts:23-26`, `packages/2-sql/5-runtime/src/sql-runtime.ts:767-790`, `packages/1-framework/1-core/framework-components/src/execution/runtime-middleware.ts:352-358`, `docs/releases/v8.0.0-rc.2.md:72` +- `orm/reference/transactions-and-runtime.mdx:199`, `:279-301` — the MongoDB client exposes `execute()` and `db.execute(plan)` runs a pipeline plan — the row-executing `db.execute` facade method was removed in rc.2; the client exposes `orm`, `query`, `raw`, `contract`, `enums`, `context`, `connect()`, `runtime()`, `close()`. Rows come from `(await db.runtime()).query(plan)` — evidence: `packages/3-extensions/mongo/src/runtime/mongo.ts:28-40, 189-196`, `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-100`, `docs/releases/v8.0.0-rc.2.md:72` +- `orm/fundamentals/advanced-queries.mdx:230` — "`(await db.runtime()).execute(plan)` on MongoDB" — same rename: `(await db.runtime()).query(plan)` for rows — evidence: `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-100` +- `orm/reference/transactions-and-runtime.mdx:581`, `:609-611`, `:662`, `:665-710` — `ps.execute(runtime, { label })` returns rows (`Promise`) — a prepared statement built from a row-returning plan is a `PreparedStatement` whose method is `query(target, params, options?)` returning `AsyncIterableResult`; `execute(target, params)` exists only on `PreparedExecution` (a plan terminated with `.affectedCount()`) and resolves `SqlStatementStats` — evidence: `packages/2-sql/5-runtime/src/prepared/types.ts:55-105`, `docs/releases/v8.0.0-rc.2.md:72` ("Prepared row consumption moves ... to `prepared.query(target, params)`") +- `orm/reference/transactions-and-runtime.mdx:459`, `:467` — `withTransaction`'s `tx` surface is "`execute` (and `executePrepared`) only" — the transaction context is a `RuntimeScope`: `query(plan)` for rows and `execute(plan)` for stats; there is no `executePrepared` method (prepared hooks are symbol-keyed and reached through `prepared.query(tx, params)`) — evidence: `packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts:23-26`, `packages/2-sql/5-runtime/src/sql-runtime.ts:137-141, 786-800` +- `orm/reference/transactions-and-runtime.mdx:653-662` — `await db.prepare(...)` followed by `const runtime = await db.connect()` — `db.prepare` calls `getRuntime()`, which starts the driver connection in the background when a `url` was given; a later `connect()` then throws `DRIVER.ALREADY_CONNECTED` ("Postgres client already connected"). Use `db.runtime()` after any query, `prepare`, or ORM call, and reserve `connect()` for the very first action — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:194-199, 245-250, 297-303, 330-339` +- `orm/fundamentals/writing-data.mdx:182-195` — PostgreSQL `upsert({ create, update })` with no `conflictOn`, and the prose "the record is matched on the model's unique fields (here `email`)" — when `conflictOn` is omitted the conflict target falls back to the table's primary key columns, not the unique fields. Because `create` does not supply `id` (it is generated), the statement never conflicts and either inserts a second row or fails on the `email` unique constraint. Pass `conflictOn: { email: ... }` — evidence: `packages/3-extensions/sql-orm-client/src/collection-contract.ts:511-530`, `packages/3-extensions/sql-orm-client/src/collection.ts:1732-1775` + +## Misleading + +- `orm/fundamentals/reading-data.mdx:280-309`, `:362` (and `orm/index.mdx:29` "streaming results") — `for await` over `.all()` "streams" rows from the database with a "steady, flat memory footprint" for millions of rows, and leaving the loop early means "unprocessed records are never buffered" — the `postgres()` facade constructs its driver with `cursor: { disabled: true }`, which the driver documents as buffered execution: the whole result is fetched before iteration begins. `for await` only changes how the already-buffered rows are handed to your code. Cursor streaming exists in the driver (`batchSize`) and is exposed by the serverless entry point only — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`, `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:39-43, 50-53, 95-101`, `packages/3-extensions/postgres/src/runtime/postgres-serverless.ts:28-42` +- `orm/fundamentals/advanced-queries.mdx:129` — "Prisma 8 does not run standalone raw SQL statements: every query goes through the typed builder" — a whole-query raw lane exists: `db.raw.sql\`SELECT ...\`.returnsRow({ col: 'pg/text@1' }).build()` for typed rows and `.affectedCount()` for mutations, executed through `runtime.query` / `runtime.execute`. `orm/core-concepts.mdx:106` describes the PostgreSQL raw escape hatch only as fragments spliced into builder queries — evidence: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:117-170`, `packages/2-sql/4-lanes/sql-builder/src/runtime/raw-lane.ts:24-33`, `packages/3-extensions/postgres/src/runtime/postgres.ts:61, 284`, `docs/releases/v8.0.0-rc.2.md:120` +- `orm/fundamentals/relations-and-joins.mdx:64-74`, `:217` — "The mirror field on the other model (`profile Profile?` on `User`) is not supported in the contract yet", so users are sent to the SQL builder — a singular back-relation is supported; emit only rejects it when the foreign key is not unique (`PSL_NON_UNIQUE_BACKRELATION`), and `userCollection.include('profile')` type-checks as a to-one include — evidence: `packages/2-sql/2-authoring/contract-psl/src/psl-relation-resolution.ts:448`, `docs/releases/v0.16.0.md:23-40`, `packages/3-extensions/sql-orm-client/test/include-cardinality.test-d.ts:36`, `packages/3-extensions/sql-orm-client/src/collection-contract.ts:640` +- `orm/fundamentals/relations-and-joins.mdx:216` — implicit many-to-many (`through` junction) "not supported by `.include(...)` yet" — the ORM resolves `relation.through` into an include descriptor and the demo app includes the N:M `Post.tags` relation with a refinement callback; nested `create`/`connect`/`disconnect` through the junction also work (and `orm/reference/orm-client.mdx:1088-1098` already documents `disconnect` through the junction, contradicting this page) — evidence: `packages/3-extensions/sql-orm-client/src/collection-contract.ts:356-379`, `packages/3-extensions/sql-orm-client/src/mutation-executor.ts:74, 836-926`, `examples/prisma-8-demo/src/orm-client/get-post-tags.ts:17`, `examples/prisma-8-demo/src/orm-client/create-post-with-tags.ts:30`, `docs/releases/v8.0.0-rc.1.md:64` +- `orm/reference/orm-client.mdx:478`, `:513` — text-backed enum columns sort in declaration order under `orderBy` — changed in rc.9: `ORDER BY` and `DISTINCT ON` on text-backed enums follow the stored values; only native PostgreSQL enums keep database ordering — evidence: `docs/releases/v8.0.0-rc.9.md:7` +- `orm/fundamentals/advanced-queries.mdx:104-111` — "PostgreSQL returns counts as strings; convert with `Number(row.posts)`" — `fns.count()` resolves through the target's `count` aggregate descriptor to a `number` (the int8-as-number codec); `countBigInt()` is the `bigint` form. Site sample output `posts: '2'` is stale — evidence: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:159-172`, `packages/2-sql/4-lanes/sql-builder/src/runtime/functions.ts:242-253`, `docs/releases/v8.0.0-rc.2.md:32-53` +- `orm/reference/orm-client.mdx:384`, `:393`, `:465-467` — `min()`/`max()` "are typed for numeric fields (`NumericFieldNames`)" — the reducer field set is now derived from the aggregate descriptors: `min`/`max` accept numeric and textual columns and the date/time string and temporal codecs. The plain `pg/timestamptz@1` (`DateTime` decoded to `Date`) column is still absent from that list, so the `min('createdAt')` compile error the page describes is right for that codec, but the "numeric-only" explanation is not — evidence: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:126-152`, `packages/3-extensions/sql-orm-client/src/types.ts:663-677` +- `orm/reference/orm-client.mdx:726` — "`all()` takes no arguments" — `all(configure?: (meta: MetaBuilder<'read'>) => void)` accepts a callback for query annotations (for example `meta.annotate(cacheAnnotation({ ttl }))`); `first`, `aggregate`, and the write terminals take the same optional trailing `configure` argument — evidence: `packages/3-extensions/sql-orm-client/src/collection.ts:1038, 1060-1083, 1235-1245, 1867-1872`, `examples/prisma-8-demo/src/orm-client/get-users-cached.ts:7-21` +- `orm/reference/transactions-and-runtime.mdx:82`, `:128`, `:155`, `:234`, `:310`, `:325` — closed and double-connect failures are plain `Error: Postgres client is closed` / `Error: Mongo client already connected` — they are structured envelopes with codes `DRIVER.NOT_CONNECTED` and `DRIVER.ALREADY_CONNECTED` (plus `why`/`fix`), matchable with `isStructuredError` per the site's own error-reference intro; and `DRIVER.ALREADY_CONNECTED` is raised by PostgreSQL too, not only MongoDB as `:233` implies — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:224-228, 290-303`, `packages/3-extensions/mongo/src/runtime/mongo.ts:149, 199-202` +- `orm/reference/transactions-and-runtime.mdx:48` — the PostgreSQL client "exposes `.orm`, `.sql`, `.enums`, `connect()`, `runtime()`, `transaction()`, `prepare()`, and `close()`" — it also exposes `.raw` (the raw lane), `.nativeEnums`, `.context`, `.contract`, and `.stack`; the options table (`:35-42`) omits `verifyMarker: 'onFirstUse' | false` and `binding` — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:56-89`, `packages/2-sql/5-runtime/src/runtime-spi.ts:42` +- `orm/reference/transactions-and-runtime.mdx:185-199` — MongoDB options table omits `mode: 'strict' | 'permissive'` and `binding`; the client also exposes `.context` and `.contract` — evidence: `packages/3-extensions/mongo/src/runtime/mongo.ts:28-56, 142` +- `orm/reference/transactions-and-runtime.mdx:359`, `:369` — `tx` exposes `orm`, `sql`, `execute`, `enums` — it also exposes `query` (rows) and `nativeEnums` — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:47-54` +- `orm/fundamentals/reading-data.mdx:114`, `:354` — `.first()` "on PostgreSQL ... fetches at most one row", implying MongoDB does not — the MongoDB collection's `first()` also applies `limit: 1` — evidence: `packages/2-mongo-family/5-query-builders/orm/src/collection.ts:341-343` +- `orm/reference/orm-client.mdx:644-651` — `distinctOn()` Remarks omit that it requires the contract capability `postgres.distinctOn` and throws `... requires capability postgres.distinctOn` without it — evidence: `packages/3-extensions/sql-orm-client/src/collection.ts:957`, `packages/3-extensions/sql-orm-client/src/collection-contract.ts:598-604` +- `orm/reference/error-reference.mdx:9-13`, `:23` (and every ADR link in entries) — links and the generator note point at `github.com/prisma/prisma`, while the rc.9 source and its release notes live in `github.com/prisma/orm` (the site's own `orm/index.mdx:110` says so). The 292 code entries otherwise match the rc.9 source word for word — evidence: `docs/releases/v8.0.0-rc.9.md:7-9` (PR links to `github.com/prisma/orm`), `docs/reference/error-reference.md` (identical body after the repo/name substitutions) + +## Missing + +- Lossless aggregates `countBigInt()`, `sumBigInt(field)`, `avgDecimal(field)` (as `aggregate()` selectors, `include` reducers, and SQL-builder `fns`), and the rule that `count()` / integer `sum()` throw `RUNTIME.DECODE_FAILED` outside the safe-integer range instead of rounding — evidence: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:159-213`, `docs/releases/v8.0.0-rc.2.md:32-53`, `skills/prisma-8/references/queries-postgres.md:233-251` — belongs in `orm/reference/orm-client.mdx` (`aggregate()` and "Refinements, reducers, and combine") and `orm/fundamentals/reading-data.mdx` "Count records" +- `runtime.query(plan)` vs `runtime.execute(plan)` split (rows vs `{ affectedRows }`), and `RuntimeStatementStats` — evidence: `packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts:23-26`, `docs/releases/v8.0.0-rc.2.md:72` — belongs in `orm/reference/transactions-and-runtime.mdx` "Execution options and results" and `orm/fundamentals/advanced-queries.mdx` "Build and run a plan" +- Whole-query raw SQL: `db.raw.sql\`...\`.returnsRow(spec)` / `.affectedCount()`, `RUNTIME.RAW_COLUMN_MISSING`-style spec mismatches — evidence: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:117-170`, `docs/releases/v8.0.0-rc.2.md:120` — belongs in `orm/fundamentals/advanced-queries.mdx` "Raw SQL fragments" and the `orm/core-concepts.mdx:103-108` table +- `AsyncIterableResult.first()` and `.firstOrThrow()` (throws `RUNTIME.NO_ROWS`) on any read result — evidence: `packages/1-framework/1-core/framework-components/src/execution/async-iterable-result.ts:66-80` — belongs in `orm/reference/orm-client.mdx` "Result types" +- Query annotations: the optional `configure(meta)` callback on every terminal and `meta.annotate(...)`, which is how the built-in cache middleware is opted into per query — evidence: `packages/3-extensions/sql-orm-client/src/collection.ts:1030-1060`, `examples/prisma-8-demo/src/orm-client/get-users-cached.ts` — belongs in `orm/reference/orm-client.mdx` read terminals +- `verifyMarker: 'onFirstUse' | false` on `postgres()`: the startup contract-vs-signature check that `orm/core-concepts.mdx:67` describes without saying how to turn it on or off (it reports `CONTRACT.MARKER_MISSING` / `CONTRACT.MARKER_MISMATCH` as warnings) — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:79`, `packages/2-sql/5-runtime/src/runtime-spi.ts:42`, `packages/2-sql/5-runtime/src/sql-runtime.ts:905-925` — belongs in `orm/reference/transactions-and-runtime.mdx` `postgres(options)` +- The flat accessor form `db.orm.User` / `db.sql.user` for single-namespace contracts (the site only ever shows `db.orm.public.User`); the namespace coordinate is required only when a bare name repeats across namespaces — evidence: `packages/3-extensions/sql-orm-client/src/orm.ts:71-121`, `skills/prisma-8/references/queries.md:39-48` — belongs in `orm/reference/orm-client.mdx` "Setting up the client" +- `db.nativeEnums` (PostgreSQL native enum members at runtime) next to `db.enums` — evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:53, 60`, `docs/releases/v0.15.0.md:75` — belongs in `orm/reference/transactions-and-runtime.mdx` return-type row +- MongoDB `mode: 'strict' | 'permissive'` client option — evidence: `packages/3-extensions/mongo/src/runtime/mongo.ts:44, 142` — belongs in `orm/reference/transactions-and-runtime.mdx` `mongo(options)` +- MongoDB filter classes beyond `MongoFieldFilter`/`MongoOrExpr`: `MongoAndExpr.of([...])`, `MongoNotExpr`, `MongoExistsExpr.exists(field)` / `.notExists(field)` — evidence: `packages/2-mongo-family/4-query/query-ast/src/filter-expressions.ts:68-160`, `packages/2-mongo-family/4-query/query-ast/src/exports/execution.ts:33-37` — belongs in `orm/reference/orm-client.mdx` "Combinators" / "MongoFieldFilter" +- The SQLite facade's lifecycle (`sqlite({ contractJson, path })`, `db.connect({ path })`, `db.transaction`) has no entry on the transactions-and-runtime reference or the transactions fundamentals page (the "SQLite is planned" wording is a known item; this is the missing reference content) — evidence: `packages/9-public/@prisma/orm-sqlite/package.json`, `skills/prisma-8/references/runtime.md:285-296` — belongs in `orm/reference/transactions-and-runtime.mdx` + +## Unverified + +- `orm/reference/orm-client.mdx:334`, `:370`, `:1295` — a looked-up sub-document's `_id` and the upsert update-path `_id` "come back as a raw driver `ObjectId`" — 0.15 changed reshaping reads to decode projected `_id`s and 0.17 made Mongo write results decode through codecs; I did not trace the `$lookup` and `findOneAndUpdate` decode paths far enough to confirm which shape rc.9 returns — checked `docs/releases/v0.15.0.md:103`, `docs/releases/v0.17.0.md:85`, `packages/2-mongo-family/5-query-builders/orm/src/collection.ts:254-320, 535-600` +- `orm/reference/orm-client.mdx:871` — on PostgreSQL, `update()` / `delete()` bypassed without `where()` "narrow to a single row by identity" — the update path does call `#findFirstMatchingRowIdentityWhere()`; I did not read the delete path — checked `packages/3-extensions/sql-orm-client/src/collection.ts:1895-1955` +- `orm/reference/transactions-and-runtime.mdx:724`, `:731` — `scope` documented as a user-settable `RuntimeExecuteOptions` field — the type declares it, but every runtime call site overwrites it (`scope: 'connection'` / `'transaction'`), so a caller-supplied value may have no effect — checked `packages/1-framework/1-core/framework-components/src/execution/runtime-middleware.ts:335-338`, `packages/2-sql/5-runtime/src/sql-runtime.ts:767-880` + +## Skill vs site + +- `and` / `or` / `not` import path — skill (`queries.md:141`, `queries-postgres.md:75, 86, 251`) says the combinators are internal-only and must come from `@internal/sql-orm-client`; site (`orm/fundamentals/reading-data.mdx:167-170`, `orm/reference/orm-client.mdx:1635, 1644`) imports them from `@prisma/orm-postgres/orm-client`. Site matches the source: `packages/9-public/@prisma/orm-postgres/package.json` exports `./orm-client`, and `packages/9-public/@prisma/orm-postgres/test/facade-tarball.test.ts:58, 171` verifies it re-exports `orm`, `Collection`, and the filters +- `.count()` as a collection terminal — skill (`queries-postgres.md:30`) lists `.count()` beside `.all()` / `.first()`; site (`orm/fundamentals/reading-data.mdx:278`) says there is no `.count()` on the chain. Site matches the source: `packages/3-extensions/sql-orm-client/src/collection.ts` has no `count` method; `count()` exists only as an `include` reducer (`:259-300`) and inside `aggregate()` +- SQL-builder `insert` input — skill (`queries-postgres.md:298-299`) writes `db.sql.user.insert({ email })`; site (`orm/fundamentals/advanced-queries.mdx:118-119`) passes an array. Site matches the source: `packages/2-sql/4-lanes/sql-builder/src/runtime/table-proxy-impl.ts:207` (`insert(rows: ReadonlyArray<...>)`) +- Rows from `runtime.execute(plan)` — both the skill (`queries-postgres.md:289, 302, 333, 355`) and the site use `execute` for row reads; the source says `query` (see Breaks copy-paste, first bullet). Neither matches rc.9 +- N:M `.include()` and nested N:M mutations — skill (`queries.md:139-140`) says both are unsupported and that `mutation-executor.ts` throws; site is split (relations page says implicit N:M include is unsupported, orm-client reference shows `disconnect` through the junction). Source supports both (`mutation-executor.ts:836-926`, `examples/prisma-8-demo/src/orm-client/get-post-tags.ts`); the skill's `'N:M nested mutations are not supported yet'` string no longer exists in `packages/3-extensions/sql-orm-client/src/` +- Streaming — skill (`queries.md:146`) says there is no streaming surface; site (`reading-data.mdx:280-309`) says `for await` streams. Source: `AsyncIterableResult` is an async iterable, but the `postgres()` facade disables driver cursors, so the skill is closer to the truth about memory behaviour (`packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`) +- Error codes — skill (`debug.md:12, 78-110`) routes on `PN-CLI-*` / `PN-MIG-*` / `PN-RUN-*` codes; site (`orm/reference/error-reference.mdx`) uses the dotted `NAMESPACE.SUBCODE` scheme. Site matches the source: codes were renamed at 0.16 and `docs/reference/error-reference.md` lists only dotted codes +- Prepared statements — skill (`debug.md:127`) says you "cannot pre-prepare and re-execute a statement by name" and points to TypedSQL (which `queries.md:144` says does not exist); site documents `runtime.prepare` / `db.prepare` (`transactions-and-runtime.mdx:568-663`). Site matches the source (`packages/2-sql/5-runtime/src/sql-runtime.ts:110, 549`), apart from the `query` vs `execute` method name above +- `.first()` on MongoDB — skill (`queries-mongo.md:63`) and site (`orm-client.mdx:775`) agree there is no filter argument; source agrees (`packages/2-mongo-family/5-query-builders/orm/src/collection.ts:110, 341`) diff --git a/docs/orm-docs-audit/audit/start-guides.md b/docs/orm-docs-audit/audit/start-guides.md new file mode 100644 index 00000000000..7c3dfa0291b --- /dev/null +++ b/docs/orm-docs-audit/audit/start-guides.md @@ -0,0 +1,60 @@ +# Audit: start-guides + +Pages read: `(index)/index.mdx`, `(index)/getting-started.mdx`, `(index)/prisma-orm/index.mdx`, `(index)/prisma-orm/create-prisma.mdx`, `(index)/prisma-orm/quickstart/postgresql.mdx`, `(index)/prisma-orm/quickstart/mongodb.mdx`, `(index)/prisma-orm/add-to-existing-project/postgresql.mdx`, `(index)/prisma-orm/add-to-existing-project/mongodb.mdx`, `(index)/prisma-postgres/quickstart/prisma-orm.mdx`, `guides/index.mdx`, `guides/upgrade-prisma-orm/postgresql.mdx`, `guides/upgrade-prisma-orm/mongodb.mdx`, `guides/switch-to-prisma-orm/from-drizzle.mdx`, `guides/switch-to-prisma-orm/from-mongoose.mdx`, `guides/switch-to-prisma-orm/from-sql-orms.mdx`, `guides/database/schema-changes.mdx`, `guides/database/data-migration.mdx`, `guides/database/multiple-databases.mdx`. + +Monorepo paths below are relative to `wip/prisma-src/` unless they start with `wip/create-prisma-src/`. + +## Breaks copy-paste + +- `(index)/prisma-orm/add-to-existing-project/postgresql.mdx:46` (same on `add-to-existing-project/mongodb.mdx:48`) — tells the user to "keep the default schema path, `prisma/contract.prisma`", and every later step assumes that directory: `contract infer --output ./prisma/contract.prisma` (line 63), `prisma/contract.json` and `prisma/contract.d.ts` (line 80), `import { db } from "./prisma/db"` (lines 103, 137; mongodb page lines 109, 138) — `orm init` defaults to `src/prisma/contract.prisma` and writes `db.ts` next to it, so a user who accepts the default gets `src/prisma/`, `contract infer --output ./prisma/contract.prisma` writes a file `prisma.config.ts` never reads, `contract emit` emits the untouched starter contract, and `./prisma/db` does not exist. The site's own agent prompt at `(index)/index.mdx:96` says `src/prisma/` — evidence: `packages/1-framework/1-core/config/src/config-types.ts:45` (`DEFAULT_CONTRACT_SOURCE_DIR = 'src/prisma'`), `packages/1-framework/3-tooling/cli/src/commands/init/templates/code-templates.ts:63-67`, `packages/1-framework/3-tooling/cli/src/orm/init-scaffold.ts:188` +- `(index)/prisma-orm/create-prisma.mdx:94` — "plan and apply the migration with `npx prisma@latest migration plan` and `npx prisma@latest migrate`" — there is no top-level `migrate` command; the apply command is `db migrate`, and the generated `migrate` script runs `prisma db migrate` — evidence: `packages/1-framework/3-tooling/cli/src/orm/cli.ts:97-121` (command tree), `wip/create-prisma-src/src/tasks/install.ts:53` +- `(index)/prisma-orm/add-to-existing-project/postgresql.mdx:148` — `const rows = await db.runtime().execute(plan); console.log(rows);` for a `select` plan — `execute` returns `SqlStatementStats` (`{ affectedRows }`), not rows; rows come from `db.runtime().query(plan)` — evidence: `packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts:23-26`, `packages/2-sql/4-lanes/relational-core/src/ast/driver-types.ts:24-26`, `examples/prisma-8-demo/src/queries/get-users.ts:5` +- `(index)/prisma-orm/add-to-existing-project/mongodb.mdx:148` — `const rows = await runtime.execute(plan)` for a `from("users").match(...).project(...)` pipeline — `MongoRuntime.execute` returns statement statistics and throws `RUNTIME.MONGO_STATISTICS_UNSUPPORTED` for a command with no count field (an aggregate/find); reads go through `runtime.query(plan)` — evidence: `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-100, 282-289`, `examples/mongo-demo/src/server.ts:75` +- `guides/upgrade-prisma-orm/mongodb.mdx:266` (repeated at 293, 345, 392, 393) — `await db.execute(plan).toArray()` — the Mongo client has no `execute` method; the surface is `orm`, `query`, `raw`, `connect`, `runtime`, `close`. A plan runs as `(await db.runtime()).query(plan).toArray()` — evidence: `packages/3-extensions/mongo/src/runtime/mongo.ts:28-41`, `examples/mongo-demo/scripts/cache-demo.ts:77` + +## Misleading + +- `(index)/prisma-orm/add-to-existing-project/postgresql.mdx:41` (same on `add-to-existing-project/mongodb.mdx:43`) — "`orm init` also adds `prisma-next.md` and project-level Prisma 8 skills for Cursor, Claude Code, Codex, and Windsurf" — `orm init` writes `prisma-next.md` but installs no skills; its only skill work is deleting retired skill directories, and its own next-steps output says to run `prisma init` for skills — evidence: `packages/1-framework/3-tooling/cli/src/commands/init/skill-sources.ts:1-5`, `packages/1-framework/3-tooling/cli/src/commands/init/output.ts:106-108` +- `(index)/prisma-orm/add-to-existing-project/postgresql.mdx:43-46, 50` (same on `mongodb.mdx:45-48, 52`) — lists the prompts as "choose PSL" and "keep the default schema path", then says "Update `.env`" — `orm init` also asks "Also write a .env file from .env.example?" (default No); by default it writes `.env.example` only, so there may be no `.env` to update. `--write-env` skips the prompt — evidence: `packages/1-framework/3-tooling/cli/src/orm/init-inputs.ts:229-233`, `packages/1-framework/3-tooling/cli/src/orm/init-scaffold.ts:199, 211-218` +- `(index)/prisma-orm/create-prisma.mdx:86` — "Review `DATABASE_URL` in `.env`, then initialize the database" — for PostgreSQL the scaffold writes no `.env` (it only does for MongoDB), calls `orm init` without `--write-env`, and the generated `prisma.config.ts` has no `dotenv` import, so `DATABASE_URL` must be in the shell environment. `quickstart/postgresql.mdx:43` says this correctly — evidence: `wip/create-prisma-src/src/tasks/prisma-setup/project-files.ts:17-29`, `wip/create-prisma-src/src/tasks/prisma-setup/commands.ts:47-59`, `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs:18-37`, `wip/create-prisma-src/templates/create/_shared/README.md.hbs:71` +- `(index)/prisma-orm/quickstart/mongodb.mdx:27` and `add-to-existing-project/mongodb.mdx:19` — "Prisma 8 needs a MongoDB replica set" — nothing in the Mongo runtime or migration runner opens a session or transaction (the client has no `transaction` method and the runner deliberately avoids transactions); `orm init`'s `.env.example` says a standalone `mongod` works for first-run queries and a replica set is only needed for transactions and change streams. Only the scaffold's connection string (`replicaSet=rs0&directConnection=true`) demands one — evidence: `packages/1-framework/3-tooling/cli/src/commands/init/templates/env.ts:43-48`, `packages/3-mongo-target/1-mongo-target/src/core/control-target.ts:84-86`, `packages/3-extensions/mongo/src/runtime/mongo.ts:28-41`, `wip/create-prisma-src/src/tasks/prisma-setup/project-files.ts:25` +- `(index)/prisma-orm/create-prisma.mdx:9` (and every quickstart that says "installs Prisma 8") — create-prisma 0.11.7 pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` while the current release is rc.9, so a fresh scaffold does not get rc.9 behaviour the site documents (for example the rc.9 Mongo attribute rejection and index argument format) — evidence: `wip/create-prisma-src/src/constants/dependencies.ts:8-10`, `packages/9-public/@prisma/orm-postgres/package.json` (version `8.0.0-rc.9`), `docs/releases/v8.0.0-rc.9.md:9-25` +- `(index)/prisma-orm/create-prisma.mdx:57` — `--force` "Allows scaffolding into a non-empty directory" — it also overwrites the generated Prisma config, contract, and `db.ts`, and refuses when the target has a non-empty `migrations/` directory — evidence: `wip/create-prisma-src/src/index.ts:67-70`, `wip/create-prisma-src/src/commands/create-context.ts:181-192` +- `(index)/prisma-orm/create-prisma.mdx:35, 54, 56` — describes the deploy prompt and `--yes` without saying the defaults differ: interactively the prompt defaults to Yes, `--yes` answers No, and `--json` (not on the page) deploys unless `--no-deploy` is passed — evidence: `wip/create-prisma-src/src/tasks/prisma-setup/context.ts:112-121, 163-166`, `wip/create-prisma-src/src/index.ts:73-76` +- `(index)/prisma-orm/create-prisma.mdx:79` — the Deno command omits `--minimum-dependency-age=0`; create-prisma's README says Deno 2.9 blocks packages published in the last 24 hours, so a fresh release resolves to an older cached version without it — evidence: `wip/create-prisma-src/README.md:46-52` +- `(index)/getting-started.mdx:36`, `(index)/index.mdx:111`, `(index)/prisma-orm/index.mdx:43` — "Valid --template values: next, hono, nuxt, astro, nest, svelte, tanstack-start, elysia" omits `minimal`, which is also the default — evidence: `wip/create-prisma-src/src/types.ts:7-17`, `wip/create-prisma-src/src/commands/create-context.ts:13` +- `guides/upgrade-prisma-orm/postgresql.mdx:470-471, 510` — "Without a ref, the next `migration plan` starts from scratch and plans `CREATE TABLE` operations all over again" / "If you see `CREATE TABLE` operations instead, the `db` ref from step 4.3 is missing" — since rc.8 `migration plan` refuses to plan from an empty database when migrations already exist on disk and raises a structured error instead, so the symptom the guide tells the user to look for no longer appears — evidence: `docs/releases/v8.0.0-rc.8.md:17` +- `guides/upgrade-prisma-orm/postgresql.mdx:455` — expected output "`Database signed (marker created)`" — the command prints `Database signed` — evidence: `packages/1-framework/3-tooling/cli/src/orm/db/sign.ts:68` +- `guides/upgrade-prisma-orm/mongodb.mdx:27` — "validated against `@prisma/orm-mongo@0.16.0`" — the current package is `8.0.0-rc.9`, and breaking changes since 0.16.0 affect this guide's material (rc.7 pagination rename, rc.9 Mongo attribute rejection and index argument format) — evidence: `packages/9-public/@prisma/orm-mongo/package.json`, `docs/releases/v8.0.0-rc.7.md:9`, `docs/releases/v8.0.0-rc.9.md:9-25` +- `guides/index.mdx:35-39, 43` — lists "Upgrading: moving from Prisma 7" and "Databases" under "Coming as they land" and never links the upgrade, database, or switch guides, while `guides/upgrade-prisma-orm/postgresql.mdx` exists and is in the nav — evidence (site only): `guides/meta.json`, `guides/upgrade-prisma-orm/meta.json` +- `guides/switch-to-prisma-orm/from-drizzle.mdx`, `from-sql-orms.mdx`, `from-mongoose.mdx`, `guides/database/schema-changes.mdx`, `data-migration.mdx`, `multiple-databases.mdx` — all six sit in the Prisma 8 guides tree but are Prisma 7 / v6 guides: they install `prisma@7.10.0` or `prisma@6.19` and `@prisma/client` (`from-drizzle.mdx:52-53`, `from-sql-orms.mdx:40-41`, `from-mongoose.mdx:57-61`, `data-migration.mdx:73-77`, `multiple-databases.mdx:59-63`) and run `prisma init`, `db pull`, `migrate diff`, `migrate resolve`, `migrate dev`, `migrate deploy`, `generate`, `studio` (`from-drizzle.mdx:69, 169, 201, 209, 246`; `from-sql-orms.mdx:49, 61, 67-69, 75`; `from-mongoose.mdx:77, 170, 307`; `schema-changes.mdx:88, 155`; `data-migration.mdx:121, 243`; `multiple-databases.mdx:79, 233-237`). None of those commands exist in the Prisma ORM 8 CLI, whose tree is `orm init`, `contract *`, `db *`, `migration *`. A user coming from the Prisma 8 guides index is sent to a different product — evidence: `packages/1-framework/3-tooling/cli/src/orm/cli.ts:97-121`, `guides/meta.json` +- `guides/switch-to-prisma-orm/from-mongoose.mdx:14-20, 64-70` — "MongoDB support for Prisma ORM v7 is coming in the near future... use Prisma ORM v6.19" — Prisma ORM 8 ships MongoDB support as `@prisma/orm-mongo`, and the site's own MongoDB quickstart uses it — evidence: `packages/9-public/@prisma/orm-mongo/package.json`, `packages/3-extensions/mongo/src/runtime/mongo.ts:110-118` + +## Missing + +- Temporal requirement for inferred contracts — `contract infer` maps `timestamp`/`timestamptz` columns to `Timestamp`/`Timestamptz`, which are Temporal-backed; on a runtime without a global `Temporal` (no stable Node ships one) every read of such a column fails with `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported first or the type is changed to `TimestamptzString`. create-prisma installs the polyfill for this reason; `orm init` does not. Neither existing-project page nor the Prisma 7 upgrade guide (whose real-world schemas have `DateTime` columns) mentions it — evidence: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`, `packages/3-targets/3-targets/postgres/src/core/errors.ts:74-86`, `skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.5-to-8.0.0-rc.6/instructions.md:38-47`, `wip/create-prisma-src/src/constants/dependencies.ts:21-23`, `wip/create-prisma-src/templates/create/_shared/src/prisma/db.ts.hbs:15` — belongs on `add-to-existing-project/postgresql.mdx` step 4 and `guides/upgrade-prisma-orm/postgresql.mdx` section 2.4 +- `create-prisma --json` — non-interactive machine-readable mode for agents; not in the flag table — evidence: `wip/create-prisma-src/src/index.ts:73-76`, `wip/create-prisma-src/README.md:66-81` — belongs in the `create-prisma.mdx` flag table and the agent prompts on `getting-started.mdx` / `index.mdx` +- The full set of generated package scripts — the scaffold adds `db:update`, `db:verify`, `migration:status`, `migration:show`, `skills:sync`, `composer:dev`, `composer:deploy`, and `deploy` alongside the four the site mentions — evidence: `wip/create-prisma-src/src/tasks/install.ts:47-70` — belongs in `create-prisma.mdx` "Start the app" +- `orm init` flags — `--schema-path`, `--write-env`, `--probe-db`, `--strict-probe`, `--skip-install`, `--keep-previous-facade`, plus `--confirm ` for re-running init in an already scaffolded directory — evidence: `packages/1-framework/3-tooling/cli/src/orm/init.ts:87-112`, `packages/1-framework/3-tooling/cli/src/orm/init-inputs.ts:218-227` — `--write-env` and `--schema-path` belong on both add-to-existing-project pages, which currently rely on the defaults they describe wrongly +- Minimum database server versions — PostgreSQL 15 and MongoDB 8.0, written into `.env.example` by `orm init` — evidence: `packages/1-framework/3-tooling/cli/src/commands/init/templates/env.ts:16-19` — belongs on the PostgreSQL quickstart and existing-project pages (only the MongoDB upgrade guide states the Mongo minimum) +- MongoDB projects and Composer — Composer does not provision MongoDB; `dev:composer` and `deploy` need `MONGODB_URL` set as the secret bound in `module.ts` — evidence: `wip/create-prisma-src/templates/create/_shared/README.md.hbs:55-57`, `wip/create-prisma-src/templates/create/_shared/module.ts.hbs:24-27`, `wip/create-prisma-src/src/tasks/prisma-setup/presentation.ts:44-49` — belongs on `quickstart/mongodb.mdx`, which never mentions the Composer scripts, and on `prisma-orm/index.mdx` step 6 of the agent prompt, which assumes PostgreSQL provisioning +- A Prisma ORM 8 path for switching from another ORM — the shipped skill describes the brownfield flow (`orm init`, `contract infer --output`, review, `contract emit`, `db sign`, `db verify`) that replaces the Prisma 7 `db pull` / baseline guides — evidence: `skills/prisma-8/references/quickstart.md:229-263` — belongs in `guides/switch-to-prisma-orm/*`, which are Prisma 7 only +- Prisma ORM 8 team and data-migration workflow (`migration plan`, refs, `db update` for local iteration, `db verify`) — evidence: `skills/prisma-8/references/migrations.md`, `packages/1-framework/3-tooling/cli/src/orm/db/update.ts` — belongs in `guides/database/*`, which are Prisma 7 only +- `db init --dry-run` / `db update --dry-run` to preview operations before touching a database — evidence: `packages/1-framework/3-tooling/cli/src/orm/db/init.ts` and `db/update.ts` flag specs — useful on the quickstart step that runs `db:init` + +## Unverified + +- `(index)/getting-started.mdx:41`, `(index)/index.mdx:115`, `(index)/prisma-orm/index.mdx:48` — `npx prisma@latest db migrate --yes` — `db migrate` declares no `--yes` flag (`packages/1-framework/3-tooling/cli/src/orm/migrate.ts` flags: `db`, `to`, `advance-ref`, `show`, `from`); a global `--yes` would live in `@prisma/cli-engine`, which is not in the monorepo. create-prisma does pass `--yes` to `orm init` (`wip/create-prisma-src/src/tasks/prisma-setup/commands.ts:50`), so it exists at least there +- `(index)/index.mdx:96`, `(index)/getting-started.mdx:71` — "`orm init` may end with `CLI.INIT_SKILL_INSTALL_FAILED`, which `skills sync` repairs" — no such code exists in the monorepo and `orm init` installs no skills (`skill-sources.ts:1-5`); `skills sync` and `prisma init` are unified-CLI commands outside the monorepo +- `guides/upgrade-prisma-orm/postgresql.mdx:17, 161, 237-238` — `@prisma/prisma7@7.10.0-dev.58` and `definePrismaConfig` from `prisma/config` — both come from the prisma-cli repo; the monorepo's own `orm init` scaffold imports `definePrismaConfig` from `@prisma/cli-engine` (`code-templates.ts:304`) while create-prisma's template imports it from `prisma/config` (`prisma.config.ts.hbs:18`) +- `guides/upgrade-prisma-orm/mongodb.mdx:13` — the `prisma-mongodb-upgrade` skill and `npx skills add prisma/skills` — external repository, not checked +- `guides/upgrade-prisma-orm/mongodb.mdx:280` — "the typed builder sends the id through as a plain string, so the stage silently matches nothing" for `.match((f) => f.authorId.eq(authorId))` — did not trace ObjectId encoding in the pipeline builder's `match` path +- `(index)/prisma-orm/quickstart/postgresql.mdx:59` and `quickstart/mongodb.mdx:64` — the quoted output lines for `db init` and `db migrate` — did not locate the exact strings + +## Skill vs site + +- `skills/prisma-8/references/quickstart.md:73, 189, 201` says `orm init` scaffolds `prisma/contract.prisma` by default (TML-2532) and the site's existing-project pages (`add-to-existing-project/postgresql.mdx:46`) say the same; the source defaults to `src/prisma/contract.prisma` (`config-types.ts:45`, `code-templates.ts:63-67`). Source disagrees with both; the skill's note is stale +- `skills/prisma-8/references/queries-postgres.md:289, 302, 333` runs SQL-builder reads with `const rows = await db.runtime().execute(plan)`, and `queries-mongo.md:12, 140, 164, 178` runs pipeline reads with `runtime.execute(plan)`; the site's existing-project pages do the same. Source: `execute` returns statistics on both families and the Mongo runtime throws for a find/aggregate (`runtime-scope.ts:25`, `mongo-runtime.ts:99, 282-289`); the examples use `runtime.query(plan)`. Both skill and site are wrong +- `skills/prisma-8/references/contract.md:221` says `@@discriminator` / `@@base` are SQL-only in PSL; the site's MongoDB upgrade guide (`guides/upgrade-prisma-orm/mongodb.mdx:129, 164, 171`) uses them on MongoDB. The Mongo PSL interpreter implements both (`packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts:276-418`), so the site matches the source +- `skills/prisma-8/references/quickstart.md:196` documents an `orm init --skip-skills` flag; the site does not mention it and `orm init` declares no such flag (`packages/1-framework/3-tooling/cli/src/orm/init.ts:87-112`). Site matches the source +- `skills/prisma-8/references/quickstart.md:37` / mongo note at line 99 and the site's MongoDB pages agree on storage-name addressing (`db.orm.users`), and the scaffold's seed confirms it (`wip/create-prisma-src/templates/create/_shared/src/prisma/seed.ts.hbs:16`); no disagreement, listed for completeness diff --git a/docs/orm-docs-audit/brief-db-ref-on-adoption.md b/docs/orm-docs-audit/brief-db-ref-on-adoption.md new file mode 100644 index 00000000000..77d8448fb8e --- /dev/null +++ b/docs/orm-docs-audit/brief-db-ref-on-adoption.md @@ -0,0 +1,53 @@ +# Brief: set the `db` ref when a database is adopted + +Written 2026-09-10 for an agent with no prior context. Repo: `prisma/prisma` `main` (the Prisma 8 monorepo, rc.9). PRs go to `prisma/orm`. + +## What we want + +After adopting a database, the migration system knows the baseline. Concretely: `db sign` on a database with no prior signature should leave the project in a state where the next `migration plan` chains from the signed contract, with no extra commands. + +The shape we have in mind: `db sign` records the signed contract hash as the baseline state and sets the `db` ref to it, writing the contract snapshot so the ref resolves. Whether that also needs a baseline migration package on disk, or whether a snapshot alone is enough for `migration plan` to chain from and for `migration status` to report cleanly, is for the implementer to determine from how the planner and status resolve origins. + +Open questions to settle in the design, not to guess at: + +1. Should `db sign` on an already-signed database (re-signing under a newer hash) also move the ref? Probably yes, for the same reason, but it changes an existing behaviour. +2. Does `db sign --db ` follow the same rule as `db init --db ` and skip the ref? The existing rule is that an explicit `--db` means "not my dev database, don't move my ref". Adoption is usually done against the real database, so the rule may be wrong for sign. Decide and document. +3. If the ref already exists and points elsewhere, refuse, overwrite, or require `--advance-ref`. +4. `migration plan` with no `--from`, no ref, and no migrations on disk currently plans silently from empty. Consider warning or refusing the same way it does when migrations exist, since after this change the silent case means "you never ran init, update, or sign". + +## Acceptance + +- A test in `test/integration/` that: creates tables directly, runs `contract infer`, `contract emit`, `db sign`, changes the contract, emits, runs `migration plan`, and asserts the plan contains only the delta. +- The same flow with `--db ` on `db sign`, asserting whichever behaviour the design settles on. +- `migration status` after `db sign` reports current and target hashes equal and nothing pending. +- Update the shipped skill: `skills/prisma-8/references/migration-model.md` ("The trap" section and the origin rules) and `references/quickstart.md` (the brownfield adoption path). +- Update the monorepo docs that describe the ref rules: `docs/glossary.md` under "Ref", and any release note for the version this ships in (`docs/releases/`). +- Record upgrade instructions if the behaviour change is user-visible (the `record-upgrade-instructions` skill). + +The docs site (`prisma/web`) changes are handled separately; note in the PR what the new user-facing sequence is so the docs page can be written from it. + +## The problem + +A user with an existing database brings it under Prisma 8 by running `contract infer`, `contract emit`, and `db sign`. That is what the getting-started page for existing projects tells them to do. Then they change the contract and run `migration plan`. The plan proposes creating every table again. + +Cause: `migration plan` takes its origin from `--from`, else the `db` ref, else the empty contract. `db sign` writes the database marker but never sets the `db` ref, and there are no migrations on disk, so the plan resolves to the empty origin and the CLI does not refuse (the `MIGRATION.PLAN_ORIGIN_UNKNOWN` refusal only fires when migrations already exist on disk). + +Two Discord users hit this in one week and asked what `--from` is for. The incremental upgrade guide avoids it by teaching three extra commands (`migration plan --name baseline`, `db sign`, `migration ref set db `), and the "add to existing project" page does not teach them at all. + +## What exists today + +- `db init` and `db update` advance the `db` ref by default. `computeRefAdvancementName` in `packages/1-framework/3-tooling/cli/src/control-api/operations/ref-advancement.ts` returns `db` when no `--db` flag is given and `null` when `--db ` is passed, so passing `--db` also skips the ref. That second rule is a separate trap the shipped skill documents under "The trap" in `skills/prisma-8/references/migration-model.md`. +- `db migrate --advance-ref db` advances the ref after applying. +- `db sign` (`packages/1-framework/3-tooling/cli/src/orm/db/sign.ts`) verifies the live schema against the emitted contract and writes the marker. It does not touch refs. +- `migration ref set ` sets a ref by hand. +- `executeRefAdvancement` writes a contract snapshot under `migrations/snapshots/` and then the ref file. A ref must point at a hash that has a snapshot. + +## Pointers + +- Ref advancement: `packages/1-framework/3-tooling/cli/src/control-api/operations/ref-advancement.ts` +- Sign command: `packages/1-framework/3-tooling/cli/src/orm/db/sign.ts` +- Plan command and origin flag: `packages/1-framework/3-tooling/cli/src/orm/migration/plan.ts`, `control-api/operations/migration-plan.ts` +- Refusal text: `PLAN_ORIGIN_UNKNOWN` in `packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts` +- Existing ref tests: `test/integration/test/cli.db-ref-advancement.e2e.test.ts` +- The documented workaround: `wip/web/apps/docs/content/docs/guides/upgrade-prisma-orm/postgresql.mdx` §4.1 to 4.3 +- Migration graph ADRs: search `docs/architecture docs/adrs/` for "ref" diff --git a/docs/orm-docs-audit/brief-skills-opt-out.md b/docs/orm-docs-audit/brief-skills-opt-out.md new file mode 100644 index 00000000000..917d02d7fb0 --- /dev/null +++ b/docs/orm-docs-audit/brief-skills-opt-out.md @@ -0,0 +1,47 @@ +# Brief: let users opt out of agent skill files at scaffold time + +Written 2026-09-10 for an agent with no prior context. Repos: `prisma/create-prisma` (the scaffolder) and `prisma/prisma-cli` (the unified `prisma` binary, whose `init` and `orm init` commands are involved). A read-only clone of create-prisma is at `wip/create-prisma-src` in this worktree. + +## What we want + +1. `create-prisma` asks. Add a prompt in the interactive flow, "Install agent skills for coding assistants?" or similar, alongside the existing prompts, defaulting to yes. Add a flag for the non-interactive path, `--skills ` matching `prisma init --skills`, so `--yes` plus `--skills none` produces a project with no agent files, no `postinstall` hook, and `skills: { agents: [] }` in the config. +2. When the answer is no, the generated project has no `.claude/`, `.cursor/`, `.agents/`, or Devin directories, no `postinstall`, and no `skills:sync` script. `prisma-next.md` is a separate question: decide whether it is an agent file or a human readme and treat it accordingly. +3. `prisma orm init` on the existing-project path asks the same question when interactive, and honours `--skills` for parity with `--skip-skills`. +4. Removing skills after the fact: `prisma skills sync` with `agents: []` should remove the directories it previously wrote, or there should be a `prisma skills remove`. Decide which; the current behaviour (write nothing, leave the old copies) means the config opt-out looks like it did nothing. + +## Acceptance + +- `create-prisma my-app --yes --skills none` produces a project with none of the four agent directories, no `postinstall`, and `agents: []` in the config. Test in create-prisma's `tests/`. +- The interactive prompt appears and its answer is reflected the same way. +- `prisma orm init --skills none` on an existing project behaves the same. +- `prisma skills sync` after setting `agents: []` removes the previously written directories, or the new remove command does, with a test in prisma-cli. +- The `create-prisma` README and the CLI help text list the new flag. +- Note in the PR the exact user-facing sequence for the docs page, which is written separately: the `create-prisma` reference page, both quickstarts, `cli/init`, `cli/orm-init`, `cli/skills`, and `cli/configuration` on the docs site all need the answer. + +## The problem + +`npx create-prisma@latest` writes agent skill files for Claude, Cursor, Codex-style `.agents`, and Devin into every new project, adds a `postinstall` hook that re-syncs them on every install, and offers no prompt or flag to decline. One user counted "more than 200 files" and left. Five people raised it in one week. The workaround being passed around in the community (`skills sync --disable`, a `PRISMA_DISABLE_AGENT` env var) is wrong: the first only silences the staleness notice and the second does not exist. + +## What exists today + +In `create-prisma`: + +- `templates/create/_shared/prisma.config.ts.hbs` writes `skills: { agents: ["claude", "cursor", "agents", "devin"] }` for every non-Deno project. +- `src/tasks/install.ts` adds a `skills:sync` package script. +- `src/tasks/prisma-setup/commands.ts` first runs `prisma orm init --yes --target ... --authoring ... --skip-install`, which writes `prisma-next.md` (create-prisma deletes it again only for Deno). Then `initializeAgentSkills` runs `prisma init --yes`. That command adds a `postinstall` of `prisma skills sync || exit 0`, leaves the existing `prisma.config.ts` alone, and runs `skills sync` once. +- The CLI flags are `--template`, `--provider`, `--authoring`, `--package-manager`, `--deploy`/`--no-deploy`, `--workspace`, `--yes`, `--force`, `--verbose`, `--json`. Nothing about skills. + +In `prisma-cli`: + +- `prisma init --skills=none` writes `skills: { agents: [] }` when no config exists. With an existing config it does nothing to it. +- `prisma orm init --skip-skills` skips the skill install on the existing-project path. +- `prisma skills sync` writes the directories listed in `skills.agents`; with `agents: []` it writes nothing, but it does not delete copies already on disk. +- `skills: { check: false }` only silences the out-of-date notice. + +So the real opt-out is `skills: { agents: [] }` in `prisma.config.ts`, and nothing on the scaffold path lets the user say that. + +## Pointers + +- create-prisma: `src/tasks/setup-prisma.ts`, `src/tasks/prisma-setup/commands.ts`, `src/tasks/install.ts`, `templates/create/_shared/prisma.config.ts.hbs`, `src/index.ts` for flags +- prisma-cli: the `init`, `orm init`, and `skills` commands +- Docs pages describing current behaviour: `wip/web/apps/docs/content/docs/cli/init.mdx`, `cli/orm-init.mdx`, `cli/skills.mdx`, `cli/configuration.mdx` diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md new file mode 100644 index 00000000000..d19752fc69d --- /dev/null +++ b/docs/orm-docs-audit/changes.md @@ -0,0 +1,205 @@ +# Proposed changes + +Four kinds of change: restructure the docs, improve existing pages, create new pages, change the ORM. Ordered work first, then the items by kind. Nothing here is started. + +Sources: the first-session brief, plus the seven audit files under `audit/` (written 2026-09-10 against rc.9; every item cited below was spot-checked against `wip/prisma-src` unless marked "agent-reported"). Line numbers and full occurrence lists are in the audit files; this document names the defect and the pages. + +## Suggested order + +1. B1 to B4 and B11 to B14 as the first `prisma/web` PR: the site-wide mechanical fixes (`execute` to `query`, `sha256:` prefixes, `extensionPacks`, pagination names, `AndCount` names, snapshot layout). Each is a search-and-replace with a known correct form and breaks every user who copies it today. +2. B15 to B22 as a second PR, page by page: the existing-project pages, the migrations pages, the middleware pages, the raw SQL page, the relations page. These need rewriting sentences, not just names. +3. A7 in the same week as item 2: move or hide the sixteen Prisma 7 guides that sit under Prisma ORM 8 paths. Until then the guides index sends Prisma ORM 8 readers to `prisma generate`. +4. A4 and C4. Two small edits and one short page fix J4 and J5's discoverability. +5. A1, A2, A3, C1, C2 as the restructure, written from `mental-model.md`. This is the work that answers the Discord thread. +6. D1, D2, D3, D6, D8, D9, D10, D14, D17 raised as product tickets now, because C3, C4, and the deployment pages depend on the answers. +7. C3, C5 to C20 as each dependency clears. C9 (deployment) and C10 (Supabase and RLS) are the two largest gaps the audit found and have no page at all today. + +## Naming, across everything + +The product is "Prisma ORM"; a version number appears only when two versions are being contrasted. Rule, counts, and exceptions are in `naming.md`. Applies to every item below and to the proposed nodes in `ia.md`. + +## A. Restructure + +The current and proposed sidebar trees are in `ia.md`. The items below are the individual moves that tree implies. + +**A1. Give the ORM its own front door, organised by starting state.** Replace the current split (quickstart vs. add-to-existing) with four doors on `/prisma-orm` and `/orm`: new app from scratch, app I already started with an empty database, an existing database with data, and an existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. + +**A2. Put "Coming from Prisma 7" in the ORM sidebar at the top level and link it from the root page, `/getting-started`, `/orm`, and reading-data.** One page, with the mapping table from `mental-model.md` expanded. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. + +**A3. Human content first, agent prompts last, on every ORM page.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end of the page or into a collapsed block. Addresses the "written for AI" complaint directly. Unblocks the Newcomer and the Upgrader on every page. + +**A4. Fix the navigation labels that hide existing content.** The upgrade guide's sidebar label is "PostgreSQL" under "Upgrade Prisma ORM"; rename to "Prisma 7 to 8 (PostgreSQL)". The guides index says upgrading is "coming as they land"; remove that line. Files: `guides/upgrade-prisma-orm/meta.json`, `guides/index.mdx`. Unblocks J5. + +**A5. Root page: make the ORM line a section.** The root is the platform's page and should stay so, but the ORM needs more than "Here for the ORM? Jump to Prisma 7 or Prisma 8". Give it the four doors from A1 in one row. File: `(index)/index.mdx`. + +**A6. Absorb core-concepts into a narrative page written from `mental-model.md`.** The current page is a good glossary but reads as a list of terms. The mental model page answers "why" in the order a person meets each piece. Keep the glossary as a section at the end. File: `orm/core-concepts.mdx`. + +**A7. Get the Prisma 7 guides out of the Prisma ORM 8 tree.** Sixteen pages under the Prisma ORM 8 guides paths are Prisma 7 content end to end (`prisma@7.10.0`, `@prisma/client`, generator blocks, `prisma generate`, `migrate dev`, `db push`, `db seed`, `studio`): `guides/frameworks/react-router-7`, `guides/frameworks/solid-start`, all six of `guides/deployment/*`, `guides/integrations/github-actions`, `guides/integrations/ai-sdk`, all three of `guides/switch-to-prisma-orm/*`, all three of `guides/database/*`. None has a copy under `guides/v7/`. Move them to `guides/v7/` with the same slugs and redirect, then either write the Prisma ORM 8 replacement (C9, C11, C12) or leave the label off the Prisma ORM 8 sidebar until it exists. Evidence: `audit/gaps.md` Breaks copy-paste, `audit/start-guides.md` Misleading. Changes `ia.md`: the "Guides" tree for Prisma ORM 8 loses six labels until replacements land. + +**A8. One error reference, or two that link.** `cli/error-reference.mdx` says it lists every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code lives on `orm/reference/error-reference.mdx`, and the two pages do not link. The structured errors' `docsUrl` points at the ORM page. Either merge, or state the split on both pages and cross-link. Evidence: `audit/migrations-cli.md` Misleading. + +## B. Improve existing pages + +Copy-paste defects a user hits today, grouped by theme. B1 to B10 are from the first-session brief; B11 onward are from the audit. Full line lists are in the audit files named on each item. + +### Site-wide mechanical fixes + +**B1. `.take()`/`.skip()` to `.limit()`/`.offset()`.** 29 sites on 8 pages: `orm/fundamentals/reading-data.mdx` (8, including the meta description), `orm/reference/orm-client.mdx` (13, including two section headings), `orm/fundamentals/relations-and-joins.mdx`, `orm/reference/pipeline-builder.mdx` (3, check which are the Mongo pipeline `$skip` stage and keep those), `orm/middleware/authoring-custom-middleware.mdx`, `guides/runtimes/deno.mdx`, `(index)/full-stack-tutorial.mdx`, `(index)/prisma-orm/add-to-existing-project/postgresql.mdx`. + +**B2. `createCount`/`updateCount`/`deleteCount` to the `AndCount` names.** 31 sites on `orm/fundamentals/writing-data.mdx` and `orm/reference/orm-client.mdx`, including three section headings. + +**B3. Existing-project PostgreSQL page.** `db.orm.User` to `db.orm.public.User`; `db.sql.user` to `db.sql.public.user`; drop the `db.connect()` call or the `db.runtime()` call, not both; show `src/prisma/db.ts` once with one sentence on what it does; pick one story for `DATABASE_URL` (the page uses `.env` with `dotenv/config`, the quickstart says environment only) and say why. Then add the missing steps from J2: baseline migration and `migration ref set db` before the "next steps" section. See also B15, which found the page's default path is wrong. File: `(index)/prisma-orm/add-to-existing-project/postgresql.mdx`. + +**B4. Remove `@db.Uuid` from the PSL syntax page.** Lines 19 and 177 of `orm/contract-authoring/psl-syntax.mdx` show `Uuid = String @db.Uuid`. Removed in 0.17; `Uuid` is a built-in type name in type position and needs no alias, so the "Named types" example should alias a real type instead (for example `ShortName = VarChar(35)`). Check the rest of the page for other `@db.` forms. + +**B11. `execute()` to `query()` for every row-returning plan.** The largest defect the audit found. Since rc.2, `runtime.execute(plan)` returns `{ affectedRows }` and rows come from `runtime.query(plan)` (an `AsyncIterableResult`, awaitable to an array or iterated with `for await`). The MongoDB client's `db.execute(plan)` facade method was removed in the same release; rows come from `(await db.runtime()).query(plan)`. Prepared statements split the same way: `ps.query(runtime, params)` for rows, `execute` only for `.affectedCount()` plans. Roughly 200 lines on 14 pages: `orm/reference/sql-query-builder.mdx` (about 31), `orm/reference/pipeline-builder.mdx` (about 50), `orm/reference/raw-queries.mdx` (about 20), `orm/fundamentals/advanced-queries.mdx` (10), `orm/reference/transactions-and-runtime.mdx` (about 12, including `withTransaction`'s `tx` surface and `executePrepared`, which does not exist), `orm/core-concepts.mdx`, `orm/fundamentals/reading-data.mdx`, `orm/fundamentals/relations-and-joins.mdx`, `orm/extensions/using-extensions.mdx`, `orm/middleware/built-in-cache.mdx`, both `add-to-existing-project` pages, `guides/upgrade-prisma-orm/mongodb.mdx` (5). Non-returning writes such as `orm/fundamentals/transactions.mdx:60` are correct and stay on `execute`. The shipped skill has the same defect (D14). Evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `packages/3-extensions/mongo/src/runtime/mongo.ts:28-39`, `docs/releases/v8.0.0-rc.2.md`. Audit: `orm-client`, `builders`, `start-guides`. + +**B12. Bare hex hashes.** Every hash the site prints is `sha256:…`; since 0.17 hashes are bare hex and loaders and `migration ref set` reject the prefixed form. `orm/contract-authoring/the-contract-artifact.mdx` (5 sites, in JSON and in `StorageHashBase<"sha256:…">`), all six `orm/migrations/*` pages, `cli/migration-ref.mdx`. Evidence: `docs/releases/v0.17.0.md:45`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:14-24`. Audit: `contract`, `migrations-cli`. + +**B13. `extensionPacks` to `extensions`.** Renamed in 0.17 and the old key fails loudly. `orm/contract-authoring/typescript-schema-builder.mdx` (5 sites in `defineContract`; the PostgreSQL contract on that page does not build) and `orm/contract-authoring/the-contract-artifact.mdx` (2 sites as the `contract.json` top-level key). Evidence: `docs/releases/v0.17.0.md:73`, `packages/3-extensions/postgres/src/contract/define-contract.ts`. Audit: `contract`. + +**B14. Migration directory layout and imports.** The site shows `start-contract.json` / `end-contract.json` inside each migration directory and `migration.ts` importing `./end-contract`. Since 0.17 snapshots live once under `migrations/snapshots//contract.json` plus `contract.d.ts`, and `migration.ts` imports `../../snapshots//contract.json`. The directory holds `migration.ts`, `ops.json`, `migration.json`. Pages: `orm/migrations/how-migrations-work.mdx`, `generating-a-migration.mdx`, `editing-a-migration.mdx`. Evidence: `docs/releases/v0.17.0.md:47`, `examples/prisma-8-demo/migrations/app/*/migration.ts`. Audit: `migrations-cli`. + +### Page rewrites + +**B15. Existing-project pages: the default path is `src/prisma/`, not `prisma/`.** Both `add-to-existing-project` pages tell the reader to keep the default schema path `prisma/contract.prisma` and build every later command on it (`contract infer --output ./prisma/contract.prisma`, `import "./prisma/db"`). `orm init` defaults to `src/prisma/contract.prisma` and writes `db.ts` beside it, so a reader who accepts the default gets a file `prisma.config.ts` never reads and an import that does not resolve. Same pages also say `orm init` installs agent skills (it stopped in rc.6; it writes `prisma-next.md` only), omit the `.env` prompt (default No, so there may be no `.env` to "update"), and the MongoDB page's `runtime.execute(plan)` on an aggregate throws `RUNTIME.MONGO_STATISTICS_UNSUPPORTED`. Add the Temporal polyfill note (D10) and the `--write-env` / `--schema-path` flags. Evidence: `packages/1-framework/1-core/config/src/config-types.ts:45`, `packages/1-framework/3-tooling/cli/src/orm/init-inputs.ts:229-233`, `docs/releases/v8.0.0-rc.6.md:29`. Audit: `start-guides`. + +**B16. The `db` ref and plan-origin story on the migrations pages.** Three connected errors. (a) The pages say `migration plan` without `--from` or a `db` ref plans a full CREATE migration; since rc.8 it refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN` when migrations exist on disk, and names the exits (`migration ref set db `, `--from `, `--from @empty`). The upgrade guide tells readers to look for the CREATE TABLE symptom that no longer appears. (b) `db init` and `db update` advance the `db` ref automatically only when `--db` is omitted; every example on the site passes `--db "$DATABASE_URL"`, which suppresses that unless `--advance-ref` is also given, so a reader following the site's loop hits (a) on the second plan. No page says this. (c) Retracted after PR 2: the audit said `MIGRATION.NO_TARGET` never comes from `migration plan`, but `plan-resolution.ts` calls `findLatestMigration`, which calls `findLeaf`, which throws it on a cyclic graph, and the monorepo's `gotchas.md:83-110` reproduces exactly the rollback case `rollbacks-and-recovery.mdx` describes. That page was right. Also `the-migration-graph.mdx` says there is no baseline mechanism; the planner writes an automatic baseline when the graph is empty and the `db` ref names a snapshot, and `--from @empty` is the supported retrofit. Pages: all six `orm/migrations/*`, `cli/migration-plan.mdx`, `cli/db-init.mdx`, `cli/db-update.mdx`, `cli/migration-ref.mdx`, `cli/index.mdx`, `guides/upgrade-prisma-orm/postgresql.mdx`. Evidence: `packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts:428-475`, `cli/src/control-api/operations/ref-advancement.ts:19-28`, `cli/src/control-api/operations/migration-plan.ts:369,505-545`. Audit: `migrations-cli`, `start-guides`. Ties to D1, D2, D9. + +**B17. Middleware pages: the hook model is wrong.** The pages document five hooks with `intercept` and `beforeExecute` for reads. Since rc.2 there are two lifecycles: `beforeQuery` / `interceptQuery` / `onRow` / `afterQuery` for row queries, and `beforeExecute` / `interceptExecute` / `afterExecute` for non-returning writes. There is no `intercept`, no compatibility alias, and `afterExecute` carries `stats.affectedRows`, not `rowCount`. The authoring guide's flagship query logger implements only `afterExecute` and reads `result.rowCount`, so it is a type error and would never log the SELECT the page shows it logging. Also: `unindexedPredicate` is not a lint severity key; `severities.latency` on budgets is read (page says it is not); "permissive mode" is unreachable from the Postgres client (D12); the cache runs on the query lifecycle. Pages: all five `orm/middleware/*`. Evidence: `packages/2-sql/5-runtime/src/middleware/sql-middleware.ts`, `packages/2-sql/5-runtime/src/middleware/lints.ts:13-23`, `budgets.ts:97-125`, `examples/prisma-8-demo/src/prisma/slow-query-warning.ts`. Audit: `builders`. + +**B18. Raw SQL page says the opposite of what ships.** `orm/reference/raw-queries.mdx` and `advanced-queries.mdx` say there is no way to run a standalone raw statement. Since rc.2 there is: `db.raw.sql\`…\`.returnsRow(spec).build()` for rows and `.affectedCount().build()` for writes; raw row queries compose as subqueries and CTEs. The page also calls `db.raw` as a template tag; it is a lane object and the tag is `db.raw.sql`. The "bare scalar interpolation is broken because the inferer emits unversioned ids" callout is contradicted by the adapter source, which emits versioned ids. Evidence: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:117-170`, `packages/3-targets/6-adapters/postgres/src/core/adapter.ts:112-140`, `examples/prisma-8-demo/src/queries/raw-query-demo.ts`. Audit: `builders`, `orm-client`. + +**B19. Relations and data-modeling pages say things are unsupported that work.** (a) The 1:1 mirror field `profile Profile?` "is not supported yet": it is accepted (rejected only when the foreign key is not unique) and `include('profile')` type-checks as a to-one include. (b) Implicit many-to-many `include` "not supported yet": the ORM resolves `through` relations and the demo includes `Post.tags`; nested `create` / `connect` / `disconnect` through the junction also work, and `orm-client.mdx` already documents `disconnect` through the junction. (c) Referential actions "as it lands": `onDelete` / `onUpdate` with `Cascade` / `Restrict` / `SetNull` / `NoAction` are lowered today. (d) The discriminator "is not filled in automatically": `.variant('Bug').create()` injects it; the page never mentions `.variant()`. Both pages send users to the SQL builder for things the ORM does. Pages: `orm/fundamentals/relations-and-joins.mdx`, `orm/data-modeling/relational-databases.mdx`. Evidence: `packages/2-sql/2-authoring/contract-psl/test/interpreter.relations.test.ts:78`, `packages/3-extensions/sql-orm-client/src/collection-contract.ts:356-379`, `mutation-executor.ts:836-926`, `collection.ts:406`, `psl-relation-resolution.ts:19-22`. Audit: `contract`, `orm-client`. + +**B20. Aggregates decode as numbers, not strings.** `sql-query-builder.mdx` and `advanced-queries.mdx` tell users `COUNT` / `SUM` / `AVG` come back as strings and to call `Number(...)`. Since rc.2 `count()`, integer `sum()`, and `avg()` return `number` (throwing `RUNTIME.DECODE_FAILED` outside the safe range), with `countBigInt()`, `sumBigInt()`, `avgDecimal()` beside them. The "fixed" function list on `sql-query-builder.mdx` omits these; `min` / `max` are not numeric-only. Correction after PR 2: the audit said the `DateTime` column (`pg/timestamptz@1`) is still excluded from `min`/`max`; no such codec exists at rc.9. `DateTime` maps to `pg/timestamptz-temporal@1`, which is in `MIN_MAX_PRESERVING_CODECS`, so `min('createdAt')` type-checks; the compile error the page should show is `sum`/`avg` over a timestamp column. Evidence: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:126-213`, `docs/releases/v8.0.0-rc.2.md:32-53`. Audit: `builders`, `orm-client`. + +**B21. Stale CLI names, flags, codes, and output.** One pass over `cli/*` and `orm/migrations/*`: `--skip-skills` and `CLI.INIT_SKILL_INSTALL_FAILED` on `orm-init.mdx` (removed rc.6; also cited on `(index)/index.mdx` and `getting-started.mdx`); `ref set` / `ref list` bare group (rc.5: `migration ref set`) and `ref set prod @db` (fails, `@db` is not accepted by the offline command); `prisma-cli migrate` hint text and the sentence explaining it (rc.5: hints print `prisma db migrate`); `(PN-RUN-3000)` (0.17: dotted codes, `MIGRATION.RUNNER_FAILED` and siblings); `from: null` (prints `from: (baseline)`); the "Applied 1 migration(s)…" summary line (no migration count); `git clone …/orm` then `cd prisma`; `npx prisma@latest migrate` on `create-prisma.mdx` (the command is `db migrate`); hyphenated `--name add-users-table` shown as the directory name (slugs become `add_users_table`); `contract infer` presents `--db` as required (falls back to config); `orm-init.mdx` says the scaffolded `db.ts` does not load `.env` (it starts with `import 'dotenv/config'`) and that `contract:emit` calls `prisma-cli`. Audit: `migrations-cli`, `start-guides`, `contract`. + +**B22. `editing-a-migration.mdx` data-transform example does not typecheck.** `sql({ context })` omits the required `rawCodecInferer`, so `node migration.ts` fails before writing `ops.json`. Evidence: `packages/2-sql/4-lanes/sql-builder/src/runtime/sql.ts:11-19`. Audit: `migrations-cli`. + +### Smaller fixes, one line each + +**B5. Supported databases.** `orm/index.mdx` says SQLite is planned. It ships as `@prisma/orm-sqlite`; `sql-query-builder.mdx` also says "PostgreSQL is supported today". Say Postgres, MongoDB, SQLite, and what is next. + +**B6. Un-pin the upgrade guides.** The PostgreSQL guide says every command was validated on rc.6 and rc.4; the MongoDB guide says `0.16.0`. Re-run on rc.9 (the Mongo guide is also hit by the rc.7 pagination rename and the rc.9 attribute rejection) and either drop the version callout or keep it current per release. Also `Database signed (marker created)` is printed as `Database signed`. Files: `guides/upgrade-prisma-orm/postgresql.mdx`, `mongodb.mdx`. + +**B7. One line on agent files, on three pages.** On `create-prisma.mdx`, both quickstarts, and the existing-project page: "Prisma writes skill files for coding agents into your repo. To stop that, set `skills: { agents: [] }` in `prisma.config.ts`; see Configuration." Until D3 lands, that is the only correct answer. + +**B8. Node version.** The quickstart says 24 or newer; seven framework guides say "Node.js 24 or later"; the scaffold's `engines` says `^22.18.0 || >=24.11.0` and create-prisma refuses below 22.18; the upgrade guide says 22.18+. Node 24.0 to 24.10 does not work. Say the true floor once. + +**B9. Explain `// use prisma-next`.** It appears at the top of every PSL example and is never explained. One sentence where the contract file is first introduced, and on the editor page (C5). + +**B10. `db.runtime()` on Mongo.** Mongo needs `(await db.runtime())`, Postgres does not. Say so where `db.ts` is first shown, not only in the transactions reference. + +**B23. `db.close()`, not `db.runtime().close()`.** Four guides (Bun, Hono, Elysia, NestJS) tear down with `db.runtime().close()`; the client method is `db.close()` (idempotent, also `Symbol.asyncDispose`), and every other page uses it. Audit: `gaps`. + +**B24. Upsert needs `conflictOn`.** `writing-data.mdx:182-195` upserts without `conflictOn` and says the match is on `email`; without `conflictOn` the target is the primary key, so the sample inserts a duplicate or fails on the unique constraint. Audit: `orm-client`. + +**B25. Streaming claim.** `reading-data.mdx` promises a flat memory footprint for `for await` over millions of rows; the `postgres()` facade constructs its driver with `cursor: { disabled: true }`, so the whole result is buffered first. Either soften the page or fix the ORM (D8). Audit: `orm-client`. + +**B26. Enum ordering changed in rc.9.** `orm-client.mdx:478,513` say text-backed enums sort in declaration order; rc.9 sorts by stored value, only native enums keep database order. Audit: `orm-client`. + +**B27. Structured errors, not plain `Error`.** `transactions-and-runtime.mdx` shows closed / double-connect failures as plain `Error` strings; they are `DRIVER.NOT_CONNECTED` / `DRIVER.ALREADY_CONNECTED` envelopes, and the latter is raised by Postgres too. Its `db.prepare` then `db.connect()` sample throws `DRIVER.ALREADY_CONNECTED`. `pipeline-builder.mdx` calls the unknown-root error a plain `Error`; it is `ORM.MODEL_UNKNOWN`. Audit: `orm-client`, `builders`. + +**B28. create-prisma page details.** The `--template` list omits `minimal` (the default) on three pages; for PostgreSQL the scaffold writes no `.env` (page says "review `DATABASE_URL` in `.env`"); `--force` also overwrites the generated Prisma files and refuses on a non-empty `migrations/`; the deploy prompt defaults differ between interactive, `--yes`, and `--json`; the Deno command needs `--minimum-dependency-age=0`; the page lists four of the twelve generated scripts. Audit: `start-guides`, `gaps`. + +**B29. MongoDB replica set.** Both MongoDB start pages say Prisma 8 needs a replica set; nothing in the runtime or migration runner opens a session or transaction, and `orm init`'s `.env.example` says a standalone `mongod` works. Only the scaffold's connection string demands one. Audit: `start-guides`. + +**B30. Framework guide details.** The Bun guide's `esbuild` build step fails (the scaffold builds with `tsdown`; edit `tsdown.config.ts` instead) and `bun run dev` is `tsx watch`, so "no build step" and the one-shot output are wrong; the NestJS `@Inject` workaround describes a defect the template fixed; seven guides say `db:init` applies `src/prisma/contract.prisma` without saying the TypeScript authoring path is `contract.ts` with output under `src/prisma/generated/`; the Deno page's "separate Deno CLI entry point" note is stale and its sample output omits fields. Audit: `gaps`. + +**B31. `data-modeling/index.mdx` scalar table.** `Json` binds to native `json` since 0.17; `Jsonb` is the separate scalar (what `field.json()` and value objects use). The table never mentions `Jsonb`, `Decimal`, `Bytes`. Audit: `contract`. + +**B33. `ai/tools/skills.mdx` describes skills that do not exist.** It says `orm init --skip-skills` skips installation (no such flag; `orm init` does not touch skills since rc.6), lists `prisma-next-upgrade` and `prisma-8-extension-upgrade` as installable (retired; `prisma init` deletes those directories; only `prisma-8` ships, with upgrading as a branch inside it), says `orm init` pins the GitHub install (the skill ships inside the `@prisma/orm-*` tarball and `prisma skills sync` copies it), and leads with `npx skills add prisma/prisma/skills`, which the monorepo README calls a fallback nothing keeps current. Evidence: `skills/README.md`, `cli/src/commands/init/skill-sources.ts:1-49`. Audit: `extras`. + +**B34. Full-stack tutorial.** The tutorial shows the scaffold's `User` model with `createdAt DateTime` and `updatedAt temporal.updatedAt()`; the rc.9 starter contract writes `TimestamptzString` and `temporal.updatedAtString()`, which store a different runtime type. It also says the scaffold added a `postinstall` hook for skills; create-prisma adds a `skills:sync` script and runs `prisma init --yes` once. Evidence: `cli/src/commands/init/templates/code-templates.ts:171-193`, `wip/create-prisma-src/src/tasks/install.ts:56`. Audit: `extras`. + +**B35. `using-extensions.mdx` recipe and links.** The generic five-step recipe (import `/control`, pass to `postgres({ extensions })`) does not work for Supabase, which is wired with `extensions: [supabasePack]` from `/pack` and a client built by `supabase()` from `/runtime`. Every catalog row links to a monorepo README whose install command is `pnpm add @internal/extension-`, a private name. Also `orm/data-modeling/index.mdx:159` lists `Json` without saying filtering is whole-value equality only (D17). Audit: `extras`. + +**B32. Guides index.** `guides/index.mdx` lists "Upgrading" and "Databases" under "Coming as they land" while the upgrade guide exists and is in the nav. Fold into A4. + +## C. New pages + +**C1. Coming from Prisma 7.** The mapping table from `mental-model.md`, in four sections: schema and types, CLI commands, client API, and "not in Prisma 8 yet" with a status per item. The last section is the one users asked for most and the one no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types (with a link to the PRs), `@updatedAt` (rejected with a hint to use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`). Unblocks J3. Depends on A2 for placement. + +**C2. Add Prisma ORM to an app you already started.** The J1 page. Starts from "you have a project directory and an empty or absent database". `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since it is the case reported, with a note for Node. Replaces the Bun guide's scaffold-first opening or sits beside it. + +**C3. Adopt an existing database.** The J2 page, split out from the current existing-project page so B3 and B15's fixes have room. Adds what to expect from `contract infer` (it is SQL-only; it captures indexes, checks, RLS, and 1:1 relations from unique indexes; it emits Temporal-backed `Timestamp` types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, and the second migration with `--advance-ref db`. Depends on D1 for how short this can be. + +**C4. Prisma ORM 8 release status.** One short page: Prisma ORM 8 is a release candidate; GA expected in the window Will has stated publicly; Prisma ORM 7 receives bug fixes and security updates for 12 months; `npx prisma` and `npm install prisma` now resolve to Prisma ORM 8; to stay on 7, install `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. Depends on D6 for whether the tag stays. + +**C5. Editor setup.** VS Code extension location (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `contract.prisma` needs `// use prisma-next` on line one, and `prisma contract format` as the fallback. Under getting started. Unblocks J7. Needs Serhii to confirm the current state. + +**C6. Types.** Model types, result types, where and input types, with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch and published the day prisma/orm#30231, #30236, and #30158 ship. Unblocks J9. Also covers what `contract.d.ts` already exports today: `AddressInput` beside `AddressOutput`, `FieldOutputTypes`, `TypeMaps`, `QueryOperationTypes`, `AggregateTypes`. + +**C7. Advanced Postgres.** The audit answered the product questions the first brief left open: RLS and policies are expressible in PSL (`@@rls`, `policy_select` and siblings, `role` blocks) and in the TypeScript builder; expression and partial indexes are `@@index(expression:, where:, unique:, type:)`; hand-written checks are `@@check`; `@noCheck` waives generated checks; `installExtension` / `createExtension` are migration factories; `@@control` sets how much of a table Prisma manages. None of it is on the site. Write the page from `skills/prisma-8/references/contract.md:101-108,265-367` and `packages/2-sql/2-authoring/contract-psl/README.md`. Unblocks J8. Audit: `contract`, `gaps`. + +**C8. Money and Decimal.** Short page or section under data modeling: cents as integers (already there), `Decimal` with precision and scale in type position (`Numeric(p, s)`), what `@default` accepts on it, and the aggregate return types (`avgDecimal`). Answers the open Discord question. + +**C9. Deploying Prisma ORM 8.** (See also the production caveat at the end of this item.) There is no Prisma ORM 8 deployment guide for any host; all six `guides/deployment/*` pages are Prisma 7 (A7). What a deploy needs is in the source: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). One page with sections for Docker, Vercel, Cloudflare Workers, and monorepos, or one page per host under the same label. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, 128 MiB isolate memory so `limit()` is the memory cap) and carries a production caveat with zero site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s), workaround `cursor: { disabled: true }`. Evidence: `skills/prisma-8/references/build.md:421-435`, `migrations.md:487`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. Audit: `gaps`, `extras`. + +**C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, the async `supabase({ contractJson, url, jwksUrl | jwtSecret })` factory, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*` reads, and `SUPABASE.JWT_INVALID` / `SUPABASE.CONFIG_INVALID`. A page under `orm/extensions/` and a guide. Evidence: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. Audit: `gaps`. + +**C11. CI with Prisma ORM 8.** The only CI guide is Prisma 7 (A7). The Prisma ORM 8 shape: `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Evidence: `skills/prisma-8/references/migration-review.md:172-197`, `cli/src/orm/migration/status-findings.ts`. Audit: `gaps`, `migrations-cli`. + +**C12. Switching from another ORM, and team schema workflow.** The three `switch-to-prisma-orm/*` and three `database/*` guides are Prisma 7 (A7). The Prisma ORM 8 replacements are the brownfield flow (`orm init`, `contract infer --output`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Much of C3 and C11 can be reused. Audit: `start-guides`. + +**C13. Migration factory reference.** The site shows six migration factories (`createSchema`, `createTable`, `addColumn`, `setNotNull`, `dataTransform`, `rawSql`). The `Migration` base class has about thirty: indexes, foreign keys, uniques, checks, column type and default changes, native enum create / drop / add-value, `installExtension`, RLS enable / disable, policy create / drop / rename, plus the free factories `createExtension`, `foreignKey`, `unique`, `checkExpression`, `fn`, `lit`. Also the `node migration.ts` self-emit CLI's `--dry-run` and `--config`. A reference page beside `editing-a-migration.mdx`. Evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. Audit: `migrations-cli`. + +**C14. PSL and TypeScript builder completeness.** Not a new page but a rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. Missing from PSL: native types in type position (`Uuid`, `VarChar(255)`, `Numeric`, `Timestamptz`, `TimestamptzString`, `Jsonb`, `BigIntNumber`, `UnboundedInt`, and the rest), the `@default` generator list (`uuid(4|7)`, `cuid(2)`, `ulid()`, `nanoid(n)`, `dbgenerated`), `temporal.createdAt()` / `updatedAt()` presets, scalar lists and which targets support them, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks and cross-space relation targets, `native_enum` blocks, `@relation("Name")` disambiguation, `onDelete` / `onUpdate`, extension types inline in field position, MongoDB index options (`sort:`, `@@textIndex`), and `.variant()` for polymorphic reads. Missing from the TypeScript page: the field helpers beyond four, `.attributes()` for composite keys and uniques (the page shows no way to declare a composite primary key), `constraints.index`, `check`, `.noCheck()`, `rel.belongsTo().sql({ fk })`, `foreignKeyDefaults` / `naming`, the `output` config option, and the MongoDB builder's `valueObject`, `index`, `enumType`, `field.vector()`, and polymorphism. Evidence: `packages/2-sql/2-authoring/contract-psl/README.md`, `contract-ts/README.md`, `packages/2-mongo-family/2-authoring/contract-ts/README.md`. Audit: `contract`. + +**C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute` and `RuntimeStatementStats`; `verifyMarker: 'onFirstUse' | false` (the startup check core-concepts describes without saying how to control it); `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat accessor form `db.orm.User` for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the optional `configure(meta)` callback on every terminal and `meta.annotate(...)` (how cache opt-in works per query); `distinctOn` needs the `postgres.distinctOn` capability; MongoDB `mode: 'strict' | 'permissive'` and the filter classes `MongoAndExpr`, `MongoNotExpr`, `MongoExistsExpr`; the SQLite facade lifecycle; the driver-free static client (`@prisma/orm-postgres/static`); `db.prepare` and prepared bind sites on `limit()` / `offset()`; `ctx.signal` and `MongoMiddleware` on the middleware pages; `createInMemoryCacheStore` and the cache debug events; `RUNTIME.MISSING_EXTENSION_PACK`; `fns.cosineSimilarity`. Audit: `orm-client`, `builders`. + +**C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; Vite 7 and 8; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides (SvelteKit, Astro, Nuxt, TanStack Start) tell readers to run `contract:emit` by hand. A section on `the-contract-artifact.mdx` plus one paragraph per framework guide. Evidence: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`, `skills/prisma-8/references/build.md`. Audit: `gaps`, `contract`. + +**C18. Supported versions and requirements.** No page states the floors. The monorepo's `docs/Supported Versions.md` says Node 24, Bun 1.2, Deno 2.0, PostgreSQL 15, MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, and ESM-only with no CommonJS. The site says Bun 1.1, states no PostgreSQL floor anywhere, says nothing about ESM or `strict`, and the upgrade guide shows `module: nodenext`. The doc's Node 24 disagrees with the scaffold's `^22.18.0 || >=24.11.0` (B8) and its `--merge-tsconfig` flag does not exist at rc.9, so confirm each number with product before publishing. One short page under getting started, linked from every quickstart. Audit: `extras`. + +**C19. Extension pages beyond pgvector.** PostGIS (`Geometry` type, its seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), and arktype-json (`arktypeJson(schema)`, never shown) each have one catalog row. One section per pack on `using-extensions.mdx` or one page each, with the real public import paths. Audit: `extras`. + +**C20. Telemetry page.** `cli/telemetry.mdx` never mentions `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file and its `enableTelemetry` field, that CI never sends, the first-run notice, that the preference is per-user, agent detection, or the event fields (the monorepo's `docs/Telemetry.md` is itself stale: rc.9 also sends `exitCode`). The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, not this page. Evidence: `packages/1-framework/3-tooling/cli-telemetry/src/`, `cli/src/orm/telemetry/reporting.ts`. Audit: `extras`. + +**C17. CLI page additions.** `cli/configuration.mdx`: the `migrations.dir` and `formatter` keys, the `composer` section every scaffold ships, telemetry opt-out variables (`DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`). `cli/orm-init.mdx`: the full flag list, exit codes 4 and 5, `prisma-next.md`, `--confirm` for re-running. `cli/db-update.mdx`: it never plans `data`-class operations. `cli/migration-ref.mdx`: the refusals. `cli/migration-new.mdx`: default origin rules. `cli/migration-status.mdx`: `--json` diagnostics. `cli/db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH` and `PATH_UNREACHABLE`. `cli/contract-emit.mdx`: `--json` output and the `output` config option. `cli/index.mdx`: `@prisma/orm-toolchain` and `@prisma/orm-framework`. Audit: `migrations-cli`, `contract`, `gaps`. + +## D. Change the ORM + +These are places where the docs are hard because the tool is. Each is a candidate for the product backlog, not a docs fix. D1 and D3 have briefs (`brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`) and are handed off. + +**D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan --name baseline` (or equivalent), `migration ref set db `. Two options: have `db sign` also set the `db` ref when no ref exists, or add a `db adopt` command that runs sign plus ref. Either removes the recreate-everything trap in J2 and cuts C3 in half. Handed off. + +**D2. `migration plan` with no origin and no migrations on disk.** The CLI refuses when migrations exist on disk with no ref (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). When no migrations exist it silently plans from empty. For a signed database with no ref that is the wrong default; it should warn or refuse the same way. Related to D1. + +**D3. Opt out of agent files at scaffold time.** `create-prisma` has no flag and always writes all four agents plus a `postinstall`. Add a prompt and a `--skills none` flag, and have `orm init` ask. Five users in one week; the circulating workaround is wrong. Handed off. + +**D4. Missing client API.** Verified absent from the SQL ORM client source: `firstOrThrow` on the collection (it exists on `AsyncIterableResult`, so `.all().firstOrThrow()` works and could be documented as the workaround), atomic `increment`/`decrement` on update, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), and filtering on JSON columns by path or containment (the `jsonb` codec declares only the `equality` trait and the SQL builder has no `->>` or `@>` functions; the workaround is `db.raw.sql`). Also confirmed not supported, for C1's "not yet" list: soft delete, model validations, lifecycle callbacks, custom `Collection` subclasses (`CollectionImpl` has private clone methods), read replicas and multi-database routing, MongoDB referential actions. Each needs a decision: build it, or document the workaround (SQL builder or raw) and say it is not planned. The types work (`Models`, `Shape<>`, where types) is already in PRs. + +**D5. `contract infer` output on Prisma 7 databases.** Users report the inferred contract failing to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether infer on rc.9 still emits removed syntax, and whether the `Decimal @default(0.00)` failure is a bug. Infer should produce a contract that emits. See also D10. + +**D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Either move the RC to a `next` tag until GA or state the policy on C4. Serhii said he would find out why; no update. + +**D7. `db.connect()` versus `db.runtime()`, and `db.close()` versus `db.runtime().close()`.** Two names for adjacent things, used interchangeably across pages, with a Mongo-only `await`, and now a third pair for teardown. `db.prepare` followed by `db.connect()` throws `DRIVER.ALREADY_CONNECTED` because `prepare` connects in the background. If the API can be one call on both targets, the docs get simpler on every page that shows a script. + +**D8. Streaming does not stream.** `postgres()` builds its driver with `cursor: { disabled: true }`, so `for await` over a result iterates an already-buffered array; only the serverless facade exposes cursor batches. The reading-data page promises the opposite. Either expose `cursor` / `batchSize` on `postgres()` or drop the promise (B25). Evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`, `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:39-53`. + +**D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the `db` ref only when `--db` is omitted; with `--db` they do not unless `--advance-ref` is also passed. Every doc example passes `--db`, and the result is `MIGRATION.PLAN_ORIGIN_UNKNOWN` on the second plan. The rule is surprising and undocumented. Consider advancing regardless of how the URL was supplied, or warning when `--db` is used without `--advance-ref` and no `db` ref exists. Related to D1 and D2. Evidence: `cli/src/control-api/operations/ref-advancement.ts:19-28`. + +**D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps `timestamp` / `timestamptz` columns to Temporal-backed `Timestamp` / `Timestamptz`; on Node.js before 26.8.2 (checked: 26.8.1, 24.16, and 22.22 have no `globalThis.Temporal`; 26.8.2 does) every read of such a column throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported first. `create-prisma` installs the polyfill; `orm init` does not, and neither the existing-project page nor the upgrade guide mentions it, so real upgrades with `DateTime` columns break after step 3. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit time with a clear message. Evidence: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`, `packages/3-targets/3-targets/postgres/src/core/errors.ts:74-86`. + +**D11. create-prisma pins rc.8.** `create-prisma@0.11.7` pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` (to match a Composer peer dependency), so a fresh scaffold does not get the rc.9 behaviour the site documents. Either bump on every RC or document the lag. Evidence: `wip/create-prisma-src/src/constants/dependencies.ts:8-10`. + +**D12. Permissive mode is unreachable on Postgres.** `postgres(...)` never forwards a `mode`, so the runtime is always strict and every "warn in permissive mode" path on the lints and budgets pages cannot happen; only `mongo(...)` accepts `mode`. Either expose `mode` on `postgres()` or remove the branches and the docs. Evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. + +**D13. `migration ref set … @db` fails.** `@db` parses to the empty sentinel for the offline command and fails with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the database marker. Either support it (read the marker when a `--db` is available) or reject it with a message that says so. Evidence: `cli/src/control-api/operations/ref.ts:104-118`. + +**D14. The shipped skill is stale in the same places as the site, and a few more.** (Also: `cipherstash.EncryptedString` as the canonical extension example although that package was dropped, `createTelemetryMiddleware` from a package that does not exist, and no mention of the cache middleware.) Will said skills are not the focus, but every audit found the skill wrong where the site is wrong, and it is what agents read. Verified stale in `skills/prisma-8/references/`: `execute` for row reads (should be `query`), `PN-CLI-*` / `PN-MIG-*` / `PN-RUN-*` codes (dotted since 0.17), the flat `defineConfig` config file (envelope since rc.4), `orm init --skip-skills` and the `prisma/contract.prisma` default (`src/prisma/`), "N:M include and nested mutations unsupported" (they work), `pn_meta_marker` (it is `prisma_contract.marker`), `createTelemetryMiddleware` from a package that does not exist, `@@discriminator` / `@@base` "SQL-only" (Mongo has them), scalar lists "rejected" (Postgres accepts them), `-y` for destructive consent (it is `--confirm `), free-function migration factories (they are `this.` methods), `migration show` with no argument (positional required). One ticket to the skills owner with this list; the audit files have the line numbers. + +**D15. `db update` never plans data operations.** Its allowed classes are additive, widening, destructive; a change that needs a backfill fails and the user must switch to `migration plan`. Undocumented. Either allow it or print the switch hint. Evidence: `cli/src/control-api/operations/db-update.ts:17`. + +**D16. `migration status` exits 0 on warnings.** CI must parse `--json` `diagnostics[]` to catch `MIGRATION.DIVERGED`, `MARKER_NOT_IN_HISTORY`, `CONTRACT.AHEAD`, `NO_MARKER`. A `--strict` flag or a non-zero exit on warn-level findings would make C11 one line. Evidence: `cli/src/orm/migration/status-findings.ts`. + +**D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` and the site's capabilities page disagree on key namespacing (`sql.lateral` vs `postgres.lateral`), pack key nesting, the error code spelling, and whether capabilities are negotiated at connect time or fixed at emit time. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`; the scaffold says 22.18 and the flag does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md` (from which the site's ORM error reference is generated word for word) still writes `ref set`, `ref list`, and `prisma ref set ` in eight entries; the mounted command has been `migration ref set` since rc.5, so the fix belongs in the error definitions' `fix` text. `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Whoever owns `docs/` in the monorepo should reconcile these before the site is written from them; until then the audit treats `packages/` and `docs/releases/` as the only truth. + +**D18. create-prisma's MongoDB scaffold writes a `.env` nothing reads.** For MongoDB the scaffold writes `.env` with `DATABASE_URL`, but the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file, so the file is dead and the CLI's own next-step text says to set `MONGODB_URL` in the environment. Found during the PR 3 review. Evidence: `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`, `src/tasks/prisma-setup/presentation.ts:46`. + +## Unverified, carried from the audits + +Things the agents flagged but could not confirm against the monorepo, mostly because the `prisma` binary and `@prisma/cli-engine` live in the uncloned `prisma-cli` repo. Check before acting: the global `--yes` flag on `db migrate`; `cli/global-flags.mdx`, `cli/init.mdx`, `cli/skills.mdx` wholesale; `definePrismaConfig` from `prisma/config` versus `@prisma/cli-engine`; `HostedStateBootstrapError` and `--name`; Mongo `_id` decoding through `$lookup` and `findOneAndUpdate`; `_id` equality inside `match()`; the apply order of extension spaces versus `app`; whether `DateTime` still parses in PSL now that the starter contract writes `TimestamptzString`; the raw `EXTRACT(...)` codec claim; the `ilike` `fns` helper; "ParadeDB and Supabase are experimental"; which agent directory list is current (`ai/tools/skills.mdx` says Claude Code, Cursor, Codex, Windsurf; `cli/skills.mdx` and the scaffold say `claude`, `cursor`, `agents`, `devin`); whether `npx skills add` wants `prisma/prisma/skills` or `prisma/orm/skills`; the real capability key strings (see D17). Full list in the `## Unverified` section of each audit file. diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md new file mode 100644 index 00000000000..eae7f207300 --- /dev/null +++ b/docs/orm-docs-audit/ia.md @@ -0,0 +1,178 @@ +# Information architecture: proposal + +Proposal first, then why, then the current state it changes. Source: the `meta.json` files and page titles in `wip/web/apps/docs/content/docs/` on 2026-09-10. Labels are what the sidebar shows. + +## Proposed + +Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and two labels under Guides. Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. + +### Getting Started > Prisma ORM + +``` +Prisma ORM + Introduction to Prisma 8 human content first, agent prompt last + + Prisma 8 release status RC, GA window, 7 support period, what npx prisma installs, how to pin 7 + ~ Start a new app was "Quickstart"; same two pages + PostgreSQL + MongoDB + + Add to an app you already have empty or no database: orm init, contract, emit, db init, first query, db.ts shown + PostgreSQL + MongoDB + ~ Adopt an existing database was "Add to Existing Project"; adds baseline, ref, second migration + PostgreSQL + MongoDB + + Coming from Prisma 7 link to the ORM page below, so the Upgrader finds it from here + + Editor setup + create-prisma reference; moved to last +``` + +Four starting states, one group each. "Coming from Prisma 7" is a link node here because the page itself belongs with the API it maps. + +### ORM > Introduction + +``` +Introduction + Prisma 8 + + Coming from Prisma 7 the mapping page: schema and types, CLI, client API, not-yet list + ~ Core concepts rewritten as narrative from mental-model.md; glossary kept at the end +``` + +### Guides + +``` +Overview remove "Upgrading: moving from Prisma 7" from the coming-soon list +Upgrade Prisma ORM + ~ Prisma 7 to 8 (PostgreSQL) was "PostgreSQL" + ~ Prisma 6 to 8 (MongoDB) was "MongoDB" + v7, v6, v5, v4, v3, v1 +``` + +### The ORM root page (`/orm`) + +Today the page has five sections: "Your schema becomes a contract", "What changed for developers", "Supported databases", "Get started" (three cards), "Go deeper" (five cards), and "Learn more about the design of Prisma 8" (five blog links). Three of the six argue for the design against Prisma 7. There is no query on the page. A Newcomer cannot tell from it what the product does; an Upgrader is told why it is different before being shown what it is. + +Proposed structure, in order: + +1. One sentence saying what it is: a typed data layer for TypeScript, for PostgreSQL, MongoDB, and SQLite. +2. The product in one screen: a short contract, the query it enables, and the typed result, side by side. Nothing else above the fold. +3. The four starting-state doors from the Getting Started subtree. +4. What you can do with it: one line and one link each for modeling, querying, relations, transactions, migrations, middleware, extensions. This is the section map, not an argument. +5. Coming from Prisma 7: one line linking to the mapping page. +6. Release status: one line linking to the status page. + +Removed from this page: the three-step workflow explanation, "What changed for developers", and the blog list. The first moves into Core concepts; the other two go, or the blog list moves to the bottom of Core concepts. + +### Root page (`/`) + +The ORM line becomes a short row with the four starting states, linking into the subtree above. The platform hero stays. + +### What each proposed node fixes + +| Node | Jobs | +| --- | --- | +| Prisma 8 release status | J4 | +| Add to an app you already have | J1 | +| Adopt an existing database (rewritten) | J2 | +| Coming from Prisma 7 | J3, J5 (links to the incremental guide), J6 (attribute map) | +| Editor setup | J7 | +| Guides labels and overview line | J5 | +| Core concepts rewritten | the "written for AI" complaint, by giving the Newcomer a why-first page | + +J8, J9, and J10 need product decisions or shipped code before a node makes sense; they are in `changes.md` under C and D. + +### Not proposed + +No change to the top-level section list, to Data Modeling, Contract Authoring, Fundamentals, Migrations, Middleware, Extensions, Reference, or to any Guides subtree except the two labels. The "Prisma 7" group at the bottom of Getting Started stays as the home for people staying on 7. + +## Why: where each job lands today, and where the structure fails it + +| Job | Lands on | Structural failure | +| --- | --- | --- | +| J1 existing app, empty database | Add to Existing Project > PostgreSQL | page assumes tables exist; no node for this state | +| J2 existing database with data | Add to Existing Project > PostgreSQL | right node, page stops before the ref step | +| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; content spread over nine pages | +| J4 should I move now | root, `/prisma-orm` | no node; note box only says 7 is supported | +| J5 incremental upgrade | Guides > Upgrade Prisma ORM > PostgreSQL | not linked from any ORM node; label hides it | +| J6 data types | Data Modeling > Overview | right node; one stale example | +| J7 editor setup | none | no node | +| J8 advanced Postgres | none | no node; needs product answers | +| J9 types | none | no node; API in PRs | +| J10 opt out of agent files | CLI > configuration | right node, unreachable from Getting Started | + +Two observations follow from the table. + +First, the Getting Started > Prisma ORM subtree is organised by the tool that runs (`create-prisma` for Quickstart, `orm init` for Add to Existing Project) and then by database. The reader does not know those tools yet. The failures in J1 and J2 both happen at the point where the reader's situation differs from the page's assumption about it. The reader knows their situation: do I have an app, do I have a database, does it have data, was it Prisma 7. That is why I proposed organising this subtree by starting state. The database split (PostgreSQL / MongoDB) stays inside each. + +Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides with a database name as its label. + +## Current state + +Top-level sections, in nav order: Getting Started, ORM, Composer, Local development, AI, Compute, Postgres, Storage, Studio, Query insights, Console, Guides, CLI, REST API, Accelerate. + +### Getting Started + +``` +Start + Get started with Prisma / platform landing; ORM is one line + Choose a Prisma 8 setup path /getting-started + Deploy the full Prisma stack /full-stack-tutorial + Deploy your first app /prisma-compute/deploy +Prisma ORM + Introduction to Prisma 8 /prisma-orm + create-prisma /prisma-orm/create-prisma + Quickstart + PostgreSQL /prisma-orm/quickstart/postgresql + MongoDB /prisma-orm/quickstart/mongodb + Add to Existing Project + PostgreSQL /prisma-orm/add-to-existing-project/postgresql + MongoDB /prisma-orm/add-to-existing-project/mongodb +Prisma Postgres + (quickstarts per ORM, import from existing database, from the CLI) +Prisma 7 + Prisma 7 setup paths /v7/getting-started (for people staying on 7) +``` + +### ORM + +``` +Introduction + Prisma 8 /orm + Core concepts /orm/core-concepts +Data Modeling + Overview, Relational data modeling, MongoDB data modeling +Contract Authoring + The data contract, Author in PSL, Author in TypeScript, The emitted artifacts, Capabilities +Fundamentals + Reading data, Writing data, Relations and joins, Transactions, Advanced queries +Migrations + How migrations work, The migration graph, Generating, Editing, Applying, Rollbacks and recovery +Middleware + How middleware works, Built-in: budgets, lints, cache, Authoring custom middleware +Extensions + Using extensions +Reference + API reference, ORM client, SQL query builder, Pipeline builder, Raw queries, Transactions and runtime, Error reference +``` + +### Guides (ORM-relevant parts) + +``` +Overview /guides says "Upgrading: moving from Prisma 7" is coming +v7 +Frameworks (Next.js, Hono, TanStack Start, NestJS, Astro, Nuxt, SvelteKit, Elysia, React Router 7, SolidStart) +Runtimes (Bun, Deno) +Deployment, Authentication, Integrations, Postgres +Database (Expand-and-contract migrations, Multiple databases, Schema management in teams) +Switch to Prisma ORM, Switch to Prisma Postgres +Upgrade Prisma ORM + PostgreSQL /guides/upgrade-prisma-orm/postgresql title: "Migrate from Prisma 7 to Prisma 8" + MongoDB /guides/upgrade-prisma-orm/mongodb v6 Mongo to 8 + v7, v6, v5, v4, v3, v1 older version-to-version guides +Making guides +``` + +### Where Prisma 7 readers are pointed today + +- Root page: one line, "Here for the ORM? Jump straight to Prisma 7 or Prisma 8". +- A "Using Prisma 7?" note box on `/orm`, `/prisma-orm`, both PostgreSQL getting-started pages, and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. +- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides, where the label is "PostgreSQL". diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md new file mode 100644 index 00000000000..b2bd7e7bcc7 --- /dev/null +++ b/docs/orm-docs-audit/journeys.md @@ -0,0 +1,147 @@ +# Jobs users come to the docs to do, and how the docs serve them today + +Each job has: who, where they land, what "done" looks like, the path through the current site, and a verdict. Paths were traced in the `prisma/web` source at `wip/web/apps/docs/content/docs/` and checked against the live site on 2026-09-10. Verdicts: **green** works, **amber** works with friction, **red** fails or is missing. + +## J1. Add Prisma 8 to an app I already started, with an empty database + +Who: Newcomer, sometimes Upgrader. The Bun user in Discord is this job. + +Done: models defined, tables created, one query returns rows, from inside the app they already have. + +Path today: + +- Search "prisma bun" lands on the Bun guide. It starts with `create-prisma`, so it scaffolds a new app instead of joining theirs. +- `/getting-started` offers "Add to an existing project", which goes to the existing-project PostgreSQL page. That page assumes the database already has tables: step 4 is `contract infer`. There is no branch for "empty database". +- The right three commands (`orm init`, `contract emit`, `db init`) exist only as a snippet on the CLI reference overview, under "Start in an existing project". +- Whichever page they use, the query example is wrong: the existing-project page uses `db.orm.User` (must be `db.orm.public.User` on Postgres) and `.take(2)` (removed in rc.7). +- `orm init` writes `src/prisma/db.ts`, but no getting-started page shows the file, so `import { db } from "./prisma/db"` is unexplained. +- The quickstart says scripts read `DATABASE_URL` from the environment, not `.env`; the existing-project page uses `.env` with `dotenv/config`. The two pages disagree and neither says why. +- The existing-project script calls both `db.connect()` and `db.runtime()`. The difference is explained only deep in the transactions-and-runtime reference. +- Skill files land in the repo with no mention of how to stop that. + +Verdict: **red**. No page is written for this job, and the nearest page has two copy-paste errors. + +## J2. Bring an existing database with data under Prisma 8, then make the next schema change + +Who: Upgrader mostly, some Newcomers with a legacy database. + +Done: contract matches the database, database is signed, first query works, and `migration plan` for the next change produces one small migration rather than a full recreate. + +Path today: the existing-project PostgreSQL page, steps 2 to 9. + +- Steps 2 to 7 are in the right order: init, connection, infer, review, emit, sign, query. +- Step 4 says "review the inferred contract" but not what to expect. Users hit `@db.*` attributes (removed in 0.17), non-`public` schemas, and a `Decimal` default that fails to emit, with no guidance. +- Step 6 signs the database but never explains what a signature is or what to do if `db sign` exits 4. +- Step 9 says "use `db update` or `migration plan`". It never mentions the `db` ref. `db sign` does not set the ref (only `db init`, `db update`, and `db migrate --advance-ref` do). With no migrations on disk and no ref, `migration plan` silently plans from an empty database and proposes recreating every table. This is the `--from` confusion reported twice in Discord. +- The upgrade guide gets this right (baseline migration, sign, `migration ref set db`, then `--advance-ref db` on each migrate), but J2 users on the existing-project page never see it. + +Verdict: **red**. The page stops one step short and the missing step produces a destructive-looking plan. + +## J3. Rewrite Prisma 7 queries in Prisma 8 + +Who: Upgrader. + +Done: for every Prisma 7 call in their code, they know the Prisma 8 call or that it does not exist. + +Path today: + +- No single mapping page. Sixteen inline "For Prisma 7 users" diff blocks are spread across reading-data, writing-data, transactions-and-runtime, pipeline-builder, data-modeling, and eight places in the ORM reference. +- Pagination is taught as `.take()`/`.skip()` on eight pages (29 sites). Those were renamed to `.limit()`/`.offset()` in rc.7 and the old names removed. +- The bulk count mutations are taught as `createCount`/`updateCount`/`deleteCount` (31 sites on two pages). They were renamed to `createAndCount` and friends in 0.17. +- `createMany` appears on no Prisma 8 page. `createAll` and `createAndCount` are documented but nothing says they replace it. `skipDuplicates` has no equivalent and no page says so. +- `findUniqueOrThrow`, `findFirstOrThrow`, atomic `increment`/`decrement`, and case-insensitive filters have no Prisma 8 equivalent in the SQL ORM client source. No page says so. +- `$transaction([...])` is covered in one inline block. `Prisma.UserGetPayload` and the model types have no page at all; the replacements are in open PRs. +- Accessor casing (`prisma.user` became `db.orm.public.User`) is stated once in reading-data and nowhere else. + +Verdict: **red**. The answers that exist are scattered, two of them are wrong, and the missing features are not admitted. + +## J4. Decide whether to move to Prisma 8 now + +Who: Upgrader, also a Newcomer choosing an ORM. + +Done: they know Prisma 8 is a release candidate, when GA is expected, how long 7 is supported, what `npx prisma` now installs, and how to pin 7. + +Path today: the root page says "Prisma 7 remains fully supported" and shows `npx prisma@7.10.0 init`. Nothing on the site says Prisma 8 is an RC, gives a GA window, states the 12-month support commitment for 7, or explains the npm `latest` tag. Five people asked this in Discord in one week. + +Verdict: **red**, and the cheapest fix on the list. + +## J5. Migrate a whole Prisma 7 app incrementally + +Who: Upgrader with a team and a production database. + +Done: both versions run side by side, routes move one at a time, migrations hand over, Prisma 7 is removed. + +Path today: `guides/upgrade-prisma-orm/postgresql` covers all five phases and is the best page on the site for the Upgrader. Getting there is the problem: the root page, `/getting-started`, and the ORM overview never link to it. The guides index lists "Upgrading: moving from Prisma 7" under "Coming as they land". In the sidebar it sits under "Upgrade Prisma ORM" as "PostgreSQL", with no "7 to 8" in the label. It is also pinned to rc.6 and rc.4 and says so in a callout. + +Verdict: content **amber**, discoverability **red**. + +## J6. Model my data, especially types Prisma 7 handled with `@db.*` + +Who: Newcomer and Upgrader. + +Done: they can write `Text`, `VarChar(100)`, `Uuid`, `Decimal`, enums, relations, and know which Prisma 7 attributes are gone. + +Path today: + +- The data-modeling overview has a scalar table (`String` is `Text`) and a money-in-cents recommendation. Good. +- The PSL syntax page shows `Uuid = String @db.Uuid` in its opening example and again at line 177. That syntax was removed in 0.17. Copying it fails emission. +- No page maps Prisma 7 attributes (`@db.Text`, `@db.VarChar(n)`, `@db.Decimal(p,s)`) to Prisma 8 types. +- `Decimal` defaults and money beyond "use cents" are not covered. One user asked and got no answer. +- Implicit many-to-many is honestly marked unsupported. Good. + +Verdict: **amber**, with one stale example that must go. + +## J7. Set up my editor + +Who: Newcomer and Upgrader. + +Done: syntax highlighting and formatting work for `contract.prisma`. + +Path today: no page. The facts (extension is on open-vsx not the Microsoft marketplace, no bundled language server, needs the CLI installed locally, file needs `// use prisma-next` on line one) were given by Serhii in a Discord thread. The `// use prisma-next` line appears in examples but is never explained. + +Verdict: **red**, missing. + +## J8. Use advanced Postgres features + +Who: Newcomer and Upgrader on real projects. RLS, policies, expression and functional indexes, extensions such as pg_trgm. + +Done: they know whether the contract can express it, and how, or that they must manage it outside Prisma. + +Path today: nothing under `orm/`. RLS is covered only through the Supabase extension in the shipped skill. One user's agent invented a contract-builder API because there was nothing to read. + +Verdict: **red**, missing. Needs a product answer before a docs answer. + +## J9. Name a model or result type for reuse + +Who: Newcomer and Upgrader. + +Done: `type User = ...` and the type of a query result, without reading `contract.d.ts`. + +Path today: no page. `ResultType` for SQL builder plans is the only documented helper. The `Models` namespace, `Shape<>`, and where-type exports are in open PRs. + +Verdict: **red** until the PRs ship, then a page is needed on release day. + +## J10. Stop Prisma from writing agent files into my repo + +Who: Newcomer and Upgrader, five people in one week. + +Done: one config line, and they know it. + +Path today: `skills: { agents: [] }` is documented on the CLI configuration page and `init --skills=none` on the init page. Neither is linked from create-prisma, the quickstarts, or the existing-project page. The advice circulating in Discord (`skills sync --disable`, an env var) is wrong. `create-prisma` has no flag. + +Verdict: **amber** for docs, **red** for the tool. + +## Summary + +| Job | Verdict | Cheapest fix | +| --- | --- | --- | +| J1 existing app, empty DB | red | new page | +| J2 existing DB, next migration | red | add baseline and ref steps | +| J3 Prisma 7 query mapping | red | one mapping page plus rename fixes | +| J4 should I move now | red | one short page, linked from root | +| J5 incremental upgrade | amber / red | links and a nav label | +| J6 data types | amber | remove `@db.` example, add attribute map | +| J7 editor | red | new page | +| J8 advanced Postgres | red | product decision first | +| J9 types | red | page on PR merge | +| J10 agent files | amber | one line on three pages | diff --git a/docs/orm-docs-audit/mental-model.md b/docs/orm-docs-audit/mental-model.md new file mode 100644 index 00000000000..8f70f0eeafb --- /dev/null +++ b/docs/orm-docs-audit/mental-model.md @@ -0,0 +1,112 @@ +# The Prisma 8 mental model, from first principles + +This is the source we write docs pages from. It explains why Prisma 8 has the pieces it has, in the order a person meets them. Everything here was checked against the monorepo glossary, the architecture overview, and the rc.9 release notes. + +## The one idea + +Your application and your database each have an opinion about what the data looks like. In Prisma 7 the schema file was the only written-down version, and the generated client trusted that the database matched it. Prisma 8 makes the agreement explicit and checkable from both sides. Everything else follows from that. + +## Two things, not one: the contract and the schema + +The **contract** is what you write. It is your description of the models, fields, relations, and how they map to tables. It lives in your repository, in `contract.prisma` or in TypeScript. + +The **schema** is what the database actually has right now: the tables, columns, and indexes. + +Prisma 7 called your file the schema. Prisma 8 reserves that word for the database side, because the whole point is that the two can disagree. When a command or error says "schema", it means the database. + +Every Prisma 8 operation is a relationship between these two: queries are typed against the contract, migrations move the schema toward the contract, and verification checks that the schema still satisfies the contract. + +## Emit: the build step that replaces `prisma generate` + +Prisma 7 generated a client package from your schema. Prisma 8 emits two plain files from your contract: + +- `contract.json`, a canonical description of the models, storage layout, and the database features it needs. +- `contract.d.ts`, the TypeScript types derived from it. + +The command is `prisma contract emit`. It is deterministic, so the same source always produces byte-identical output, and you commit both files. Think of the pair as `package.json` and its lockfile: the source is what you asked for, the artifacts are the resolved result. + +Why a build step at all: every other tool reads the artifacts, not your source. The query APIs read the types. The migration planner diffs two `contract.json` files. The runtime compares `contract.json` with the database. That is why "emit first" comes before almost every other command, and why forgetting it produces stale types or an empty migration plan. + +## The signature: how the database says which contract it satisfies + +Because emit is deterministic, hashing `contract.json` gives a short identifier for that exact contract, the way a commit hash identifies an exact state of your code. + +The database stores a small marker record, the **signature**, naming the contract hash it currently satisfies. Three commands write it: + +- `db init` creates the tables for the contract in an empty database and signs it. +- `db sign` checks that an existing database already matches the emitted contract and, if so, signs it. This is how you adopt a database you did not create with Prisma 8. +- `db migrate` applies a migration and updates the signature to the migration's target hash. + +`db verify` reads it and reports **drift**: any disagreement between contract and schema. + +Why this exists: a deploy against an unmigrated database, or a migration run against the wrong database, is caught before any query runs, because the runtime and the migration runner both check the signature first. In Prisma 7 the same mistake produced wrong results or a failed query later. + +## Queries: every query becomes a plan + +All query APIs are typed against `contract.d.ts`. Each query compiles to a **plan**, a plain data object holding the statement, its parameters, and metadata about what it touches. Running the plan is a separate step. + +Why: one pipeline. The ORM client, the SQL builder, and raw SQL all reach the database as plans, so middleware, telemetry, budgets, and authorization see every query in the same shape. A plan is data, so it can be inspected before anything touches the database. + +The three query surfaces on Postgres, from highest to lowest: + +1. The **ORM client**: `db.orm.public.User.where({ ... }).all()`. Model-based, coordinates several statements for `.include()`, hands back one typed result. Start here. +2. The **SQL builder**: `db.sql.public.user.select(...).where(...).build()`. Composable joins, grouping, and projections. One plan is exactly one statement. +3. **Raw fragments** spliced into builder queries when the builder cannot express it. + +Why `db.orm.public.User` and not `prisma.user`: Postgres tables live in schemas, and Prisma 8 addresses models through the schema namespace so a contract can span more than one. `public` is the default schema. Aliasing by assignment (`const User = db.orm.public.User`) is fine. On MongoDB the key is the collection's storage name (`db.orm.users`) and there is no SQL builder. + +## Migrations: edges between contract hashes + +A migration is a step from one contract hash to another. Together they form a graph, not a timestamped list. Every migration records the hash it starts from and the hash it produces. + +`migration plan` diffs two contracts and writes a migration package. The target is always your emitted contract. The origin is, in order: `--from` if you pass it, otherwise the `db` ref, otherwise an empty database. + +The `db` **ref** is a named pointer to a contract hash, kept in the repo, meaning "the state I consider the database to be at". `db init`, `db update`, and `db migrate --advance-ref db` move it. `db sign` does not. + +Why this matters more than it seems: a project with no `db` ref plans every migration from empty, which proposes recreating every table. This is the trap for anyone who adopts an existing database with `db sign` and then runs `migration plan`. The fix is a baseline migration plus `migration ref set db ` once, then `--advance-ref db` on each migrate. The incremental upgrade guide does this; the existing-project page does not. + +Why a graph and not a list: two branches can each add a migration, and the graph resolves the merge by hashes instead of by timestamp order. Partial failures are safe to retry because each edge has a verifiable precondition. + +`db update` is the development shortcut: diff the contract against the live database and apply the difference directly, no migration package, ref advanced for you. Use it while iterating; use `migration plan` plus `db migrate` when you want the change checked in. + +## The command vocabulary in one table + +| Command | Reads | Writes | When | +| --- | --- | --- | --- | +| `contract emit` | contract source | `contract.json`, `contract.d.ts` | after every contract change, before anything else | +| `db init` | emitted contract | tables, signature, `db` ref | empty database, first time | +| `db sign` | emitted contract, live schema | signature | adopting a database that already matches | +| `db verify` | emitted contract, live schema | nothing | check for drift | +| `db update` | emitted contract, live schema | schema diff, signature, `db` ref | development iteration | +| `migration plan` | origin contract, emitted contract | a migration package | change you want checked in | +| `db migrate` | migration packages, signature | schema, signature, `db` ref with `--advance-ref` | apply checked-in migrations | +| `migration ref set` | a hash | the ref | after a baseline, or to repoint | +| `contract infer` | live schema | a draft contract source | first contract for an existing database | + +## What moved from Prisma 7, and why + +| Prisma 7 | Prisma 8 | Why | +| --- | --- | --- | +| `schema.prisma` | `contract.prisma` | the file describes an agreement, not the database | +| `prisma generate` | `prisma contract emit` | data artifacts instead of a generated client | +| `prisma migrate dev` | `db update` (dev) or `migration plan` + `db migrate` | plans are explicit and reviewable | +| `prisma db push` | `db update` | same job, now also signs | +| `prisma db pull` | `contract infer` | produces a contract draft | +| `new PrismaClient()` | `postgres({ contractJson, url })` in `db.ts` | the client is built from the contract at runtime | +| `prisma.user.findMany({ where })` | `db.orm.public.User.where(...).all()` | chainable, namespace-qualified | +| `findUnique` / `findFirst` | `.first()` | one terminal for one row | +| `{ data: { ... } }` | the fields directly | no wrapper | +| `take` / `skip` | `.limit()` / `.offset()` | renamed in rc.7 | +| `createMany` | `createAll` (rows back) or `createAndCount` (count back) | the return shape is in the name | +| `$transaction([...])` | `db.transaction(async tx => ...)` | callback form only | +| `@db.Text`, `@db.VarChar(n)` | `Text`, `VarChar(n)` in type position | native types are types, not attributes | +| `Prisma.UserGetPayload<...>` | `Shape<...>` (in an open PR) | not shipped yet | +| `skipDuplicates`, `increment`, `findUniqueOrThrow`, `mode: "insensitive"` | no equivalent yet | say so plainly | + +## The eight words + +**Contract**: what you write. **Schema**: what the database has. **Emit**: build the contract into artifacts. **Hash**: the identifier of one exact contract. **Signature**: the database's record of which hash it satisfies. **Drift**: the two disagree. **Plan**: a compiled query or migration, as data. **Ref**: a named pointer to a hash, used as the migration origin. + +## What the model costs, honestly + +Two extra concepts before the first query: the emit step and the signature. Prisma 7 had neither. The docs must pay that cost back on the same page by showing what it buys: a deploy that refuses to run against the wrong database, a migration plan you can read before it runs, and a query you can inspect before it executes. If a page introduces the concept without the payoff, cut the concept from that page. diff --git a/docs/orm-docs-audit/naming.md b/docs/orm-docs-audit/naming.md new file mode 100644 index 00000000000..7e9752c14f7 --- /dev/null +++ b/docs/orm-docs-audit/naming.md @@ -0,0 +1,37 @@ +# Naming: the product is "Prisma ORM" + +## The rule + +"Prisma ORM" names the product. A version number appears only when two versions are being told apart. So: + +- "Add Prisma ORM to an existing project", not "Add Prisma 8 to an existing project". +- "Prisma ORM emits the contract", not "Prisma 8 emits the contract". +- "Coming from Prisma ORM 7" and "Migrate from Prisma ORM 7 to 8" keep the numbers, because the contrast is the point. +- The release status page says "Prisma ORM 8 is a release candidate; Prisma ORM 7 is supported until ...". +- The Prisma 7 docs trees (`orm/v7`, `(index)/v7`, `guides/v7`, `cli/v7`) keep their version label in the nav, because that is what they are. + +"Prisma 8" as a bare product name reads as a different product from "Prisma ORM", which is the Upgrader's fear stated back to them. It also collides with the platform, where "Prisma" alone means the whole stack. + +## How to do it + +Not a global replace. Each of the 109 files needs a read, because "Prisma 8" in a contrast sentence becomes "Prisma ORM 8" and elsewhere becomes "Prisma ORM". Do it per page as each page is touched by the restructure and the content fixes, and sweep the remainder at the end. The 96 titles are the visible part and should go first, since they are the sidebar and the browser tab. + +## What stays as is + +- Identifiers: `prisma-next.md`, `// use prisma-next`, `@prisma/orm-postgres`, `/studio/prisma-next`, package names, error codes. 40 occurrences of `prisma-next` as an identifier; none as prose ("Prisma Next" appears zero times on the site). +- The "Prisma 7" group at the bottom of Getting Started and the v7 doc trees. +- Release notes and changelogs, which name versions by nature. + +## Scope on the site today + +Outside the v6 and v7 trees: + +| Term | Occurrences | Files | +| --- | --- | --- | +| "Prisma 8" | 691 | 109 | +| "Prisma 7" | 198 | 33 | +| "Prisma ORM" | 2816 | 95 | + +By area: `orm/` 225, `guides/` 196, `(index)/` 135, `cli/` 81. 96 page titles or meta titles contain "Prisma 8". No sidebar label does; the labels come from titles. + +The most common sentence shapes ("Add Prisma 8 to an ...", "Prisma 8 is the ...", "Prisma 8 app with ...", "Prisma 8 skills for ...") all take "Prisma ORM" as a drop-in replacement. The ones that do not are the contrast sentences, which should keep the number and add "ORM". diff --git a/docs/orm-docs-audit/personas.md b/docs/orm-docs-audit/personas.md new file mode 100644 index 00000000000..7a95be649fe --- /dev/null +++ b/docs/orm-docs-audit/personas.md @@ -0,0 +1,33 @@ +# Who reads the Prisma 8 docs + +Four readers arrive at the docs. The first two produce almost all the complaints. The docs outside `orm/` are built for the third. The fourth never complains. + +## The Newcomer + +Has never used Prisma. Has an app, or is about to start one, and wants typed queries against a database. Arrives from npm, a search result, or a framework tutorial. Often already ran `bun init` or `npm create next-app` before looking for an ORM, so scaffolding tools that create the app for them are the wrong shape. + +What they need on the first visit: install, define models, connect, run one query, in one sitting. They will accept one new idea (the contract) if it pays off on the same page. They will not read a philosophy page first. + +How they judge the docs: can I copy the example and does it run. + +## The Upgrader + +Has used Prisma 5, 6, or 7. Has a running app, a database with data in it, and a migration history. Arrived because `npx prisma` installed Prisma 8 without them choosing it, or because they saw the announcement. Most of the Discord complaints are from this reader. + +What they need: first, a straight answer on whether to move now and how to stay on 7 if not. Second, the Prisma 8 name for every Prisma 7 thing they know, or a plain statement that it does not exist yet. Third, the exact sequence to bring an existing database under Prisma 8 control and make the next migration work. + +How they judge the docs: against the mental model they already have. Every page that explains contracts before answering "where did `findMany` go" costs trust. + +## The Builder + +Wants to ship a product on the Prisma platform: Composer, Compute, Postgres, Storage. May be technical, may lean on a coding agent. The ORM is one component. Happy to have tools scaffold the app and happy to hand a prompt to an agent. + +The docs root, the framework guides, the agent prompts, and the full-stack tutorial serve this reader well. They are not the problem, but their content occupies the entry points the Newcomer and the Upgrader land on. + +## The Agent + +Reads the shipped skill, `llms.txt`, and the `.md` version of any page. Never complains. The skill is out of scope for this audit except where the human pages feed into it. + +## What this means for the audit + +The ORM entry points must serve the Newcomer and the Upgrader before the Builder. Today the order is reversed: the root page is the Builder's, the ORM landing opens with an Agent prompt, and the Upgrader gets a two-line note saying Prisma 7 still exists. diff --git a/docs/orm-docs-audit/slice-corrections.md b/docs/orm-docs-audit/slice-corrections.md new file mode 100644 index 00000000000..e7d5d50e5ac --- /dev/null +++ b/docs/orm-docs-audit/slice-corrections.md @@ -0,0 +1,83 @@ +# Slice 1: corrections to published pages + +Scope: fix what is wrong on pages that exist today, without moving, adding, or removing pages. Everything in `changes.md` section B, plus A4 (two label edits). Sections A, C, D are out of scope and come after the IA discussion. Each fix cites the rc.9 source line it was verified against; the audit files under `audit/` hold the line lists. + +## Proposed batches + +Three PRs to `prisma/web`, in this order. Each is reviewable on its own and does not depend on the others. + +### PR 1: mechanical renames (about 350 lines, 20 pages) + +Search-and-replace with a known correct form. Low judgement, high volume. Reviewer checks the diff is uniform. + +| Item | What changes | Pages | +|---|---|---| +| B11 | `execute(plan)` to `query(plan)` for row reads; Mongo `db.execute(plan)` to `(await db.runtime()).query(plan)`; `ps.execute` to `ps.query`; drop `executePrepared`. Writes with no returned rows stay on `execute`. | 14 | +| B1 | `.take()`/`.skip()` to `.limit()`/`.offset()`; keep Mongo pipeline `skip` stages | 8 | +| B2 | `createCount` and siblings to `createAndCount` and siblings, including headings | 2 | +| B12 | drop the `sha256:` prefix on every hash | 9 | +| B13 | `extensionPacks` to `extensions` | 2 | +| B14 | migration directory listing and `migration.ts` imports to the `migrations/snapshots//` layout | 3 | +| B4 | remove `@db.Uuid`; re-point the named-types example at a real alias | 1 | +| B21 | stale flags, codes, command names, and printed output (`--skip-skills`, `CLI.INIT_SKILL_INSTALL_FAILED`, bare `ref set`, `prisma-cli` hints, `PN-RUN-3000`, `from: null`, the "Applied 1 migration(s)" line, `cd prisma`, top-level `migrate`, hyphenated slugs, `--db` shown as required) | 10 | +| B23 | `db.runtime().close()` to `db.close()` | 4 | +| B26 | enum ordering note updated for rc.9 | 1 | + +### PR 2: page rewrites (about 12 pages) + +Sentences change, not just names. Each page gets one commit so the reviewer can read it as prose. + +| Item | Page | What changes | +|---|---|---| +| B15 + B3 + B10 | both `add-to-existing-project` pages | default path is `src/prisma/`; `orm init` writes no skills; `.env` is a prompt; show `db.ts` once; one `DATABASE_URL` story; Temporal polyfill note; `--write-env` / `--schema-path`; `db.orm.public.User` | +| B16 | six `orm/migrations/*`, `cli/migration-plan`, `cli/db-init`, `cli/db-update`, `cli/migration-ref`, `cli/index`, upgrade guide | `migration plan` refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN`; `db init` / `db update` advance the ref only without `--db`; `NO_TARGET` belongs to `migration new`; the automatic baseline and `--from @empty` | +| B17 | five `orm/middleware/*` | two lifecycles, no `intercept`; rewrite the logger example on `afterQuery`; fix lint keys, budgets latency, cache hooks; drop "permissive mode" on Postgres | +| B18 | `orm/reference/raw-queries`, `advanced-queries` | whole-query raw SQL exists; `db.raw.sql`; drop the "unversioned ids" callout | +| B19 | `relations-and-joins`, `data-modeling/relational-databases` | 1:1 back side, N:M include and nested writes, referential actions, `.variant()` all work; stop sending readers to the SQL builder | +| B20 | `sql-query-builder`, `advanced-queries`, `orm-client` | aggregates return numbers; the `BigInt` / `Decimal` variants; `min` / `max` typing | +| B22 | `editing-a-migration` | add `rawCodecInferer` so the data-transform example typechecks | +| B24 | `writing-data` | upsert needs `conflictOn` | +| B27 | `transactions-and-runtime`, `pipeline-builder` | structured error codes, not plain `Error`; fix the `prepare` then `connect()` sample | +| B31 | `data-modeling/index` | scalar table: `Json` vs `Jsonb`, add `Decimal`, `Bytes` | +| B35 | `using-extensions` | the recipe does not fit Supabase; catalog links lead to `@internal` install commands | + +### PR 3: start pages and guides, small facts (about 20 pages) + +One-line or one-paragraph facts on the getting-started pages and guides. + +| Item | What changes | +|---|---| +| B5 | SQLite ships; `orm/index` and `sql-query-builder` | +| B6 | upgrade guides: version pins, `Database signed` output, the CREATE TABLE symptom that no longer appears | +| B8 | one Node floor, stated once (needs decision 2) | +| B9 | explain `// use prisma-next` where the contract is introduced | +| B28 | `create-prisma` page: `minimal` template, no `.env` for Postgres, `--force`, deploy defaults, Deno flag, script list | +| B29 | MongoDB pages: replica set is not required | +| B30 | Bun guide build and dev scripts; NestJS `@Inject` note; TypeScript authoring paths; Deno page staleness | +| B32 + A4 | guides index and the upgrade guide's sidebar label | +| B33 | `ai/tools/skills` page: one skill, no `--skip-skills`, `orm init` does not install | +| B34 | full-stack tutorial: `TimestamptzString`, no `postinstall` | +| B7 | the agent-files line on four pages (needs decision 1) | +| B25 | streaming claim on `reading-data` (needs decision 3) | + +## What this slice does not do + +- It does not touch the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7). They are wrong for a Prisma ORM 8 reader, but fixing them means moving or rewriting whole pages, which is the IA discussion. If you want something now, the smallest honest change is a one-line banner at the top of each saying it is written for Prisma ORM 7; say so and I will add it to PR 3. +- It does not add missing content (C). Where a fix would leave a hole (for example B18 removes "raw SQL does not exist" but the page still needs a section on what does), the fix states the fact in one paragraph and stops. +- It does not touch the skill (D14) or the monorepo docs (D17). +- It does not rename "Prisma 8" to "Prisma ORM" (naming.md). That is a site-wide pass and cleaner as its own PR after this slice; mixing it in would bury the corrections in a 700-line diff. + +## Decisions before PR 3 + +Will answered on 2026-09-10: 1 and 4 as proposed; 2 and 3 checked as below. + +1. **B7, agent files.** Write the `skills: { agents: [] }` workaround now; replace it when the opt-out brief lands. +2. **B8, Node floor.** Checked by running rc.9 end to end (`contract emit`, `db init`, ORM create and read, `for await`, SQL builder) in a scratch project under Node 22.12.0, 22.18.0, and 22.22.3: all pass. Node release schedule (`nodejs/Release/schedule.json`): 22 "Jod" is Maintenance LTS until 2027-04-30; 23 reached end of life 2025-06-01; 24 "Krypton" is Active LTS, Maintenance from 2026-10-20, end of life 2028-04-30; 26 becomes LTS 2026-10-28. So Node 22 is supported and in LTS for another seven months, and 23 is dead. The scaffold's `engines` range `^22.18.0 || >=24.11.0` is what `create-prisma` enforces; the excluded 24.0 to 24.10 band is odd and worth asking the create-prisma owner about, but the site should not contradict what the scaffold refuses. Site wording: "Node.js 22.18 or newer; Node.js 24 recommended." The monorepo's `Supported Versions.md` says 24 and is wrong about what runs. +3. **B25, streaming.** What the page says: `for await` over `.all()` "streams" rows with a "steady, flat memory footprint" for millions of rows, you "start working on the first record before the last one has arrived", and on early exit "unprocessed records are never buffered". What the implementation does: `postgres()` creates its driver with `cursor: { disabled: true }` (`packages/3-extensions/postgres/src/runtime/postgres.ts:245`), and the driver's own comment calls that "buffered execution": the whole result set is fetched into memory before iteration starts; only decoding through the codecs happens per row as your loop pulls. Cursor batches (`batchSize`, default 100) exist in the driver and are only reachable through the serverless facade's `cursor` option. Measured on a 400,006-row table under Node 22.18: `for await` that breaks after the first row took 186 ms and grew the heap by 64 MB (every row was fetched), versus 824 ms for `await ...all()` (fetch plus decode of every row). So `for await` saves the decode work and the decoded array, not the fetch. The page's three claims about memory and arrival order are false on `postgres()`; the "read once" rule and the per-row hand-off are true. Fix for this slice: rewrite the section to say what actually happens (rows are fetched in full, decoded one at a time as you iterate, use `limit()` or the serverless facade with cursors for genuinely large results). Whether `postgres()` should expose `cursor` is D8 and is out of this slice. +4. **B16, the `--db` quirk.** Document the current behaviour as-is, with `--advance-ref db` shown in every example that passes `--db`. + +## How the work runs + +- One implementer per PR, working from the audit files and `changes.md`, in this worktree on a branch off `main`. Every changed code sample cites the source line in the commit message. Where a sample can be typechecked against `wip/prisma-src/examples/prisma-8-demo`, it is. +- I review each PR against the source before it goes to you. You do the prose pass. +- No push and no PR until you say so; the branches sit here until then. From cdd48e5fce24920247b6b9b4c5245c56a23e2ee5 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 14:38:33 +0200 Subject: [PATCH 02/68] docs: add the prisma-8 skill staleness brief to the audit Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 2 +- docs/orm-docs-audit/brief-skill-staleness.md | 42 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 docs/orm-docs-audit/brief-skill-staleness.md diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 792005a9d2e..86d3af4ed99 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -11,7 +11,7 @@ Read in this order: 5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B, shipped), new pages (C), ORM changes (D). Leads with the suggested order. 6. `naming.md` — the "Prisma ORM" naming rule. 7. `slice-corrections.md` — how the shipped corrections were sliced, and the decisions taken. -8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md` — two ORM changes handed to other agents. +8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). 9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. Prose is a draft throughout; the structure and the cited facts are what has been verified. diff --git a/docs/orm-docs-audit/brief-skill-staleness.md b/docs/orm-docs-audit/brief-skill-staleness.md new file mode 100644 index 00000000000..a93628008e8 --- /dev/null +++ b/docs/orm-docs-audit/brief-skill-staleness.md @@ -0,0 +1,42 @@ +# Brief: bring the `prisma-8` agent skill up to rc.9 + +Written 2026-09-11 for an ORM-focused agent with no prior context. Repo: `prisma/orm` (the Prisma ORM 8 monorepo). The skill is `skills/prisma-8/`: `SKILL.md` plus `references/*.md` and `upgrading/`. It ships inside the `@prisma/orm-postgres`, `@prisma/orm-sqlite`, and `@prisma/orm-mongo` tarballs (each package's `files` includes `skills`, and `prepack` runs `sync-package-skills.ts`), and `prisma init` / `prisma skills sync` copy it into user repos for Claude Code, Cursor, Codex, and Windsurf. It is what coding agents read instead of the docs site, so every stale line below is an agent writing broken code into a user's project. + +## What we want + +Every claim, sample, import path, command, flag, and error code in `skills/prisma-8/references/*.md` true on the current release, verified against `packages/`, `docs/releases/`, and `examples/`, with the specific defects below fixed first. Do not rewrite the skill's structure or voice; fix facts. Where the skill deliberately uses `@internal/*` import paths, leave them: that is a known convention users read as `@prisma/orm-postgres/*`. + +## Verified defects, most damaging first + +Line numbers are from the rc.9 tag. "Source" is the file that proves the correct form. + +1. **Row reads through `execute()`.** `queries-postgres.md:255-300` (and 289, 302, 333, 355), `queries.md:144, 149`, `queries-mongo.md:12, 140, 164, 178` read rows with `db.runtime().execute(plan)` or `(await db.runtime()).execute(plan)`. Since rc.2, `execute()` resolves `{ affectedRows }` and rows come from `query()`, which returns an `AsyncIterableResult`. On Mongo, `execute()` on a find or aggregate throws `RUNTIME.MONGO_STATISTICS_UNSUPPORTED`. Only non-returning writes stay on `execute`. Source: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `packages/2-mongo-family/7-runtime/src/mongo-runtime.ts:98-100,282-289`, `docs/releases/v8.0.0-rc.2.md`, `examples/prisma-8-demo/src/queries/*.ts`, `examples/mongo-demo/test/query-builder-writes.test.ts`. +2. **`PN-*` error codes.** `debug.md:12, 78-110, 306-338`, `contract.md:28, 62-66`, `migrations.md:21, 67-75` route on `PN-CLI-4001…4020`, `PN-MIG-2001…2005`, `PN-RUN-3001…3030`, `PN-SCHEMA-0001`. No such string exists in `packages/`. Every published error is a dotted structured code since 0.17 (`MIGRATION.RUNNER_FAILED`, `CONTRACT.MARKER_MISSING`, `CONTRACT.MARKER_MISMATCH`, `MIGRATION.UNFILLED_PLACEHOLDER`, `MIGRATION.DATA_TRANSFORM_CONTRACT_MISMATCH`, and so on). Source: `docs/releases/v0.17.0.md:27`, `docs/reference/error-reference.md`, `packages/1-framework/1-core/errors/src/`. +3. **Flat config file.** `contract.md:47, 164-170` shows `defineConfig({ contract, extensions })` from `@internal/postgres/config` as the whole `prisma.config.ts`. The envelope form `definePrismaConfig({ orm: ormConfig({ contract, db: { connection }, extensions }) })` replaced it in rc.4 and the flat fallback is gone. Source: `docs/releases/v8.0.0-rc.4.md`, `examples/prisma-8-demo/prisma.config.ts`. +4. **`orm init` facts.** `quickstart.md:73, 189, 201` says the default schema path is `prisma/contract.prisma` (it is `src/prisma/contract.prisma`, with `db.ts` beside it); `quickstart.md:196` documents `orm init --skip-skills` (removed in rc.6; `orm init` no longer touches skills at all). Source: `packages/1-framework/1-core/config/src/config-types.ts:45`, `packages/1-framework/3-tooling/cli/src/orm/init.ts:87-112`, `cli/src/commands/init/skill-sources.ts:1-5`, `docs/releases/v8.0.0-rc.6.md:29`. +5. **Many-to-many.** `queries.md:139-140` says N:M `.include()` and nested N:M mutations are unsupported and that `mutation-executor.ts` throws. Both work through the junction: `include('tags', …)`, nested `create` / `connect` / `disconnect`. The quoted throw string no longer exists. Source: `packages/3-extensions/sql-orm-client/src/mutation-executor.ts:836-926`, `collection-contract.ts:356-379`, `examples/prisma-8-demo/src/orm-client/get-post-tags.ts`, `create-post-with-tags.ts`. +6. **Destructive consent.** `migrations.md:33, 146, 470` says pass `-y` to auto-accept a destructive `db update`. `--yes` does not grant consent; the user types the database name or passes `--confirm `. Source: `cli/src/orm/db/update.ts:118-124, 218-224`, `cli/src/orm/db/consent.ts`. +7. **Migration factories as free functions.** `migrations.md:231-235, 254-270` renders `addColumn('public', 'user', {...})` and `setNotNull('public', 'user', 'name')`. They are methods on the `Migration` base class with object arguments: `this.addColumn({ schema, table, column: col(...) })`, `this.setNotNull({ schema, table, column })`. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:231, 364`, `examples/prisma-8-demo/migrations/app/20260810T1108_add_post_engagement_counters/migration.ts:17-21`. +8. **Transaction scope of `db migrate`.** `migrations.md:48` says each migration runs in its own `BEGIN … COMMIT`. The runner issues one `BEGIN`, applies every space's plan, then one `COMMIT` or `ROLLBACK`. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/runner.ts:176-215, 684-696`. +9. **Marker name.** `quickstart.md:125` calls the marker a `pn_meta_marker` row. It is `prisma_contract.marker`. Source: `runner.ts:321-326`. +10. **Middleware that does not exist, and one that does.** `runtime.md:11, 135-158, 315, 322` imports `createTelemetryMiddleware` from `@internal/middleware-telemetry`; no such package exists. `runtime.md` also says lints and budgets must come from `@internal/sql-runtime` because the facade has no middleware subpath; the public path is `@prisma/orm-postgres/family-runtime`. And it never mentions the cache middleware (`@prisma/orm-extension-middleware-cache`), which ships. Source: `packages/9-public/@prisma/orm-postgres/package.json` (`./family-runtime`), `packages/3-extensions/middleware-cache/`, `examples/prisma-8-demo/src/prisma/db.ts`. +11. **Dropped extension as the canonical example.** `contract.md:25, 29, 49` uses `cipherstash.EncryptedString(...)`. The in-tree cipherstash extension was dropped in favour of CipherStash's own package (`CHANGELOG.md:1040`). Use `pgvector.Vector(1536)` as the demo does. +12. **Mongo PSL attributes.** `contract.md:221` says `@@discriminator` / `@@base` are SQL-only and Mongo polymorphism needs the TypeScript builder. The Mongo PSL interpreter implements both and the Mongo demo uses them. Source: `packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts:276-418`, `examples/mongo-demo/src/contract.prisma`. +13. **Scalar lists.** `contract.md:123` says `String[]` is rejected by the SQL interpreter. Lists are gated on the `sql.scalarList` capability, which PostgreSQL declares; only SQLite rejects them. Source: `packages/2-sql/2-authoring/contract-psl/src/psl-field-resolution.ts:497-500`, `examples/prisma-8-demo/src/prisma/contract.json` (`"scalarList": true`). +14. **`.count()` as a collection terminal.** `queries-postgres.md:30` lists `.count()` beside `.all()` / `.first()`. There is no `count` method on the collection; `count()` exists as an `include` reducer and inside `aggregate()`. Source: `packages/3-extensions/sql-orm-client/src/collection.ts`. +15. **SQL-builder `insert` input.** `queries-postgres.md:258, 298-299` passes a single object; `insert()` takes an array of rows. Source: `packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts:122-123`. +16. **Combinator import path.** `queries.md:141`, `queries-postgres.md:75, 86, 251` say `and` / `or` / `not` are internal-only. `@prisma/orm-postgres/orm-client` exports them. Source: `packages/9-public/@prisma/orm-postgres/package.json`, `test/facade-tarball.test.ts:58, 171`. +17. **Prepared statements.** `debug.md:127` says you cannot pre-prepare and re-execute a statement and points to TypedSQL (which `queries.md:144` says does not exist). `db.prepare(...)` and `runtime.prepare(...)` exist; a row-returning prepared statement runs with `ps.query(runtime, params)`. Source: `packages/2-sql/5-runtime/src/sql-runtime.ts:110, 549`, `packages/2-sql/5-runtime/src/prepared/types.ts:55-105`. +18. **Streaming.** `queries.md:146` says there is no streaming surface and recommends holding a `pg.Client`. The read terminals return an `AsyncIterableResult` you can `for await`; but on the long-lived `postgres()` facade the driver runs with cursors disabled, so the full result is fetched before iteration and only decoding is per row. The serverless facade (`@prisma/orm-postgres/serverless`) reads through a cursor in batches of 100. Say exactly that. Source: `packages/3-extensions/sql-orm-client/src/collection.ts:998-1022`, `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`, `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:39-53`, `postgres-serverless.ts:28-42`. +19. **`migration show` with no argument.** `migrations.md:189` runs it bare; the `` positional is required. Source: `cli/src/orm/migration/show.ts:3-6`. +20. **`--from` grammar.** `migration-model.md:67` lists `@contract | @db | @empty` for `migration plan --from`. The command is offline: only `@empty` resolves there (`@db` needs the live marker, `@contract` needs a contract hash the plan resolver does not pass). Source: `cli/src/control-api/operations/plan-resolution.ts:224-229`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:39-56`. +21. **Node.js floor for Temporal.** Wherever the skill says Temporal-backed types need a polyfill "on Node", say: Node.js 26.8.2 and later ship `globalThis.Temporal`; 26.8.1 and earlier, including every 22 and 24, do not, so `temporal-polyfill/full/global` must be imported before the first read or the column authored as a `*String` type. Checked empirically on 22.22.3, 24.16.0, 26.8.1, 26.8.2. + +Things the skill gets right that the site had wrong (keep them): `db.raw.sql` as the raw tag and whole-query raw SQL with `.returnsRow()` / `.affectedCount()` (`queries.md:143`, `queries-postgres.md:392, 415`); `extensions` not `extensionPacks` in `defineContract` (`contract.md:51, 386`); the five lint severity keys (`runtime.md`); `../../snapshots//contract.json` imports (`migrations.md:225, 253`); `db.close()` for teardown (`runtime.md:66-78`); the `prebuild` emit for Next.js (`build.md:466`). + +## Acceptance + +- Every item above is fixed, with the commit citing the source line used. +- A pass over the rest of `references/*.md` for the same classes of defect: any `execute(` on a row-returning plan, any `PN-` code, any flat `defineConfig`, any `@internal/middleware-telemetry`, any `--skip-skills`, any `prisma/contract.prisma` default. +- The skill's own journey tests (`skills/journey-tests/`) pass, and any sample that can be typechecked against `examples/prisma-8-demo` or `examples/mongo-demo` is. +- The `skills/prisma-8/upgrading/` instructions are not in scope unless they repeat one of the defects above. From f25edb93fad050eecd6eefce4060f75aa37f37cb Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 14:44:11 +0200 Subject: [PATCH 03/68] docs: rewrite the audit change list for readers without the audit context Status first, open work only in the recommended order, decisions with owners, the shipped corrections collapsed to a summary, new pages grouped by where they live, ORM changes grouped by owner, process residue removed. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 268 +++++++++++++-------------------- 1 file changed, 106 insertions(+), 162 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index d19752fc69d..ef0458832df 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -1,205 +1,149 @@ -# Proposed changes +# Prisma ORM 8 docs: what to change, and in what order -Four kinds of change: restructure the docs, improve existing pages, create new pages, change the ORM. Ordered work first, then the items by kind. Nothing here is started. +This is the working list of changes to the Prisma ORM 8 documentation, built from a page-by-page audit against `@prisma/orm-postgres@8.0.0-rc.9` (the audit files are under `audit/`, with a source citation for every finding). Four kinds of change: restructure the site, correct existing pages, write new pages, change the ORM or its tooling where the docs are hard because the tool is. -Sources: the first-session brief, plus the seven audit files under `audit/` (written 2026-09-10 against rc.9; every item cited below was spot-checked against `wip/prisma-src` unless marked "agent-reported"). Line numbers and full occurrence lists are in the audit files; this document names the defect and the pages. +Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J10" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. -## Suggested order +Status as of 2026-09-11. -1. B1 to B4 and B11 to B14 as the first `prisma/web` PR: the site-wide mechanical fixes (`execute` to `query`, `sha256:` prefixes, `extensionPacks`, pagination names, `AndCount` names, snapshot layout). Each is a search-and-replace with a known correct form and breaks every user who copies it today. -2. B15 to B22 as a second PR, page by page: the existing-project pages, the migrations pages, the middleware pages, the raw SQL page, the relations page. These need rewriting sentences, not just names. -3. A7 in the same week as item 2: move or hide the sixteen Prisma 7 guides that sit under Prisma ORM 8 paths. Until then the guides index sends Prisma ORM 8 readers to `prisma generate`. -4. A4 and C4. Two small edits and one short page fix J4 and J5's discoverability. -5. A1, A2, A3, C1, C2 as the restructure, written from `mental-model.md`. This is the work that answers the Discord thread. -6. D1, D2, D3, D6, D8, D9, D10, D14, D17 raised as product tickets now, because C3, C4, and the deployment pages depend on the answers. -7. C3, C5 to C20 as each dependency clears. C9 (deployment) and C10 (Supabase and RLS) are the two largest gaps the audit found and have no page at all today. +## Where things stand -## Naming, across everything +**Shipped.** Every correction to an existing page (section B, 35 items) went out in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist), #8237 (pages whose explanations were wrong), and #8238 (facts on the getting-started pages and guides). Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -The product is "Prisma ORM"; a version number appears only when two versions are being contrasted. Rule, counts, and exceptions are in `naming.md`. Applies to every item below and to the proposed nodes in `ia.md`. +**In progress.** A7 (moving the sixteen Prisma 7 guides out of the Latest tree) is with Ankur. D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. -## A. Restructure - -The current and proposed sidebar trees are in `ia.md`. The items below are the individual moves that tree implies. - -**A1. Give the ORM its own front door, organised by starting state.** Replace the current split (quickstart vs. add-to-existing) with four doors on `/prisma-orm` and `/orm`: new app from scratch, app I already started with an empty database, an existing database with data, and an existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. - -**A2. Put "Coming from Prisma 7" in the ORM sidebar at the top level and link it from the root page, `/getting-started`, `/orm`, and reading-data.** One page, with the mapping table from `mental-model.md` expanded. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. - -**A3. Human content first, agent prompts last, on every ORM page.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end of the page or into a collapsed block. Addresses the "written for AI" complaint directly. Unblocks the Newcomer and the Upgrader on every page. - -**A4. Fix the navigation labels that hide existing content.** The upgrade guide's sidebar label is "PostgreSQL" under "Upgrade Prisma ORM"; rename to "Prisma 7 to 8 (PostgreSQL)". The guides index says upgrading is "coming as they land"; remove that line. Files: `guides/upgrade-prisma-orm/meta.json`, `guides/index.mdx`. Unblocks J5. - -**A5. Root page: make the ORM line a section.** The root is the platform's page and should stay so, but the ORM needs more than "Here for the ORM? Jump to Prisma 7 or Prisma 8". Give it the four doors from A1 in one row. File: `(index)/index.mdx`. - -**A6. Absorb core-concepts into a narrative page written from `mental-model.md`.** The current page is a good glossary but reads as a list of terms. The mental model page answers "why" in the order a person meets each piece. Keep the glossary as a section at the end. File: `orm/core-concepts.mdx`. - -**A7. Get the Prisma 7 guides out of the Prisma ORM 8 tree.** Sixteen pages under the Prisma ORM 8 guides paths are Prisma 7 content end to end (`prisma@7.10.0`, `@prisma/client`, generator blocks, `prisma generate`, `migrate dev`, `db push`, `db seed`, `studio`): `guides/frameworks/react-router-7`, `guides/frameworks/solid-start`, all six of `guides/deployment/*`, `guides/integrations/github-actions`, `guides/integrations/ai-sdk`, all three of `guides/switch-to-prisma-orm/*`, all three of `guides/database/*`. None has a copy under `guides/v7/`. Move them to `guides/v7/` with the same slugs and redirect, then either write the Prisma ORM 8 replacement (C9, C11, C12) or leave the label off the Prisma ORM 8 sidebar until it exists. Evidence: `audit/gaps.md` Breaks copy-paste, `audit/start-guides.md` Misleading. Changes `ia.md`: the "Guides" tree for Prisma ORM 8 loses six labels until replacements land. - -**A8. One error reference, or two that link.** `cli/error-reference.mdx` says it lists every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code lives on `orm/reference/error-reference.mdx`, and the two pages do not link. The structured errors' `docsUrl` points at the ORM page. Either merge, or state the split on both pages and cross-link. Evidence: `audit/migrations-cli.md` Misleading. - -## B. Improve existing pages - -Copy-paste defects a user hits today, grouped by theme. B1 to B10 are from the first-session brief; B11 onward are from the audit. Full line lists are in the audit files named on each item. - -### Site-wide mechanical fixes - -**B1. `.take()`/`.skip()` to `.limit()`/`.offset()`.** 29 sites on 8 pages: `orm/fundamentals/reading-data.mdx` (8, including the meta description), `orm/reference/orm-client.mdx` (13, including two section headings), `orm/fundamentals/relations-and-joins.mdx`, `orm/reference/pipeline-builder.mdx` (3, check which are the Mongo pipeline `$skip` stage and keep those), `orm/middleware/authoring-custom-middleware.mdx`, `guides/runtimes/deno.mdx`, `(index)/full-stack-tutorial.mdx`, `(index)/prisma-orm/add-to-existing-project/postgresql.mdx`. - -**B2. `createCount`/`updateCount`/`deleteCount` to the `AndCount` names.** 31 sites on `orm/fundamentals/writing-data.mdx` and `orm/reference/orm-client.mdx`, including three section headings. - -**B3. Existing-project PostgreSQL page.** `db.orm.User` to `db.orm.public.User`; `db.sql.user` to `db.sql.public.user`; drop the `db.connect()` call or the `db.runtime()` call, not both; show `src/prisma/db.ts` once with one sentence on what it does; pick one story for `DATABASE_URL` (the page uses `.env` with `dotenv/config`, the quickstart says environment only) and say why. Then add the missing steps from J2: baseline migration and `migration ref set db` before the "next steps" section. See also B15, which found the page's default path is wrong. File: `(index)/prisma-orm/add-to-existing-project/postgresql.mdx`. - -**B4. Remove `@db.Uuid` from the PSL syntax page.** Lines 19 and 177 of `orm/contract-authoring/psl-syntax.mdx` show `Uuid = String @db.Uuid`. Removed in 0.17; `Uuid` is a built-in type name in type position and needs no alias, so the "Named types" example should alias a real type instead (for example `ShortName = VarChar(35)`). Check the rest of the page for other `@db.` forms. - -**B11. `execute()` to `query()` for every row-returning plan.** The largest defect the audit found. Since rc.2, `runtime.execute(plan)` returns `{ affectedRows }` and rows come from `runtime.query(plan)` (an `AsyncIterableResult`, awaitable to an array or iterated with `for await`). The MongoDB client's `db.execute(plan)` facade method was removed in the same release; rows come from `(await db.runtime()).query(plan)`. Prepared statements split the same way: `ps.query(runtime, params)` for rows, `execute` only for `.affectedCount()` plans. Roughly 200 lines on 14 pages: `orm/reference/sql-query-builder.mdx` (about 31), `orm/reference/pipeline-builder.mdx` (about 50), `orm/reference/raw-queries.mdx` (about 20), `orm/fundamentals/advanced-queries.mdx` (10), `orm/reference/transactions-and-runtime.mdx` (about 12, including `withTransaction`'s `tx` surface and `executePrepared`, which does not exist), `orm/core-concepts.mdx`, `orm/fundamentals/reading-data.mdx`, `orm/fundamentals/relations-and-joins.mdx`, `orm/extensions/using-extensions.mdx`, `orm/middleware/built-in-cache.mdx`, both `add-to-existing-project` pages, `guides/upgrade-prisma-orm/mongodb.mdx` (5). Non-returning writes such as `orm/fundamentals/transactions.mdx:60` are correct and stay on `execute`. The shipped skill has the same defect (D14). Evidence: `packages/2-sql/5-runtime/src/sql-runtime.ts:309-322`, `packages/3-extensions/mongo/src/runtime/mongo.ts:28-39`, `docs/releases/v8.0.0-rc.2.md`. Audit: `orm-client`, `builders`, `start-guides`. - -**B12. Bare hex hashes.** Every hash the site prints is `sha256:…`; since 0.17 hashes are bare hex and loaders and `migration ref set` reject the prefixed form. `orm/contract-authoring/the-contract-artifact.mdx` (5 sites, in JSON and in `StorageHashBase<"sha256:…">`), all six `orm/migrations/*` pages, `cli/migration-ref.mdx`. Evidence: `docs/releases/v0.17.0.md:45`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:14-24`. Audit: `contract`, `migrations-cli`. - -**B13. `extensionPacks` to `extensions`.** Renamed in 0.17 and the old key fails loudly. `orm/contract-authoring/typescript-schema-builder.mdx` (5 sites in `defineContract`; the PostgreSQL contract on that page does not build) and `orm/contract-authoring/the-contract-artifact.mdx` (2 sites as the `contract.json` top-level key). Evidence: `docs/releases/v0.17.0.md:73`, `packages/3-extensions/postgres/src/contract/define-contract.ts`. Audit: `contract`. - -**B14. Migration directory layout and imports.** The site shows `start-contract.json` / `end-contract.json` inside each migration directory and `migration.ts` importing `./end-contract`. Since 0.17 snapshots live once under `migrations/snapshots//contract.json` plus `contract.d.ts`, and `migration.ts` imports `../../snapshots//contract.json`. The directory holds `migration.ts`, `ops.json`, `migration.json`. Pages: `orm/migrations/how-migrations-work.mdx`, `generating-a-migration.mdx`, `editing-a-migration.mdx`. Evidence: `docs/releases/v0.17.0.md:47`, `examples/prisma-8-demo/migrations/app/*/migration.ts`. Audit: `migrations-cli`. - -### Page rewrites - -**B15. Existing-project pages: the default path is `src/prisma/`, not `prisma/`.** Both `add-to-existing-project` pages tell the reader to keep the default schema path `prisma/contract.prisma` and build every later command on it (`contract infer --output ./prisma/contract.prisma`, `import "./prisma/db"`). `orm init` defaults to `src/prisma/contract.prisma` and writes `db.ts` beside it, so a reader who accepts the default gets a file `prisma.config.ts` never reads and an import that does not resolve. Same pages also say `orm init` installs agent skills (it stopped in rc.6; it writes `prisma-next.md` only), omit the `.env` prompt (default No, so there may be no `.env` to "update"), and the MongoDB page's `runtime.execute(plan)` on an aggregate throws `RUNTIME.MONGO_STATISTICS_UNSUPPORTED`. Add the Temporal polyfill note (D10) and the `--write-env` / `--schema-path` flags. Evidence: `packages/1-framework/1-core/config/src/config-types.ts:45`, `packages/1-framework/3-tooling/cli/src/orm/init-inputs.ts:229-233`, `docs/releases/v8.0.0-rc.6.md:29`. Audit: `start-guides`. - -**B16. The `db` ref and plan-origin story on the migrations pages.** Three connected errors. (a) The pages say `migration plan` without `--from` or a `db` ref plans a full CREATE migration; since rc.8 it refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN` when migrations exist on disk, and names the exits (`migration ref set db `, `--from `, `--from @empty`). The upgrade guide tells readers to look for the CREATE TABLE symptom that no longer appears. (b) `db init` and `db update` advance the `db` ref automatically only when `--db` is omitted; every example on the site passes `--db "$DATABASE_URL"`, which suppresses that unless `--advance-ref` is also given, so a reader following the site's loop hits (a) on the second plan. No page says this. (c) Retracted after PR 2: the audit said `MIGRATION.NO_TARGET` never comes from `migration plan`, but `plan-resolution.ts` calls `findLatestMigration`, which calls `findLeaf`, which throws it on a cyclic graph, and the monorepo's `gotchas.md:83-110` reproduces exactly the rollback case `rollbacks-and-recovery.mdx` describes. That page was right. Also `the-migration-graph.mdx` says there is no baseline mechanism; the planner writes an automatic baseline when the graph is empty and the `db` ref names a snapshot, and `--from @empty` is the supported retrofit. Pages: all six `orm/migrations/*`, `cli/migration-plan.mdx`, `cli/db-init.mdx`, `cli/db-update.mdx`, `cli/migration-ref.mdx`, `cli/index.mdx`, `guides/upgrade-prisma-orm/postgresql.mdx`. Evidence: `packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts:428-475`, `cli/src/control-api/operations/ref-advancement.ts:19-28`, `cli/src/control-api/operations/migration-plan.ts:369,505-545`. Audit: `migrations-cli`, `start-guides`. Ties to D1, D2, D9. - -**B17. Middleware pages: the hook model is wrong.** The pages document five hooks with `intercept` and `beforeExecute` for reads. Since rc.2 there are two lifecycles: `beforeQuery` / `interceptQuery` / `onRow` / `afterQuery` for row queries, and `beforeExecute` / `interceptExecute` / `afterExecute` for non-returning writes. There is no `intercept`, no compatibility alias, and `afterExecute` carries `stats.affectedRows`, not `rowCount`. The authoring guide's flagship query logger implements only `afterExecute` and reads `result.rowCount`, so it is a type error and would never log the SELECT the page shows it logging. Also: `unindexedPredicate` is not a lint severity key; `severities.latency` on budgets is read (page says it is not); "permissive mode" is unreachable from the Postgres client (D12); the cache runs on the query lifecycle. Pages: all five `orm/middleware/*`. Evidence: `packages/2-sql/5-runtime/src/middleware/sql-middleware.ts`, `packages/2-sql/5-runtime/src/middleware/lints.ts:13-23`, `budgets.ts:97-125`, `examples/prisma-8-demo/src/prisma/slow-query-warning.ts`. Audit: `builders`. - -**B18. Raw SQL page says the opposite of what ships.** `orm/reference/raw-queries.mdx` and `advanced-queries.mdx` say there is no way to run a standalone raw statement. Since rc.2 there is: `db.raw.sql\`…\`.returnsRow(spec).build()` for rows and `.affectedCount().build()` for writes; raw row queries compose as subqueries and CTEs. The page also calls `db.raw` as a template tag; it is a lane object and the tag is `db.raw.sql`. The "bare scalar interpolation is broken because the inferer emits unversioned ids" callout is contradicted by the adapter source, which emits versioned ids. Evidence: `packages/2-sql/4-lanes/sql-builder/src/types/raw-query.ts:117-170`, `packages/3-targets/6-adapters/postgres/src/core/adapter.ts:112-140`, `examples/prisma-8-demo/src/queries/raw-query-demo.ts`. Audit: `builders`, `orm-client`. - -**B19. Relations and data-modeling pages say things are unsupported that work.** (a) The 1:1 mirror field `profile Profile?` "is not supported yet": it is accepted (rejected only when the foreign key is not unique) and `include('profile')` type-checks as a to-one include. (b) Implicit many-to-many `include` "not supported yet": the ORM resolves `through` relations and the demo includes `Post.tags`; nested `create` / `connect` / `disconnect` through the junction also work, and `orm-client.mdx` already documents `disconnect` through the junction. (c) Referential actions "as it lands": `onDelete` / `onUpdate` with `Cascade` / `Restrict` / `SetNull` / `NoAction` are lowered today. (d) The discriminator "is not filled in automatically": `.variant('Bug').create()` injects it; the page never mentions `.variant()`. Both pages send users to the SQL builder for things the ORM does. Pages: `orm/fundamentals/relations-and-joins.mdx`, `orm/data-modeling/relational-databases.mdx`. Evidence: `packages/2-sql/2-authoring/contract-psl/test/interpreter.relations.test.ts:78`, `packages/3-extensions/sql-orm-client/src/collection-contract.ts:356-379`, `mutation-executor.ts:836-926`, `collection.ts:406`, `psl-relation-resolution.ts:19-22`. Audit: `contract`, `orm-client`. - -**B20. Aggregates decode as numbers, not strings.** `sql-query-builder.mdx` and `advanced-queries.mdx` tell users `COUNT` / `SUM` / `AVG` come back as strings and to call `Number(...)`. Since rc.2 `count()`, integer `sum()`, and `avg()` return `number` (throwing `RUNTIME.DECODE_FAILED` outside the safe range), with `countBigInt()`, `sumBigInt()`, `avgDecimal()` beside them. The "fixed" function list on `sql-query-builder.mdx` omits these; `min` / `max` are not numeric-only. Correction after PR 2: the audit said the `DateTime` column (`pg/timestamptz@1`) is still excluded from `min`/`max`; no such codec exists at rc.9. `DateTime` maps to `pg/timestamptz-temporal@1`, which is in `MIN_MAX_PRESERVING_CODECS`, so `min('createdAt')` type-checks; the compile error the page should show is `sum`/`avg` over a timestamp column. Evidence: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts:126-213`, `docs/releases/v8.0.0-rc.2.md:32-53`. Audit: `builders`, `orm-client`. - -**B21. Stale CLI names, flags, codes, and output.** One pass over `cli/*` and `orm/migrations/*`: `--skip-skills` and `CLI.INIT_SKILL_INSTALL_FAILED` on `orm-init.mdx` (removed rc.6; also cited on `(index)/index.mdx` and `getting-started.mdx`); `ref set` / `ref list` bare group (rc.5: `migration ref set`) and `ref set prod @db` (fails, `@db` is not accepted by the offline command); `prisma-cli migrate` hint text and the sentence explaining it (rc.5: hints print `prisma db migrate`); `(PN-RUN-3000)` (0.17: dotted codes, `MIGRATION.RUNNER_FAILED` and siblings); `from: null` (prints `from: (baseline)`); the "Applied 1 migration(s)…" summary line (no migration count); `git clone …/orm` then `cd prisma`; `npx prisma@latest migrate` on `create-prisma.mdx` (the command is `db migrate`); hyphenated `--name add-users-table` shown as the directory name (slugs become `add_users_table`); `contract infer` presents `--db` as required (falls back to config); `orm-init.mdx` says the scaffolded `db.ts` does not load `.env` (it starts with `import 'dotenv/config'`) and that `contract:emit` calls `prisma-cli`. Audit: `migrations-cli`, `start-guides`, `contract`. - -**B22. `editing-a-migration.mdx` data-transform example does not typecheck.** `sql({ context })` omits the required `rawCodecInferer`, so `node migration.ts` fails before writing `ops.json`. Evidence: `packages/2-sql/4-lanes/sql-builder/src/runtime/sql.ts:11-19`. Audit: `migrations-cli`. +**Not started.** The naming pass, the restructure (A1 to A3, A5, A6, A8), every new page (C), and the rest of D. -### Smaller fixes, one line each +## Recommended order for the open work -**B5. Supported databases.** `orm/index.mdx` says SQLite is planned. It ships as `@prisma/orm-sqlite`; `sql-query-builder.mdx` also says "PostgreSQL is supported today". Say Postgres, MongoDB, SQLite, and what is next. +1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (691 occurrences in 109 files). Mechanical, one PR, done after A7 lands so the two do not conflict. +2. **C4, release status page.** Half a page; unblocks J4 (the reader who got upgraded by accident). Needs the GA window and the Prisma ORM 7 support policy from Will. +3. **C2, add Prisma ORM to an app you already started.** The J1 page and the complaint that started this work. One page, written from `mental-model.md`. +4. **C1, coming from Prisma 7.** The mapping table and the "not yet" list. Unblocks J3. +5. **C9, deployment.** The largest hole: zero Prisma ORM 8 coverage for any host, and the six pages A7 removes had been standing in for it. +6. **The restructure** (A1, A2, A3, A5, A6) as one piece of work, after the pages above exist to be organised. +7. **Everything else in C** as its dependency in D clears. -**B6. Un-pin the upgrade guides.** The PostgreSQL guide says every command was validated on rc.6 and rc.4; the MongoDB guide says `0.16.0`. Re-run on rc.9 (the Mongo guide is also hit by the rc.7 pagination rename and the rc.9 attribute rejection) and either drop the version callout or keep it current per release. Also `Database signed (marker created)` is printed as `Database signed`. Files: `guides/upgrade-prisma-orm/postgresql.mdx`, `mongodb.mdx`. +## Decisions needed, and from whom -**B7. One line on agent files, on three pages.** On `create-prisma.mdx`, both quickstarts, and the existing-project page: "Prisma writes skill files for coding agents into your repo. To stop that, set `skills: { agents: [] }` in `prisma.config.ts`; see Configuration." Until D3 lands, that is the only correct answer. +| Item | Decision | Who | +|---|---|---| +| C4 | GA window to state publicly; Prisma ORM 7 support policy | Will | +| D6 | Keep the release candidate on npm `latest`, or move it to `next` until GA | Will, with whoever owns publishing | +| D4 | For each missing client API: build it, or document the workaround and say it is not planned | ORM product | +| D1 | Which of the two designs for one-step adoption | ORM (brief in `brief-db-ref-on-adoption.md`) | +| D3 | Flag name and prompt wording for the skills opt-out | create-prisma (brief in `brief-skills-opt-out.md`) | +| C18 | The version floors to publish: the monorepo's `docs/Supported Versions.md` says Node 24; the scaffold enforces 22.18 and rc.9 runs on 22.12 | ORM product | +| C5 | Current state of the VS Code extension and language server | Serhii | +| C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | ORM product | -**B8. Node version.** The quickstart says 24 or newer; seven framework guides say "Node.js 24 or later"; the scaffold's `engines` says `^22.18.0 || >=24.11.0` and create-prisma refuses below 22.18; the upgrade guide says 22.18+. Node 24.0 to 24.10 does not work. Say the true floor once. - -**B9. Explain `// use prisma-next`.** It appears at the top of every PSL example and is never explained. One sentence where the contract file is first introduced, and on the editor page (C5). - -**B10. `db.runtime()` on Mongo.** Mongo needs `(await db.runtime())`, Postgres does not. Say so where `db.ts` is first shown, not only in the transactions reference. - -**B23. `db.close()`, not `db.runtime().close()`.** Four guides (Bun, Hono, Elysia, NestJS) tear down with `db.runtime().close()`; the client method is `db.close()` (idempotent, also `Symbol.asyncDispose`), and every other page uses it. Audit: `gaps`. - -**B24. Upsert needs `conflictOn`.** `writing-data.mdx:182-195` upserts without `conflictOn` and says the match is on `email`; without `conflictOn` the target is the primary key, so the sample inserts a duplicate or fails on the unique constraint. Audit: `orm-client`. - -**B25. Streaming claim.** `reading-data.mdx` promises a flat memory footprint for `for await` over millions of rows; the `postgres()` facade constructs its driver with `cursor: { disabled: true }`, so the whole result is buffered first. Either soften the page or fix the ORM (D8). Audit: `orm-client`. - -**B26. Enum ordering changed in rc.9.** `orm-client.mdx:478,513` say text-backed enums sort in declaration order; rc.9 sorts by stored value, only native enums keep database order. Audit: `orm-client`. - -**B27. Structured errors, not plain `Error`.** `transactions-and-runtime.mdx` shows closed / double-connect failures as plain `Error` strings; they are `DRIVER.NOT_CONNECTED` / `DRIVER.ALREADY_CONNECTED` envelopes, and the latter is raised by Postgres too. Its `db.prepare` then `db.connect()` sample throws `DRIVER.ALREADY_CONNECTED`. `pipeline-builder.mdx` calls the unknown-root error a plain `Error`; it is `ORM.MODEL_UNKNOWN`. Audit: `orm-client`, `builders`. - -**B28. create-prisma page details.** The `--template` list omits `minimal` (the default) on three pages; for PostgreSQL the scaffold writes no `.env` (page says "review `DATABASE_URL` in `.env`"); `--force` also overwrites the generated Prisma files and refuses on a non-empty `migrations/`; the deploy prompt defaults differ between interactive, `--yes`, and `--json`; the Deno command needs `--minimum-dependency-age=0`; the page lists four of the twelve generated scripts. Audit: `start-guides`, `gaps`. - -**B29. MongoDB replica set.** Both MongoDB start pages say Prisma 8 needs a replica set; nothing in the runtime or migration runner opens a session or transaction, and `orm init`'s `.env.example` says a standalone `mongod` works. Only the scaffold's connection string demands one. Audit: `start-guides`. +## A. Restructure -**B30. Framework guide details.** The Bun guide's `esbuild` build step fails (the scaffold builds with `tsdown`; edit `tsdown.config.ts` instead) and `bun run dev` is `tsx watch`, so "no build step" and the one-shot output are wrong; the NestJS `@Inject` workaround describes a defect the template fixed; seven guides say `db:init` applies `src/prisma/contract.prisma` without saying the TypeScript authoring path is `contract.ts` with output under `src/prisma/generated/`; the Deno page's "separate Deno CLI entry point" note is stale and its sample output omits fields. Audit: `gaps`. +The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. -**B31. `data-modeling/index.mdx` scalar table.** `Json` binds to native `json` since 0.17; `Jsonb` is the separate scalar (what `field.json()` and value objects use). The table never mentions `Jsonb`, `Decimal`, `Bytes`. Audit: `contract`. +- **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. +- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. +- **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. +- **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. +- **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** In progress (Ankur). `guides/frameworks/react-router-7`, `solid-start`, all of `guides/deployment/*`, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` are Prisma 7 end to end and have no copy under `guides/v7/`. Move with the same slugs and redirects; the Latest sidebar loses those labels until C9, C11, and C12 replace them. +- **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. +- **A4** (sidebar labels and the guides index) shipped in #8238. -**B33. `ai/tools/skills.mdx` describes skills that do not exist.** It says `orm init --skip-skills` skips installation (no such flag; `orm init` does not touch skills since rc.6), lists `prisma-next-upgrade` and `prisma-8-extension-upgrade` as installable (retired; `prisma init` deletes those directories; only `prisma-8` ships, with upgrading as a branch inside it), says `orm init` pins the GitHub install (the skill ships inside the `@prisma/orm-*` tarball and `prisma skills sync` copies it), and leads with `npx skills add prisma/prisma/skills`, which the monorepo README calls a fallback nothing keeps current. Evidence: `skills/README.md`, `cli/src/commands/init/skill-sources.ts:1-49`. Audit: `extras`. +## B. Corrections to existing pages (shipped) -**B34. Full-stack tutorial.** The tutorial shows the scaffold's `User` model with `createdAt DateTime` and `updatedAt temporal.updatedAt()`; the rc.9 starter contract writes `TimestamptzString` and `temporal.updatedAtString()`, which store a different runtime type. It also says the scaffold added a `postinstall` hook for skills; create-prisma adds a `skills:sync` script and runs `prisma init --yes` once. Evidence: `cli/src/commands/init/templates/code-templates.ts:171-193`, `wip/create-prisma-src/src/tasks/install.ts:56`. Audit: `extras`. +Thirty-five items, all verified against rc.9 source and shipped in #8236, #8237, #8238. What they fixed, in order of how many readers they hit: -**B35. `using-extensions.mdx` recipe and links.** The generic five-step recipe (import `/control`, pass to `postgres({ extensions })`) does not work for Supabase, which is wired with `extensions: [supabasePack]` from `/pack` and a client built by `supabase()` from `/runtime`. Every catalog row links to a monorepo README whose install command is `pnpm add @internal/extension-`, a private name. Also `orm/data-modeling/index.mdx:159` lists `Json` without saying filtering is whole-value equality only (D17). Audit: `extras`. +| Theme | What was wrong | Items | +|---|---|---| +| Row reads through `execute()` | Since rc.2 `execute()` returns `{ affectedRows }`; rows come from `query()`. About 200 lines on 14 pages, plus Mongo's removed `db.execute`. | B11 | +| Renamed API | `take`/`skip` (rc.7), `createCount` and siblings (0.17), `extensionPacks` (0.17), `@db.*` attributes (0.17), `sha256:` hash prefixes (0.17), the migration snapshot layout (0.17) | B1, B2, B4, B12, B13, B14 | +| Existing-project pages | Wrong default path (`prisma/` vs `src/prisma/`), skills claim, `.env` prompt, Temporal polyfill, namespace-qualified accessors | B3, B15, B10 | +| The `db` ref | `migration plan` refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`) instead of planning CREATE-everything; `db init`/`db update` advance the ref only without `--db`; the automatic baseline | B16 | +| Middleware | Five-hook model replaced by the two rc.2 lifecycles; the logger example never fired on reads; lint keys, budgets latency, "permissive mode" | B17 | +| Things called unsupported that work | Whole-query raw SQL, 1:1 back-relations, many-to-many include and nested writes, referential actions, `.variant()` | B18, B19 | +| Aggregates | Return numbers, not strings; the lossless variants | B20 | +| Stale CLI surface | `--skip-skills`, bare `ref` group, `prisma-cli` hints, `PN-RUN-*` codes, printed output, top-level `migrate` | B21 | +| Samples that failed | Data-transform wiring, upsert without `conflictOn`, `prepare` then `connect()`, structured error codes shown as plain `Error` | B22, B24, B27 | +| Getting-started facts | Node floor (22.18; on the 24 line 24.11; 24 recommended), MongoDB replica set not required, create-prisma flags and scripts, `npm create prisma@latest`, SQLite ships, upgrade-guide version targets, `// use prisma-next`, `db.close()`, enum ordering, the scalar table, the skills page, the tutorial's starter model, the extensions recipe, streaming does not stream on `postgres()` | B5 to B9, B23, B25, B26, B28 to B35 | -**B32. Guides index.** `guides/index.mdx` lists "Upgrading" and "Databases" under "Coming as they land" while the upgrade guide exists and is in the nav. Fold into A4. +Two audit claims were overruled by the source during implementation and the pages left as they were: `migration plan` can raise `MIGRATION.NO_TARGET` after a rollback cycle, and `min`/`max` over a `DateTime` column type-checks at rc.9. ## C. New pages -**C1. Coming from Prisma 7.** The mapping table from `mental-model.md`, in four sections: schema and types, CLI commands, client API, and "not in Prisma 8 yet" with a status per item. The last section is the one users asked for most and the one no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types (with a link to the PRs), `@updatedAt` (rejected with a hint to use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`). Unblocks J3. Depends on A2 for placement. - -**C2. Add Prisma ORM to an app you already started.** The J1 page. Starts from "you have a project directory and an empty or absent database". `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since it is the case reported, with a note for Node. Replaces the Bun guide's scaffold-first opening or sits beside it. - -**C3. Adopt an existing database.** The J2 page, split out from the current existing-project page so B3 and B15's fixes have room. Adds what to expect from `contract infer` (it is SQL-only; it captures indexes, checks, RLS, and 1:1 relations from unique indexes; it emits Temporal-backed `Timestamp` types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, and the second migration with `--advance-ref db`. Depends on D1 for how short this can be. - -**C4. Prisma ORM 8 release status.** One short page: Prisma ORM 8 is a release candidate; GA expected in the window Will has stated publicly; Prisma ORM 7 receives bug fixes and security updates for 12 months; `npx prisma` and `npm install prisma` now resolve to Prisma ORM 8; to stay on 7, install `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. Depends on D6 for whether the tag stays. - -**C5. Editor setup.** VS Code extension location (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `contract.prisma` needs `// use prisma-next` on line one, and `prisma contract format` as the fallback. Under getting started. Unblocks J7. Needs Serhii to confirm the current state. - -**C6. Types.** Model types, result types, where and input types, with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch and published the day prisma/orm#30231, #30236, and #30158 ship. Unblocks J9. Also covers what `contract.d.ts` already exports today: `AddressInput` beside `AddressOutput`, `FieldOutputTypes`, `TypeMaps`, `QueryOperationTypes`, `AggregateTypes`. - -**C7. Advanced Postgres.** The audit answered the product questions the first brief left open: RLS and policies are expressible in PSL (`@@rls`, `policy_select` and siblings, `role` blocks) and in the TypeScript builder; expression and partial indexes are `@@index(expression:, where:, unique:, type:)`; hand-written checks are `@@check`; `@noCheck` waives generated checks; `installExtension` / `createExtension` are migration factories; `@@control` sets how much of a table Prisma manages. None of it is on the site. Write the page from `skills/prisma-8/references/contract.md:101-108,265-367` and `packages/2-sql/2-authoring/contract-psl/README.md`. Unblocks J8. Audit: `contract`, `gaps`. - -**C8. Money and Decimal.** Short page or section under data modeling: cents as integers (already there), `Decimal` with precision and scale in type position (`Numeric(p, s)`), what `@default` accepts on it, and the aggregate return types (`avgDecimal`). Answers the open Discord question. - -**C9. Deploying Prisma ORM 8.** (See also the production caveat at the end of this item.) There is no Prisma ORM 8 deployment guide for any host; all six `guides/deployment/*` pages are Prisma 7 (A7). What a deploy needs is in the source: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). One page with sections for Docker, Vercel, Cloudflare Workers, and monorepos, or one page per host under the same label. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, 128 MiB isolate memory so `limit()` is the memory cap) and carries a production caveat with zero site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s), workaround `cursor: { disabled: true }`. Evidence: `skills/prisma-8/references/build.md:421-435`, `migrations.md:487`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. Audit: `gaps`, `extras`. - -**C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, the async `supabase({ contractJson, url, jwksUrl | jwtSecret })` factory, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*` reads, and `SUPABASE.JWT_INVALID` / `SUPABASE.CONFIG_INVALID`. A page under `orm/extensions/` and a guide. Evidence: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. Audit: `gaps`. - -**C11. CI with Prisma ORM 8.** The only CI guide is Prisma 7 (A7). The Prisma ORM 8 shape: `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Evidence: `skills/prisma-8/references/migration-review.md:172-197`, `cli/src/orm/migration/status-findings.ts`. Audit: `gaps`, `migrations-cli`. - -**C12. Switching from another ORM, and team schema workflow.** The three `switch-to-prisma-orm/*` and three `database/*` guides are Prisma 7 (A7). The Prisma ORM 8 replacements are the brownfield flow (`orm init`, `contract infer --output`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Much of C3 and C11 can be reused. Audit: `start-guides`. - -**C13. Migration factory reference.** The site shows six migration factories (`createSchema`, `createTable`, `addColumn`, `setNotNull`, `dataTransform`, `rawSql`). The `Migration` base class has about thirty: indexes, foreign keys, uniques, checks, column type and default changes, native enum create / drop / add-value, `installExtension`, RLS enable / disable, policy create / drop / rename, plus the free factories `createExtension`, `foreignKey`, `unique`, `checkExpression`, `fn`, `lit`. Also the `node migration.ts` self-emit CLI's `--dry-run` and `--config`. A reference page beside `editing-a-migration.mdx`. Evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. Audit: `migrations-cli`. - -**C14. PSL and TypeScript builder completeness.** Not a new page but a rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. Missing from PSL: native types in type position (`Uuid`, `VarChar(255)`, `Numeric`, `Timestamptz`, `TimestamptzString`, `Jsonb`, `BigIntNumber`, `UnboundedInt`, and the rest), the `@default` generator list (`uuid(4|7)`, `cuid(2)`, `ulid()`, `nanoid(n)`, `dbgenerated`), `temporal.createdAt()` / `updatedAt()` presets, scalar lists and which targets support them, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks and cross-space relation targets, `native_enum` blocks, `@relation("Name")` disambiguation, `onDelete` / `onUpdate`, extension types inline in field position, MongoDB index options (`sort:`, `@@textIndex`), and `.variant()` for polymorphic reads. Missing from the TypeScript page: the field helpers beyond four, `.attributes()` for composite keys and uniques (the page shows no way to declare a composite primary key), `constraints.index`, `check`, `.noCheck()`, `rel.belongsTo().sql({ fk })`, `foreignKeyDefaults` / `naming`, the `output` config option, and the MongoDB builder's `valueObject`, `index`, `enumType`, `field.vector()`, and polymorphism. Evidence: `packages/2-sql/2-authoring/contract-psl/README.md`, `contract-ts/README.md`, `packages/2-mongo-family/2-authoring/contract-ts/README.md`. Audit: `contract`. - -**C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute` and `RuntimeStatementStats`; `verifyMarker: 'onFirstUse' | false` (the startup check core-concepts describes without saying how to control it); `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat accessor form `db.orm.User` for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the optional `configure(meta)` callback on every terminal and `meta.annotate(...)` (how cache opt-in works per query); `distinctOn` needs the `postgres.distinctOn` capability; MongoDB `mode: 'strict' | 'permissive'` and the filter classes `MongoAndExpr`, `MongoNotExpr`, `MongoExistsExpr`; the SQLite facade lifecycle; the driver-free static client (`@prisma/orm-postgres/static`); `db.prepare` and prepared bind sites on `limit()` / `offset()`; `ctx.signal` and `MongoMiddleware` on the middleware pages; `createInMemoryCacheStore` and the cache debug events; `RUNTIME.MISSING_EXTENSION_PACK`; `fns.cosineSimilarity`. Audit: `orm-client`, `builders`. - -**C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; Vite 7 and 8; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides (SvelteKit, Astro, Nuxt, TanStack Start) tell readers to run `contract:emit` by hand. A section on `the-contract-artifact.mdx` plus one paragraph per framework guide. Evidence: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`, `skills/prisma-8/references/build.md`. Audit: `gaps`, `contract`. - -**C18. Supported versions and requirements.** No page states the floors. The monorepo's `docs/Supported Versions.md` says Node 24, Bun 1.2, Deno 2.0, PostgreSQL 15, MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, and ESM-only with no CommonJS. The site says Bun 1.1, states no PostgreSQL floor anywhere, says nothing about ESM or `strict`, and the upgrade guide shows `module: nodenext`. The doc's Node 24 disagrees with the scaffold's `^22.18.0 || >=24.11.0` (B8) and its `--merge-tsconfig` flag does not exist at rc.9, so confirm each number with product before publishing. One short page under getting started, linked from every quickstart. Audit: `extras`. - -**C19. Extension pages beyond pgvector.** PostGIS (`Geometry` type, its seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), and arktype-json (`arktypeJson(schema)`, never shown) each have one catalog row. One section per pack on `using-extensions.mdx` or one page each, with the real public import paths. Audit: `extras`. - -**C20. Telemetry page.** `cli/telemetry.mdx` never mentions `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file and its `enableTelemetry` field, that CI never sends, the first-run notice, that the preference is per-user, agent detection, or the event fields (the monorepo's `docs/Telemetry.md` is itself stale: rc.9 also sends `exitCode`). The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, not this page. Evidence: `packages/1-framework/3-tooling/cli-telemetry/src/`, `cli/src/orm/telemetry/reporting.ts`. Audit: `extras`. - -**C17. CLI page additions.** `cli/configuration.mdx`: the `migrations.dir` and `formatter` keys, the `composer` section every scaffold ships, telemetry opt-out variables (`DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`). `cli/orm-init.mdx`: the full flag list, exit codes 4 and 5, `prisma-next.md`, `--confirm` for re-running. `cli/db-update.mdx`: it never plans `data`-class operations. `cli/migration-ref.mdx`: the refusals. `cli/migration-new.mdx`: default origin rules. `cli/migration-status.mdx`: `--json` diagnostics. `cli/db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH` and `PATH_UNREACHABLE`. `cli/contract-emit.mdx`: `--json` output and the `output` config option. `cli/index.mdx`: `@prisma/orm-toolchain` and `@prisma/orm-framework`. Audit: `migrations-cli`, `contract`, `gaps`. +Grouped by where the page lives. Each says what the page is for, what it must cover, where the facts come from, and what it waits on. -## D. Change the ORM +### Entry pages -These are places where the docs are hard because the tool is. Each is a candidate for the product backlog, not a docs fix. D1 and D3 have briefs (`brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`) and are handed off. +- **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. +- **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. +- **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, the second migration with `--advance-ref db`. Unblocks J2. Waits on D1, which decides how short it can be. +- **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for twelve months; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. Waits on Will (facts) and D6 (whether the tag stays). +- **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. +- **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Waits on Serhii. -**D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan --name baseline` (or equivalent), `migration ref set db `. Two options: have `db sign` also set the `db` ref when no ref exists, or add a `db adopt` command that runs sign plus ref. Either removes the recreate-everything trap in J2 and cuts C3 in half. Handed off. +### Guides -**D2. `migration plan` with no origin and no migrations on disk.** The CLI refuses when migrations exist on disk with no ref (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). When no migrations exist it silently plans from empty. For a signed database with no ref that is the wrong default; it should warn or refuse the same way. Related to D1. +- **C9. Deploying Prisma ORM 8.** Zero coverage today for any host. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. +- **C11. CI.** `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. +- **C12. Switching from another ORM; team schema workflow.** Replaces the six Prisma 7 guides A7 removes. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. +- **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. -**D3. Opt out of agent files at scaffold time.** `create-prisma` has no flag and always writes all four agents plus a `postinstall`. Add a prompt and a `--skills none` flag, and have `orm init` ask. Five users in one week; the circulating workaround is wrong. Handed off. +### Reference completeness -**D4. Missing client API.** Verified absent from the SQL ORM client source: `firstOrThrow` on the collection (it exists on `AsyncIterableResult`, so `.all().firstOrThrow()` works and could be documented as the workaround), atomic `increment`/`decrement` on update, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), and filtering on JSON columns by path or containment (the `jsonb` codec declares only the `equality` trait and the SQL builder has no `->>` or `@>` functions; the workaround is `db.raw.sql`). Also confirmed not supported, for C1's "not yet" list: soft delete, model validations, lifecycle callbacks, custom `Collection` subclasses (`CollectionImpl` has private clone methods), read replicas and multi-database routing, MongoDB referential actions. Each needs a decision: build it, or document the workaround (SQL builder or raw) and say it is not planned. The types work (`Models`, `Shape<>`, where types) is already in PRs. +- **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. +- **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch; publish when prisma/orm#30231, #30236, #30158 ship. Also what `contract.d.ts` already exports today. Unblocks J9. +- **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. +- **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. +- **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. +- **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. +- **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. +- **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. +- **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. -**D5. `contract infer` output on Prisma 7 databases.** Users report the inferred contract failing to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether infer on rc.9 still emits removed syntax, and whether the `Decimal @default(0.00)` failure is a bug. Infer should produce a contract that emits. See also D10. +## D. Change the ORM and its tooling -**D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Either move the RC to a `next` tag until GA or state the policy on C4. Serhii said he would find out why; no update. +Places where the docs are hard because the tool is. Grouped by who owns the fix. -**D7. `db.connect()` versus `db.runtime()`, and `db.close()` versus `db.runtime().close()`.** Two names for adjacent things, used interchangeably across pages, with a Mongo-only `await`, and now a third pair for teardown. `db.prepare` followed by `db.connect()` throws `DRIVER.ALREADY_CONNECTED` because `prepare` connects in the background. If the API can be one call on both targets, the docs get simpler on every page that shows a script. +### ORM behaviour -**D8. Streaming does not stream.** `postgres()` builds its driver with `cursor: { disabled: true }`, so `for await` over a result iterates an already-buffered array; only the serverless facade exposes cursor batches. The reading-data page promises the opposite. Either expose `cursor` / `batchSize` on `postgres()` or drop the promise (B25). Evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`, `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:39-53`. +- **D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan`, `migration ref set db `. Either `db sign` sets the `db` ref when none exists, or a `db adopt` command does sign plus ref. Removes the recreate-everything trap in J2 and halves C3. In progress; brief in `brief-db-ref-on-adoption.md`. +- **D2. `migration plan` with no origin and no migrations on disk plans from empty silently.** With migrations on disk it refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). For a signed database with no ref the silent case is the wrong default; it should warn or refuse the same way. +- **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. +- **D13. `migration ref set … @db` fails** with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the marker. Support it when a connection is available, or reject it with a message that says why. Source: `cli/src/control-api/operations/ref.ts:104-118`. +- **D15. `db update` never plans data operations.** A change that needs a backfill fails and the user must switch to `migration plan`; nothing says so. Allow it, or print the hint. Source: `cli/src/control-api/operations/db-update.ts:17`. +- **D16. `migration status` exits 0 on warnings.** CI has to parse `--json`. A `--strict` flag or a non-zero exit on warn-level findings makes C11 one line. Source: `cli/src/orm/migration/status-findings.ts`. +- **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. +- **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. +- **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js before 26.8.2 every read throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. +- **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. -**D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the `db` ref only when `--db` is omitted; with `--db` they do not unless `--advance-ref` is also passed. Every doc example passes `--db`, and the result is `MIGRATION.PLAN_ORIGIN_UNKNOWN` on the second plan. The rule is surprising and undocumented. Consider advancing regardless of how the URL was supplied, or warning when `--db` is used without `--advance-ref` and no `db` ref exists. Related to D1 and D2. Evidence: `cli/src/control-api/operations/ref-advancement.ts:19-28`. +### Product decisions -**D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps `timestamp` / `timestamptz` columns to Temporal-backed `Timestamp` / `Timestamptz`; on Node.js before 26.8.2 (checked: 26.8.1, 24.16, and 22.22 have no `globalThis.Temporal`; 26.8.2 does) every read of such a column throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported first. `create-prisma` installs the polyfill; `orm init` does not, and neither the existing-project page nor the upgrade guide mentions it, so real upgrades with `DateTime` columns break after step 3. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit time with a clear message. Evidence: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`, `packages/3-targets/3-targets/postgres/src/core/errors.ts:74-86`. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work (`Models`, `Shape<>`) is in PRs. +- **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. -**D11. create-prisma pins rc.8.** `create-prisma@0.11.7` pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` (to match a Composer peer dependency), so a fresh scaffold does not get the rc.9 behaviour the site documents. Either bump on every RC or document the lag. Evidence: `wip/create-prisma-src/src/constants/dependencies.ts:8-10`. +### create-prisma -**D12. Permissive mode is unreachable on Postgres.** `postgres(...)` never forwards a `mode`, so the runtime is always strict and every "warn in permissive mode" path on the lints and budgets pages cannot happen; only `mongo(...)` accepts `mode`. Either expose `mode` on `postgres()` or remove the branches and the docs. Evidence: `packages/3-extensions/postgres/src/runtime/postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. +- **D3. Opt out of agent files at scaffold time.** No flag exists; every scaffold writes all four agent directories plus a `postinstall` hook. Add a prompt and `--skills none`, and have `orm init` ask. In progress; brief in `brief-skills-opt-out.md`. +- **D11. create-prisma pins rc.8.** `create-prisma@0.11.7` pins the ORM packages to `8.0.0-rc.8` for a Composer peer dependency, so fresh scaffolds lag the site. Bump on every release candidate, or document the lag. Source: `create-prisma/src/constants/dependencies.ts:8-10`. +- **D18. The MongoDB scaffold writes a `.env` nothing reads.** It contains `DATABASE_URL`; the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file. Source: `create-prisma/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`. +- **Node 24.0 to 24.10.** The generated `package.json` declares `^22.18.0 || >=24.11.0` while create-prisma itself accepts `>=22.18.0`. Nobody could say why the 24 sub-range is excluded. Worth a question to the owner. -**D13. `migration ref set … @db` fails.** `@db` parses to the empty sentinel for the offline command and fails with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the database marker. Either support it (read the marker when a `--db` is available) or reject it with a message that says so. Evidence: `cli/src/control-api/operations/ref.ts:104-118`. +### The agent skill -**D14. The shipped skill is stale in the same places as the site, and a few more.** (Also: `cipherstash.EncryptedString` as the canonical extension example although that package was dropped, `createTelemetryMiddleware` from a package that does not exist, and no mention of the cache middleware.) Will said skills are not the focus, but every audit found the skill wrong where the site is wrong, and it is what agents read. Verified stale in `skills/prisma-8/references/`: `execute` for row reads (should be `query`), `PN-CLI-*` / `PN-MIG-*` / `PN-RUN-*` codes (dotted since 0.17), the flat `defineConfig` config file (envelope since rc.4), `orm init --skip-skills` and the `prisma/contract.prisma` default (`src/prisma/`), "N:M include and nested mutations unsupported" (they work), `pn_meta_marker` (it is `prisma_contract.marker`), `createTelemetryMiddleware` from a package that does not exist, `@@discriminator` / `@@base` "SQL-only" (Mongo has them), scalar lists "rejected" (Postgres accepts them), `-y` for destructive consent (it is `--confirm `), free-function migration factories (they are `this.` methods), `migration show` with no argument (positional required). One ticket to the skills owner with this list; the audit files have the line numbers. +- **D14. `skills/prisma-8/` is stale in the same places the site was, and more.** Twenty-one verified defects, the worst being row reads through `execute()`, `PN-*` error codes that no longer exist anywhere, and the flat config file removed in rc.4. It ships inside the ORM packages and is what coding agents read instead of the site. Brief ready to hand over: `brief-skill-staleness.md`. -**D15. `db update` never plans data operations.** Its allowed classes are additive, widening, destructive; a change that needs a backfill fails and the user must switch to `migration plan`. Undocumented. Either allow it or print the switch hint. Evidence: `cli/src/control-api/operations/db-update.ts:17`. +### Monorepo docs hygiene -**D16. `migration status` exits 0 on warnings.** CI must parse `--json` `diagnostics[]` to catch `MIGRATION.DIVERGED`, `MARKER_NOT_IN_HISTORY`, `CONTRACT.AHEAD`, `NO_MARKER`. A `--strict` flag or a non-zero exit on warn-level findings would make C11 one line. Evidence: `cli/src/orm/migration/status-findings.ts`. +- **D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` disagrees with the site's capabilities page on key namespacing, pack key nesting, the error code spelling, and whether capabilities are fixed at emit or negotiated at connect. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`, which does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md`, from which the site's error reference is generated verbatim, still says `ref set` and `prisma ref set` in eight entries (the command is `migration ref set` since rc.5). `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Until reconciled, the audit treats `packages/` and `docs/releases/` as the only truth. -**D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` and the site's capabilities page disagree on key namespacing (`sql.lateral` vs `postgres.lateral`), pack key nesting, the error code spelling, and whether capabilities are negotiated at connect time or fixed at emit time. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`; the scaffold says 22.18 and the flag does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md` (from which the site's ORM error reference is generated word for word) still writes `ref set`, `ref list`, and `prisma ref set ` in eight entries; the mounted command has been `migration ref set` since rc.5, so the fix belongs in the error definitions' `fix` text. `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Whoever owns `docs/` in the monorepo should reconcile these before the site is written from them; until then the audit treats `packages/` and `docs/releases/` as the only truth. +## Naming -**D18. create-prisma's MongoDB scaffold writes a `.env` nothing reads.** For MongoDB the scaffold writes `.env` with `DATABASE_URL`, but the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file, so the file is dead and the CLI's own next-step text says to set `MONGODB_URL` in the environment. Found during the PR 3 review. Evidence: `wip/create-prisma-src/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`, `src/tasks/prisma-setup/presentation.ts:46`. +The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR after A7. -## Unverified, carried from the audits +## Open questions -Things the agents flagged but could not confirm against the monorepo, mostly because the `prisma` binary and `@prisma/cli-engine` live in the uncloned `prisma-cli` repo. Check before acting: the global `--yes` flag on `db migrate`; `cli/global-flags.mdx`, `cli/init.mdx`, `cli/skills.mdx` wholesale; `definePrismaConfig` from `prisma/config` versus `@prisma/cli-engine`; `HostedStateBootstrapError` and `--name`; Mongo `_id` decoding through `$lookup` and `findOneAndUpdate`; `_id` equality inside `match()`; the apply order of extension spaces versus `app`; whether `DateTime` still parses in PSL now that the starter contract writes `TimestamptzString`; the raw `EXTRACT(...)` codec claim; the `ilike` `fns` helper; "ParadeDB and Supabase are experimental"; which agent directory list is current (`ai/tools/skills.mdx` says Claude Code, Cursor, Codex, Windsurf; `cli/skills.mdx` and the scaffold say `claude`, `cursor`, `agents`, `devin`); whether `npx skills add` wants `prisma/prisma/skills` or `prisma/orm/skills`; the real capability key strings (see D17). Full list in the `## Unverified` section of each audit file. +Things the audit flagged but could not settle, mostly because the `prisma` binary and `@prisma/cli-engine` live in the `prisma-cli` repo, which was not audited: the global `--yes` flag on `db migrate`; `cli/global-flags.mdx`, `cli/init.mdx`, `cli/skills.mdx` as whole pages; `definePrismaConfig` from `prisma/config` versus `@prisma/cli-engine`; `HostedStateBootstrapError` and `--name`; Mongo `_id` decoding through `$lookup` and `findOneAndUpdate`; `_id` equality inside `match()`; the apply order of extension spaces versus `app`; whether `DateTime` still parses in PSL now that the starter writes `TimestamptzString`; the raw `EXTRACT(...)` codec claim; the `ilike` `fns` helper; "ParadeDB and Supabase are experimental"; which agent directory list is current (the skills page says Claude Code, Cursor, Codex, Windsurf; `cli/skills.mdx` and the scaffold say `claude`, `cursor`, `agents`, `devin`); whether `npx skills add` wants `prisma/prisma/skills` or `prisma/orm/skills`; the real capability key strings. Each audit file has an `## Unverified` section with what was checked. From 18b607ddc183d0530c4d7805db841befab8bf8fd Mon Sep 17 00:00:00 2001 From: reviewer Date: Fri, 11 Sep 2026 12:45:10 +0000 Subject: [PATCH 04/68] docs: correct repo names, PR status, and citation key in the ORM docs audit The audit's citations use the worktree layout it was run in (wip/prisma-src, wip/create-prisma-src, wip/web); README now says what each prefix maps to. The db-ref brief named the monorepo prisma/prisma and said PRs go to prisma/orm; it is one repository, renamed, so name it once. The "shipped" wording for section B overstated PR 3: #8238 is still open. The model and result type work is no longer "in open PRs": prisma/orm#30158 is in rc.9, and #30231 / #30236 merged to main on 2026-09-10 and await a tagged release. --- docs/orm-docs-audit/README.md | 6 ++++-- docs/orm-docs-audit/brief-db-ref-on-adoption.md | 2 +- docs/orm-docs-audit/changes.md | 12 ++++++------ docs/orm-docs-audit/ia.md | 2 +- docs/orm-docs-audit/journeys.md | 8 ++++---- docs/orm-docs-audit/mental-model.md | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 86d3af4ed99..b41a63e6f84 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -2,15 +2,17 @@ Working documents behind the Prisma ORM 8 docs corrections (prisma/web #8236, #8237, #8238) and the proposed restructure. Written September 2026 against `@prisma/orm-postgres@8.0.0-rc.9`; source paths refer to the prisma/orm monorepo at that tag (`packages/`, `docs/releases/`, `examples/`, `skills/prisma-8/`) and to prisma/create-prisma. Site paths are relative to `apps/docs/content/docs/`. +Citations in `audit/`, `changes.md`, and the briefs use the worktree layout the audit was run in: `wip/prisma-src/` is prisma/orm (formerly prisma/prisma; the old name still redirects) at `v8.0.0-rc.9`, `wip/create-prisma-src/` is prisma/create-prisma, `wip/web/` is this repository, and `wip/docs-audit/` is this directory. Strip the prefix to get the path in the named repository. + Read in this order: 1. `personas.md` — who reads the ORM docs: the Newcomer, the Upgrader, the Builder, the Agent. 2. `journeys.md` — ten jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. 3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. 4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. -5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B, shipped), new pages (C), ORM changes (D). Leads with the suggested order. +5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; #8236 and #8237 are merged, #8238 is open as of 2026-09-11), new pages (C), ORM changes (D). Leads with the suggested order. 6. `naming.md` — the "Prisma ORM" naming rule. -7. `slice-corrections.md` — how the shipped corrections were sliced, and the decisions taken. +7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. 8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). 9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. diff --git a/docs/orm-docs-audit/brief-db-ref-on-adoption.md b/docs/orm-docs-audit/brief-db-ref-on-adoption.md index 77d8448fb8e..a6c95aafc6a 100644 --- a/docs/orm-docs-audit/brief-db-ref-on-adoption.md +++ b/docs/orm-docs-audit/brief-db-ref-on-adoption.md @@ -1,6 +1,6 @@ # Brief: set the `db` ref when a database is adopted -Written 2026-09-10 for an agent with no prior context. Repo: `prisma/prisma` `main` (the Prisma 8 monorepo, rc.9). PRs go to `prisma/orm`. +Written 2026-09-10 for an agent with no prior context. Repo: `prisma/orm` `main` (the Prisma 8 monorepo, rc.9; formerly `prisma/prisma`, and the old name still redirects). ## What we want diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index ef0458832df..347e6b4cf76 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -8,7 +8,7 @@ Status as of 2026-09-11. ## Where things stand -**Shipped.** Every correction to an existing page (section B, 35 items) went out in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist), #8237 (pages whose explanations were wrong), and #8238 (facts on the getting-started pages and guides). Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. +**Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. **In progress.** A7 (moving the sixteen Prisma 7 guides out of the Latest tree) is with Ankur. D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. @@ -48,11 +48,11 @@ The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These a - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. - **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** In progress (Ankur). `guides/frameworks/react-router-7`, `solid-start`, all of `guides/deployment/*`, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` are Prisma 7 end to end and have no copy under `guides/v7/`. Move with the same slugs and redirects; the Latest sidebar loses those labels until C9, C11, and C12 replace them. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. -- **A4** (sidebar labels and the guides index) shipped in #8238. +- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. -## B. Corrections to existing pages (shipped) +## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) -Thirty-five items, all verified against rc.9 source and shipped in #8236, #8237, #8238. What they fixed, in order of how many readers they hit: +Thirty-five items, all verified against rc.9 source, in #8236 and #8237 (merged) and #8238 (open as of 2026-09-11). What they fixed, in order of how many readers they hit: | Theme | What was wrong | Items | |---|---|---| @@ -93,7 +93,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. -- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch; publish when prisma/orm#30231, #30236, #30158 ship. Also what `contract.d.ts` already exports today. Unblocks J9. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on prisma/orm `main` (#30231 and #30236 merged 2026-09-10); publish when the first tagged release after rc.9 ships them. #30158 (reusable where filter types) is already in rc.9. Also what `contract.d.ts` already exports today. Unblocks J9. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. - **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. @@ -122,7 +122,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work (`Models`, `Shape<>`) is in PRs. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work is merged: the where filter types (#30158) are in rc.9; `Models` and `Shape<>` (#30231, #30236) are on `main` awaiting a tagged release. - **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. ### create-prisma diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index eae7f207300..6a2ec40b277 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -96,7 +96,7 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | J6 data types | Data Modeling > Overview | right node; one stale example | | J7 editor setup | none | no node | | J8 advanced Postgres | none | no node; needs product answers | -| J9 types | none | no node; API in PRs | +| J9 types | none | no node; API merged, awaiting a tagged release | | J10 opt out of agent files | CLI > configuration | right node, unreachable from Getting Started | Two observations follow from the table. diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index b2bd7e7bcc7..8a840266a51 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -50,7 +50,7 @@ Path today: - The bulk count mutations are taught as `createCount`/`updateCount`/`deleteCount` (31 sites on two pages). They were renamed to `createAndCount` and friends in 0.17. - `createMany` appears on no Prisma 8 page. `createAll` and `createAndCount` are documented but nothing says they replace it. `skipDuplicates` has no equivalent and no page says so. - `findUniqueOrThrow`, `findFirstOrThrow`, atomic `increment`/`decrement`, and case-insensitive filters have no Prisma 8 equivalent in the SQL ORM client source. No page says so. -- `$transaction([...])` is covered in one inline block. `Prisma.UserGetPayload` and the model types have no page at all; the replacements are in open PRs. +- `$transaction([...])` is covered in one inline block. `Prisma.UserGetPayload` and the model types have no page at all; the replacements (`Models`, `Shape<>`) merged to prisma/orm `main` on 2026-09-10 (#30231, #30236) and are not in a tagged release as of rc.9. - Accessor casing (`prisma.user` became `db.orm.public.User`) is stated once in reading-data and nowhere else. Verdict: **red**. The answers that exist are scattered, two of them are wrong, and the missing features are not admitted. @@ -117,9 +117,9 @@ Who: Newcomer and Upgrader. Done: `type User = ...` and the type of a query result, without reading `contract.d.ts`. -Path today: no page. `ResultType` for SQL builder plans is the only documented helper. The `Models` namespace, `Shape<>`, and where-type exports are in open PRs. +Path today: no page. `ResultType` for SQL builder plans is the only documented helper. The `Models` namespace and `Shape<>` (prisma/orm#30231, #30236) merged to `main` on 2026-09-10 and are not in a tagged release as of rc.9; the where-type exports (#30158) shipped in rc.9. -Verdict: **red** until the PRs ship, then a page is needed on release day. +Verdict: **red** until the next tagged release carries `Models` and `Shape<>`, then a page is needed on release day. ## J10. Stop Prisma from writing agent files into my repo @@ -143,5 +143,5 @@ Verdict: **amber** for docs, **red** for the tool. | J6 data types | amber | remove `@db.` example, add attribute map | | J7 editor | red | new page | | J8 advanced Postgres | red | product decision first | -| J9 types | red | page on PR merge | +| J9 types | red | page on the next tagged release | | J10 agent files | amber | one line on three pages | diff --git a/docs/orm-docs-audit/mental-model.md b/docs/orm-docs-audit/mental-model.md index 8f70f0eeafb..ad09b022ffd 100644 --- a/docs/orm-docs-audit/mental-model.md +++ b/docs/orm-docs-audit/mental-model.md @@ -100,7 +100,7 @@ Why a graph and not a list: two branches can each add a migration, and the graph | `createMany` | `createAll` (rows back) or `createAndCount` (count back) | the return shape is in the name | | `$transaction([...])` | `db.transaction(async tx => ...)` | callback form only | | `@db.Text`, `@db.VarChar(n)` | `Text`, `VarChar(n)` in type position | native types are types, not attributes | -| `Prisma.UserGetPayload<...>` | `Shape<...>` (in an open PR) | not shipped yet | +| `Prisma.UserGetPayload<...>` | `Shape<...>` (merged to prisma/orm `main` 2026-09-10, #30231) | not in a tagged release as of rc.9 | | `skipDuplicates`, `increment`, `findUniqueOrThrow`, `mode: "insensitive"` | no equivalent yet | say so plainly | ## The eight words From 7e815e77bf578fd79d6c8127828d4f173bcd089d Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 15:11:03 +0200 Subject: [PATCH 05/68] docs: keep the audit design documents free of progress state personas, journeys, mental-model, ia, naming, and the briefs describe readers, jobs, the target structure, and the reasoning; they carry no done/in-progress markers, so they do not go stale as work lands. journeys: per job, what the docs must provide and where the structure fails, with the IA node that serves it. mental-model: naming, the plan origin rule, whole-query raw SQL, the db ref rules and the adoption design. Keeps the repo-name and tagged-release facts from the previous commit. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../brief-db-ref-on-adoption.md | 8 +- docs/orm-docs-audit/brief-skills-opt-out.md | 10 +- docs/orm-docs-audit/ia.md | 26 ++-- docs/orm-docs-audit/journeys.md | 131 ++++++++---------- docs/orm-docs-audit/mental-model.md | 36 ++--- docs/orm-docs-audit/naming.md | 10 +- docs/orm-docs-audit/personas.md | 16 +-- docs/orm-docs-audit/slice-corrections.md | 89 ++---------- 8 files changed, 130 insertions(+), 196 deletions(-) diff --git a/docs/orm-docs-audit/brief-db-ref-on-adoption.md b/docs/orm-docs-audit/brief-db-ref-on-adoption.md index a6c95aafc6a..a0710d1aede 100644 --- a/docs/orm-docs-audit/brief-db-ref-on-adoption.md +++ b/docs/orm-docs-audit/brief-db-ref-on-adoption.md @@ -1,6 +1,6 @@ # Brief: set the `db` ref when a database is adopted -Written 2026-09-10 for an agent with no prior context. Repo: `prisma/orm` `main` (the Prisma 8 monorepo, rc.9; formerly `prisma/prisma`, and the old name still redirects). +Written 2026-09-10 for an agent with no prior context. Repo: `prisma/orm` `main` (the Prisma ORM 8 monorepo; formerly `prisma/prisma`, and the old name still redirects). Verified against rc.9. ## What we want @@ -28,9 +28,9 @@ The docs site (`prisma/web`) changes are handled separately; note in the PR what ## The problem -A user with an existing database brings it under Prisma 8 by running `contract infer`, `contract emit`, and `db sign`. That is what the getting-started page for existing projects tells them to do. Then they change the contract and run `migration plan`. The plan proposes creating every table again. +A user with an existing database brings it under Prisma ORM 8 by running `contract infer`, `contract emit`, and `db sign`. That is what the getting-started page for existing projects tells them to do. Then they change the contract and run `migration plan`. The plan proposes creating every table again. -Cause: `migration plan` takes its origin from `--from`, else the `db` ref, else the empty contract. `db sign` writes the database marker but never sets the `db` ref, and there are no migrations on disk, so the plan resolves to the empty origin and the CLI does not refuse (the `MIGRATION.PLAN_ORIGIN_UNKNOWN` refusal only fires when migrations already exist on disk). +Cause: `migration plan` takes its origin from `--from`, else the `db` ref, else the empty contract. `db sign` writes the database marker but never sets the `db` ref, and there are no migrations on disk, so the plan resolves to the empty origin and the CLI does not refuse (the `MIGRATION.PLAN_ORIGIN_UNKNOWN` refusal only fires when migrations already exist on disk). Once the graph has a snapshot the `db` ref can point at, `migration plan` writes an automatic baseline package; the gap is only that nothing after `db sign` creates that snapshot or the ref. Two Discord users hit this in one week and asked what `--from` is for. The incremental upgrade guide avoids it by teaching three extra commands (`migration plan --name baseline`, `db sign`, `migration ref set db `), and the "add to existing project" page does not teach them at all. @@ -49,5 +49,5 @@ Two Discord users hit this in one week and asked what `--from` is for. The incre - Plan command and origin flag: `packages/1-framework/3-tooling/cli/src/orm/migration/plan.ts`, `control-api/operations/migration-plan.ts` - Refusal text: `PLAN_ORIGIN_UNKNOWN` in `packages/1-framework/3-tooling/cli/src/utils/cli-errors.ts` - Existing ref tests: `test/integration/test/cli.db-ref-advancement.e2e.test.ts` -- The documented workaround: `wip/web/apps/docs/content/docs/guides/upgrade-prisma-orm/postgresql.mdx` §4.1 to 4.3 +- The documented workaround: `prisma/web` `apps/docs/content/docs/guides/upgrade-prisma-orm/postgresql.mdx`, sections 4.1 to 4.3 - Migration graph ADRs: search `docs/architecture docs/adrs/` for "ref" diff --git a/docs/orm-docs-audit/brief-skills-opt-out.md b/docs/orm-docs-audit/brief-skills-opt-out.md index 917d02d7fb0..568020ae815 100644 --- a/docs/orm-docs-audit/brief-skills-opt-out.md +++ b/docs/orm-docs-audit/brief-skills-opt-out.md @@ -1,19 +1,19 @@ # Brief: let users opt out of agent skill files at scaffold time -Written 2026-09-10 for an agent with no prior context. Repos: `prisma/create-prisma` (the scaffolder) and `prisma/prisma-cli` (the unified `prisma` binary, whose `init` and `orm init` commands are involved). A read-only clone of create-prisma is at `wip/create-prisma-src` in this worktree. +Written 2026-09-10 for an agent with no prior context. Repos: `prisma/create-prisma` (the scaffolder, checked at 0.11.7) and `prisma/prisma-cli` (the unified `prisma` binary, whose `init` and `skills` commands are involved). ## What we want 1. `create-prisma` asks. Add a prompt in the interactive flow, "Install agent skills for coding assistants?" or similar, alongside the existing prompts, defaulting to yes. Add a flag for the non-interactive path, `--skills ` matching `prisma init --skills`, so `--yes` plus `--skills none` produces a project with no agent files, no `postinstall` hook, and `skills: { agents: [] }` in the config. 2. When the answer is no, the generated project has no `.claude/`, `.cursor/`, `.agents/`, or Devin directories, no `postinstall`, and no `skills:sync` script. `prisma-next.md` is a separate question: decide whether it is an agent file or a human readme and treat it accordingly. -3. `prisma orm init` on the existing-project path asks the same question when interactive, and honours `--skills` for parity with `--skip-skills`. +3. `prisma init` on the existing-project path (the command that installs skills; `orm init` stopped touching skills in rc.6) asks the same question when interactive, and honours `--skills`. 4. Removing skills after the fact: `prisma skills sync` with `agents: []` should remove the directories it previously wrote, or there should be a `prisma skills remove`. Decide which; the current behaviour (write nothing, leave the old copies) means the config opt-out looks like it did nothing. ## Acceptance - `create-prisma my-app --yes --skills none` produces a project with none of the four agent directories, no `postinstall`, and `agents: []` in the config. Test in create-prisma's `tests/`. - The interactive prompt appears and its answer is reflected the same way. -- `prisma orm init --skills none` on an existing project behaves the same. +- `prisma init --skills=none` on an existing project behaves the same and, with an existing config, writes `agents: []` into it rather than leaving it alone. - `prisma skills sync` after setting `agents: []` removes the previously written directories, or the new remove command does, with a test in prisma-cli. - The `create-prisma` README and the CLI help text list the new flag. - Note in the PR the exact user-facing sequence for the docs page, which is written separately: the `create-prisma` reference page, both quickstarts, `cli/init`, `cli/orm-init`, `cli/skills`, and `cli/configuration` on the docs site all need the answer. @@ -34,7 +34,7 @@ In `create-prisma`: In `prisma-cli`: - `prisma init --skills=none` writes `skills: { agents: [] }` when no config exists. With an existing config it does nothing to it. -- `prisma orm init --skip-skills` skips the skill install on the existing-project path. +- `prisma orm init` does not install skills (the `--skip-skills` flag was removed in rc.6 along with the install); it only deletes retired skill directories. - `prisma skills sync` writes the directories listed in `skills.agents`; with `agents: []` it writes nothing, but it does not delete copies already on disk. - `skills: { check: false }` only silences the out-of-date notice. @@ -44,4 +44,4 @@ So the real opt-out is `skills: { agents: [] }` in `prisma.config.ts`, and nothi - create-prisma: `src/tasks/setup-prisma.ts`, `src/tasks/prisma-setup/commands.ts`, `src/tasks/install.ts`, `templates/create/_shared/prisma.config.ts.hbs`, `src/index.ts` for flags - prisma-cli: the `init`, `orm init`, and `skills` commands -- Docs pages describing current behaviour: `wip/web/apps/docs/content/docs/cli/init.mdx`, `cli/orm-init.mdx`, `cli/skills.mdx`, `cli/configuration.mdx` +- Docs pages describing current behaviour, in `prisma/web` under `apps/docs/content/docs/`: `cli/init.mdx`, `cli/orm-init.mdx`, `cli/skills.mdx`, `cli/configuration.mdx` diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 6a2ec40b277..f0652d43280 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -1,17 +1,17 @@ # Information architecture: proposal -Proposal first, then why, then the current state it changes. Source: the `meta.json` files and page titles in `wip/web/apps/docs/content/docs/` on 2026-09-10. Labels are what the sidebar shows. +Proposal first, then why, then the current state it changes. Source: the `meta.json` files and page titles under `apps/docs/content/docs/` in `prisma/web` on 2026-09-10. Labels are what the sidebar shows. ## Proposed -Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and two labels under Guides. Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. +Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. ### Getting Started > Prisma ORM ``` Prisma ORM - Introduction to Prisma 8 human content first, agent prompt last - + Prisma 8 release status RC, GA window, 7 support period, what npx prisma installs, how to pin 7 + Introduction to Prisma ORM human content first, agent prompt last + + Release status RC, GA window, 7 support period, what npx prisma installs, how to pin 7 ~ Start a new app was "Quickstart"; same two pages PostgreSQL MongoDB @@ -32,7 +32,7 @@ Four starting states, one group each. "Coming from Prisma 7" is a link node here ``` Introduction - Prisma 8 + Prisma ORM + Coming from Prisma 7 the mapping page: schema and types, CLI, client API, not-yet list ~ Core concepts rewritten as narrative from mental-model.md; glossary kept at the end ``` @@ -40,16 +40,20 @@ Introduction ### Guides ``` -Overview remove "Upgrading: moving from Prisma 7" from the coming-soon list +Overview no "coming soon" line for upgrading; it exists Upgrade Prisma ORM ~ Prisma 7 to 8 (PostgreSQL) was "PostgreSQL" ~ Prisma 6 to 8 (MongoDB) was "MongoDB" v7, v6, v5, v4, v3, v1 + - Deployment, Database, Switch to Prisma ORM, Prisma 7 content; lives under guides/v7 + GitHub Actions, AI SDK, React Router 7, SolidStart ``` +The six Guides labels that leave come back as Prisma ORM 8 pages when C9 (deployment), C11 (CI), and C12 (switching, team workflow) are written. + ### The ORM root page (`/orm`) -Today the page has five sections: "Your schema becomes a contract", "What changed for developers", "Supported databases", "Get started" (three cards), "Go deeper" (five cards), and "Learn more about the design of Prisma 8" (five blog links). Three of the six argue for the design against Prisma 7. There is no query on the page. A Newcomer cannot tell from it what the product does; an Upgrader is told why it is different before being shown what it is. +Today the page has six sections: "Your schema becomes a contract", "What changed for developers", "Supported databases", "Get started" (three cards), "Go deeper" (five cards), and "Learn more about the design of Prisma 8" (five blog links). Three of the six argue for the design against Prisma 7. There is no query on the page. A Newcomer cannot tell from it what the product does; an Upgrader is told why it is different before being shown what it is. Proposed structure, in order: @@ -60,6 +64,8 @@ Proposed structure, in order: 5. Coming from Prisma 7: one line linking to the mapping page. 6. Release status: one line linking to the status page. +The page name follows the naming rule: "Prisma ORM", not "Prisma 8". + Removed from this page: the three-step workflow explanation, "What changed for developers", and the blog list. The first moves into Core concepts; the other two go, or the blog list moves to the bottom of Core concepts. ### Root page (`/`) @@ -70,7 +76,7 @@ The ORM line becomes a short row with the four starting states, linking into the | Node | Jobs | | --- | --- | -| Prisma 8 release status | J4 | +| Release status | J4 | | Add to an app you already have | J1 | | Adopt an existing database (rewritten) | J2 | | Coming from Prisma 7 | J3, J5 (links to the incremental guide), J6 (attribute map) | @@ -82,7 +88,7 @@ J8, J9, and J10 need product decisions or shipped code before a node makes sense ### Not proposed -No change to the top-level section list, to Data Modeling, Contract Authoring, Fundamentals, Migrations, Middleware, Extensions, Reference, or to any Guides subtree except the two labels. The "Prisma 7" group at the bottom of Getting Started stays as the home for people staying on 7. +No change to the top-level section list, to Data Modeling, Contract Authoring, Fundamentals, Migrations, Middleware, Extensions, or Reference. Under Guides, only the label changes above and the removal of the Prisma 7 pages (A7). The "Prisma 7" group at the bottom of Getting Started stays as the home for people staying on 7. ## Why: where each job lands today, and where the structure fails it @@ -96,7 +102,7 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | J6 data types | Data Modeling > Overview | right node; one stale example | | J7 editor setup | none | no node | | J8 advanced Postgres | none | no node; needs product answers | -| J9 types | none | no node; API merged, awaiting a tagged release | +| J9 types | none | no node; API in PRs | | J10 opt out of agent files | CLI > configuration | right node, unreachable from Getting Started | Two observations follow from the table. diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index 8a840266a51..ca47fac5435 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -1,95 +1,78 @@ -# Jobs users come to the docs to do, and how the docs serve them today +# Jobs readers come to the docs to do -Each job has: who, where they land, what "done" looks like, the path through the current site, and a verdict. Paths were traced in the `prisma/web` source at `wip/web/apps/docs/content/docs/` and checked against the live site on 2026-09-10. Verdicts: **green** works, **amber** works with friction, **red** fails or is missing. +Ten jobs. Each names who does it, what "done" looks like, what the docs must provide for it, and where the site's structure fails it. The jobs are the design input for `ia.md` (which node serves each job) and `changes.md` (which page or ORM change supplies what is missing). Verdicts describe the structure, not the state of any one sentence: **green** a page exists for the job and carries it end to end, **amber** the job can be done but the reader has to assemble it from several places or work around a gap, **red** no page is written for the job. -## J1. Add Prisma 8 to an app I already started, with an empty database +## J1. Add Prisma ORM to an app I already started, with an empty database -Who: Newcomer, sometimes Upgrader. The Bun user in Discord is this job. +Who: Newcomer, sometimes Upgrader. The most common Discord complaint is this job. Done: models defined, tables created, one query returns rows, from inside the app they already have. -Path today: +What the docs must provide: one page that starts from "you have a project directory and no tables", runs `orm init`, edit the contract, `contract emit`, `db init`, one query, and shows `db.ts` and where `DATABASE_URL` comes from. -- Search "prisma bun" lands on the Bun guide. It starts with `create-prisma`, so it scaffolds a new app instead of joining theirs. -- `/getting-started` offers "Add to an existing project", which goes to the existing-project PostgreSQL page. That page assumes the database already has tables: step 4 is `contract infer`. There is no branch for "empty database". -- The right three commands (`orm init`, `contract emit`, `db init`) exist only as a snippet on the CLI reference overview, under "Start in an existing project". -- Whichever page they use, the query example is wrong: the existing-project page uses `db.orm.User` (must be `db.orm.public.User` on Postgres) and `.take(2)` (removed in rc.7). -- `orm init` writes `src/prisma/db.ts`, but no getting-started page shows the file, so `import { db } from "./prisma/db"` is unexplained. -- The quickstart says scripts read `DATABASE_URL` from the environment, not `.env`; the existing-project page uses `.env` with `dotenv/config`. The two pages disagree and neither says why. -- The existing-project script calls both `db.connect()` and `db.runtime()`. The difference is explained only deep in the transactions-and-runtime reference. -- Skill files land in the repo with no mention of how to stop that. +Where the structure fails: the getting-started subtree is organised by which tool runs (`create-prisma` for new apps, `orm init` for "existing project"). The reader's situation, an app with no database yet, falls between the two: the scaffold page creates a new app, and the existing-project page assumes tables exist and starts with `contract infer`. The three commands that fit exist only as a snippet on the CLI overview. -Verdict: **red**. No page is written for this job, and the nearest page has two copy-paste errors. +Verdict: **red**. IA node: "Add to an app you already have" (C2). -## J2. Bring an existing database with data under Prisma 8, then make the next schema change +## J2. Bring an existing database with data under Prisma ORM, then make the next schema change Who: Upgrader mostly, some Newcomers with a legacy database. Done: contract matches the database, database is signed, first query works, and `migration plan` for the next change produces one small migration rather than a full recreate. -Path today: the existing-project PostgreSQL page, steps 2 to 9. +What the docs must provide: the adoption sequence end to end, including what to expect from `contract infer` (removed attributes, non-`public` schemas, defaults it cannot express, Temporal-backed timestamp types), what `db sign` checks and what its exit codes mean, and whatever makes the next `migration plan` chain from the signed state. -- Steps 2 to 7 are in the right order: init, connection, infer, review, emit, sign, query. -- Step 4 says "review the inferred contract" but not what to expect. Users hit `@db.*` attributes (removed in 0.17), non-`public` schemas, and a `Decimal` default that fails to emit, with no guidance. -- Step 6 signs the database but never explains what a signature is or what to do if `db sign` exits 4. -- Step 9 says "use `db update` or `migration plan`". It never mentions the `db` ref. `db sign` does not set the ref (only `db init`, `db update`, and `db migrate --advance-ref` do). With no migrations on disk and no ref, `migration plan` silently plans from an empty database and proposes recreating every table. This is the `--from` confusion reported twice in Discord. -- The upgrade guide gets this right (baseline migration, sign, `migration ref set db`, then `--advance-ref db` on each migrate), but J2 users on the existing-project page never see it. +Where the structure fails: the existing-project page stops at "sign, then query". The step that makes the next migration work (today: a baseline migration and `migration ref set db`) is taught only in the incremental upgrade guide, which this reader never sees. That step exists because `db sign` does not record where migrations start from; the design in `brief-db-ref-on-adoption.md` removes it. -Verdict: **red**. The page stops one step short and the missing step produces a destructive-looking plan. +Verdict: **red**. IA node: "Adopt an existing database" (C3); ORM change D1. -## J3. Rewrite Prisma 7 queries in Prisma 8 +## J3. Rewrite Prisma ORM 7 queries in Prisma ORM 8 Who: Upgrader. -Done: for every Prisma 7 call in their code, they know the Prisma 8 call or that it does not exist. +Done: for every Prisma ORM 7 call in their code, they know the Prisma ORM 8 call or that it does not exist. -Path today: +What the docs must provide: one mapping page in four sections (schema and types, CLI commands, client API, not-yet list with a status per item), reachable from every ORM entry point. The not-yet list is the part readers ask for most: `createMany` and `skipDuplicates`, `findUniqueOrThrow`, atomic `increment`/`decrement`, case-insensitive filters, JSON path filters, `$transaction` arrays, the payload types. -- No single mapping page. Sixteen inline "For Prisma 7 users" diff blocks are spread across reading-data, writing-data, transactions-and-runtime, pipeline-builder, data-modeling, and eight places in the ORM reference. -- Pagination is taught as `.take()`/`.skip()` on eight pages (29 sites). Those were renamed to `.limit()`/`.offset()` in rc.7 and the old names removed. -- The bulk count mutations are taught as `createCount`/`updateCount`/`deleteCount` (31 sites on two pages). They were renamed to `createAndCount` and friends in 0.17. -- `createMany` appears on no Prisma 8 page. `createAll` and `createAndCount` are documented but nothing says they replace it. `skipDuplicates` has no equivalent and no page says so. -- `findUniqueOrThrow`, `findFirstOrThrow`, atomic `increment`/`decrement`, and case-insensitive filters have no Prisma 8 equivalent in the SQL ORM client source. No page says so. -- `$transaction([...])` is covered in one inline block. `Prisma.UserGetPayload` and the model types have no page at all; the replacements (`Models`, `Shape<>`) merged to prisma/orm `main` on 2026-09-10 (#30231, #30236) and are not in a tagged release as of rc.9. -- Accessor casing (`prisma.user` became `db.orm.public.User`) is stated once in reading-data and nowhere else. +Where the structure fails: there is no node. The mapping exists as sixteen inline "For Prisma 7 users" blocks across nine pages, so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. -Verdict: **red**. The answers that exist are scattered, two of them are wrong, and the missing features are not admitted. +Verdict: **red**. IA node: "Coming from Prisma 7" (C1, placed by A2); the not-yet list depends on D4. -## J4. Decide whether to move to Prisma 8 now +## J4. Decide whether to move to Prisma ORM 8 now Who: Upgrader, also a Newcomer choosing an ORM. -Done: they know Prisma 8 is a release candidate, when GA is expected, how long 7 is supported, what `npx prisma` now installs, and how to pin 7. +Done: they know Prisma ORM 8 is a release candidate, when GA is expected, how long 7 is supported, what `npx prisma` now installs, and how to pin 7. -Path today: the root page says "Prisma 7 remains fully supported" and shows `npx prisma@7.10.0 init`. Nothing on the site says Prisma 8 is an RC, gives a GA window, states the 12-month support commitment for 7, or explains the npm `latest` tag. Five people asked this in Discord in one week. +What the docs must provide: one short page with those five facts, linked from the root page and from every "Using Prisma 7?" note. -Verdict: **red**, and the cheapest fix on the list. +Where the structure fails: no node. The only signal is a note box saying Prisma 7 remains supported, with links for staying on 7. Nothing says "release candidate", gives a window, or explains that `npm install prisma` now resolves to 8 while `@prisma/client` resolves to 7. -## J5. Migrate a whole Prisma 7 app incrementally +Verdict: **red**. IA node: "Release status" (C4); the npm tag question is D6. + +## J5. Migrate a whole Prisma ORM 7 app incrementally Who: Upgrader with a team and a production database. -Done: both versions run side by side, routes move one at a time, migrations hand over, Prisma 7 is removed. +Done: both versions run side by side, routes move one at a time, migrations hand over, Prisma ORM 7 is removed. + +What the docs must provide: the five-phase guide that exists (`guides/upgrade-prisma-orm/postgresql`), reachable from the ORM entry points and from the mapping page, with a label that says what it is. -Path today: `guides/upgrade-prisma-orm/postgresql` covers all five phases and is the best page on the site for the Upgrader. Getting there is the problem: the root page, `/getting-started`, and the ORM overview never link to it. The guides index lists "Upgrading: moving from Prisma 7" under "Coming as they land". In the sidebar it sits under "Upgrade Prisma ORM" as "PostgreSQL", with no "7 to 8" in the label. It is also pinned to rc.6 and rc.4 and says so in a callout. +Where the structure fails: the page is filed under Guides and nothing under Getting Started or ORM links to it. It is the best page on the site for this reader and the hardest to find. -Verdict: content **amber**, discoverability **red**. +Verdict: content **green**, discoverability **amber**. IA: link it from "Coming from Prisma 7" and the ORM front door (A2). -## J6. Model my data, especially types Prisma 7 handled with `@db.*` +## J6. Model my data, especially types Prisma ORM 7 handled with `@db.*` Who: Newcomer and Upgrader. -Done: they can write `Text`, `VarChar(100)`, `Uuid`, `Decimal`, enums, relations, and know which Prisma 7 attributes are gone. +Done: they can write `Text`, `VarChar(100)`, `Uuid`, `Decimal`, enums, relations, and know which Prisma ORM 7 attributes are gone. -Path today: +What the docs must provide: the scalar table, the native types in type position, the `@default` generators, index and check options, and a Prisma ORM 7 attribute map (`@db.Text`, `@db.VarChar(n)`, `@db.Decimal(p,s)` to their type-position forms), plus a money and `Decimal` section. -- The data-modeling overview has a scalar table (`String` is `Text`) and a money-in-cents recommendation. Good. -- The PSL syntax page shows `Uuid = String @db.Uuid` in its opening example and again at line 177. That syntax was removed in 0.17. Copying it fails emission. -- No page maps Prisma 7 attributes (`@db.Text`, `@db.VarChar(n)`, `@db.Decimal(p,s)`) to Prisma 8 types. -- `Decimal` defaults and money beyond "use cents" are not covered. One user asked and got no answer. -- Implicit many-to-many is honestly marked unsupported. Good. +Where the structure fails: the right nodes exist (Data Modeling, Contract Authoring) but cover a fraction of the authoring surface, and the attribute map has no home. -Verdict: **amber**, with one stale example that must go. +Verdict: **amber**. Pages: C1 (schema section), C14, C8. ## J7. Set up my editor @@ -97,9 +80,11 @@ Who: Newcomer and Upgrader. Done: syntax highlighting and formatting work for `contract.prisma`. -Path today: no page. The facts (extension is on open-vsx not the Microsoft marketplace, no bundled language server, needs the CLI installed locally, file needs `// use prisma-next` on line one) were given by Serhii in a Discord thread. The `// use prisma-next` line appears in examples but is never explained. +What the docs must provide: where the VS Code extension lives (open-vsx, not the Microsoft marketplace), that there is no bundled language server and the locally installed CLI is used, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. -Verdict: **red**, missing. +Where the structure fails: no node. The facts were given once, in a Discord thread. + +Verdict: **red**. IA node: "Editor setup" (C5). ## J8. Use advanced Postgres features @@ -107,9 +92,11 @@ Who: Newcomer and Upgrader on real projects. RLS, policies, expression and funct Done: they know whether the contract can express it, and how, or that they must manage it outside Prisma. -Path today: nothing under `orm/`. RLS is covered only through the Supabase extension in the shipped skill. One user's agent invented a contract-builder API because there was nothing to read. +What the docs must provide: one page: `@@rls` and the `policy_*` blocks, `@@index(expression:, where:, unique:, type:)`, `@@check` and `@noCheck`, `installExtension` / `createExtension` in migrations, `@@control` for tables Prisma should not manage. + +Where the structure fails: no node. All of it ships and none of it is documented; readers' agents invent APIs because there is nothing to read. -Verdict: **red**, missing. Needs a product answer before a docs answer. +Verdict: **red**. Page: C7. ## J9. Name a model or result type for reuse @@ -117,31 +104,35 @@ Who: Newcomer and Upgrader. Done: `type User = ...` and the type of a query result, without reading `contract.d.ts`. -Path today: no page. `ResultType` for SQL builder plans is the only documented helper. The `Models` namespace and `Shape<>` (prisma/orm#30231, #30236) merged to `main` on 2026-09-10 and are not in a tagged release as of rc.9; the where-type exports (#30158) shipped in rc.9. +What the docs must provide: a types page with model, result, where, and input types, each beside its Prisma ORM 7 name. The `Models` namespace and `Shape<>` are in `prisma/orm` `main` and ship with the next tagged release; `ResultType` for SQL builder plans exists today. -Verdict: **red** until the next tagged release carries `Models` and `Shape<>`, then a page is needed on release day. +Where the structure fails: no node. + +Verdict: **red**. Page: C6, on the release that carries the types. ## J10. Stop Prisma from writing agent files into my repo -Who: Newcomer and Upgrader, five people in one week. +Who: Newcomer and Upgrader. Done: one config line, and they know it. -Path today: `skills: { agents: [] }` is documented on the CLI configuration page and `init --skills=none` on the init page. Neither is linked from create-prisma, the quickstarts, or the existing-project page. The advice circulating in Discord (`skills sync --disable`, an env var) is wrong. `create-prisma` has no flag. +What the docs must provide: the one line (`skills: { agents: [] }` in `prisma.config.ts`) at the point where the scaffold introduces the files, linking to the configuration reference; and, once it exists, the scaffold-time opt-out. + +Where the structure fails: the reader meets the files on the scaffold pages and the answer lives on the CLI configuration page, which those pages must link. The tool itself has no prompt or flag, and `skills sync` with an empty list does not remove what it wrote. -Verdict: **amber** for docs, **red** for the tool. +Verdict: docs **amber**, tool **red**. Tool change D3. ## Summary -| Job | Verdict | Cheapest fix | +| Job | Verdict | What serves it | | --- | --- | --- | -| J1 existing app, empty DB | red | new page | -| J2 existing DB, next migration | red | add baseline and ref steps | -| J3 Prisma 7 query mapping | red | one mapping page plus rename fixes | -| J4 should I move now | red | one short page, linked from root | -| J5 incremental upgrade | amber / red | links and a nav label | -| J6 data types | amber | remove `@db.` example, add attribute map | -| J7 editor | red | new page | -| J8 advanced Postgres | red | product decision first | -| J9 types | red | page on the next tagged release | -| J10 agent files | amber | one line on three pages | +| J1 existing app, empty DB | red | new node: Add to an app you already have (C2) | +| J2 existing DB, next migration | red | Adopt an existing database (C3) after D1 | +| J3 Prisma ORM 7 query mapping | red | Coming from Prisma 7 (C1, A2); D4 for the not-yet list | +| J4 should I move now | red | Release status (C4); D6 | +| J5 incremental upgrade | green / amber | links from the ORM entry points (A2) | +| J6 data types | amber | C1 schema section, C14, C8 | +| J7 editor | red | Editor setup (C5) | +| J8 advanced Postgres | red | Advanced Postgres (C7) | +| J9 types | red | Types (C6) on the next tagged release | +| J10 agent files | amber / red | the line on scaffold pages; D3 | diff --git a/docs/orm-docs-audit/mental-model.md b/docs/orm-docs-audit/mental-model.md index ad09b022ffd..0522ff5b83a 100644 --- a/docs/orm-docs-audit/mental-model.md +++ b/docs/orm-docs-audit/mental-model.md @@ -1,10 +1,10 @@ -# The Prisma 8 mental model, from first principles +# The Prisma ORM 8 mental model, from first principles -This is the source we write docs pages from. It explains why Prisma 8 has the pieces it has, in the order a person meets them. Everything here was checked against the monorepo glossary, the architecture overview, and the rc.9 release notes. +This is the source we write docs pages from. It explains why Prisma ORM 8 has the pieces it has, in the order a person meets them. Everything here was checked against the `prisma/orm` glossary, the rc.9 release notes, and the source under `packages/`. ## The one idea -Your application and your database each have an opinion about what the data looks like. In Prisma 7 the schema file was the only written-down version, and the generated client trusted that the database matched it. Prisma 8 makes the agreement explicit and checkable from both sides. Everything else follows from that. +Your application and your database each have an opinion about what the data looks like. In Prisma ORM 7 the schema file was the only written-down version, and the generated client trusted that the database matched it. Prisma ORM 8 makes the agreement explicit and checkable from both sides. Everything else follows from that. ## Two things, not one: the contract and the schema @@ -12,13 +12,13 @@ The **contract** is what you write. It is your description of the models, fields The **schema** is what the database actually has right now: the tables, columns, and indexes. -Prisma 7 called your file the schema. Prisma 8 reserves that word for the database side, because the whole point is that the two can disagree. When a command or error says "schema", it means the database. +Prisma ORM 7 called your file the schema. Prisma ORM 8 reserves that word for the database side, because the whole point is that the two can disagree. When a command or error says "schema", it means the database. -Every Prisma 8 operation is a relationship between these two: queries are typed against the contract, migrations move the schema toward the contract, and verification checks that the schema still satisfies the contract. +Every Prisma ORM 8 operation is a relationship between these two: queries are typed against the contract, migrations move the schema toward the contract, and verification checks that the schema still satisfies the contract. ## Emit: the build step that replaces `prisma generate` -Prisma 7 generated a client package from your schema. Prisma 8 emits two plain files from your contract: +Prisma ORM 7 generated a client package from your schema. Prisma ORM 8 emits two plain files from your contract: - `contract.json`, a canonical description of the models, storage layout, and the database features it needs. - `contract.d.ts`, the TypeScript types derived from it. @@ -34,12 +34,12 @@ Because emit is deterministic, hashing `contract.json` gives a short identifier The database stores a small marker record, the **signature**, naming the contract hash it currently satisfies. Three commands write it: - `db init` creates the tables for the contract in an empty database and signs it. -- `db sign` checks that an existing database already matches the emitted contract and, if so, signs it. This is how you adopt a database you did not create with Prisma 8. +- `db sign` checks that an existing database already matches the emitted contract and, if so, signs it. This is how you adopt a database you did not create with Prisma ORM 8. - `db migrate` applies a migration and updates the signature to the migration's target hash. `db verify` reads it and reports **drift**: any disagreement between contract and schema. -Why this exists: a deploy against an unmigrated database, or a migration run against the wrong database, is caught before any query runs, because the runtime and the migration runner both check the signature first. In Prisma 7 the same mistake produced wrong results or a failed query later. +Why this exists: a deploy against an unmigrated database, or a migration run against the wrong database, is caught before any query runs, because the runtime and the migration runner both check the signature first. In Prisma ORM 7 the same mistake produced wrong results or a failed query later. ## Queries: every query becomes a plan @@ -51,19 +51,19 @@ The three query surfaces on Postgres, from highest to lowest: 1. The **ORM client**: `db.orm.public.User.where({ ... }).all()`. Model-based, coordinates several statements for `.include()`, hands back one typed result. Start here. 2. The **SQL builder**: `db.sql.public.user.select(...).where(...).build()`. Composable joins, grouping, and projections. One plan is exactly one statement. -3. **Raw fragments** spliced into builder queries when the builder cannot express it. +3. **Raw SQL**: a whole statement, `db.raw.sql`\`...\`.returnsRow(spec)`, when the builder cannot express it, or a `fns.raw` fragment spliced into a builder query. Whole statements declare their row shape and are decoded; fragments are not. -Why `db.orm.public.User` and not `prisma.user`: Postgres tables live in schemas, and Prisma 8 addresses models through the schema namespace so a contract can span more than one. `public` is the default schema. Aliasing by assignment (`const User = db.orm.public.User`) is fine. On MongoDB the key is the collection's storage name (`db.orm.users`) and there is no SQL builder. +Why `db.orm.public.User` and not `prisma.user`: Postgres tables live in schemas, and Prisma ORM 8 addresses models through the schema namespace so a contract can span more than one. `public` is the default schema. Aliasing by assignment (`const User = db.orm.public.User`) is fine. On MongoDB the key is the collection's storage name (`db.orm.users`) and there is no SQL builder. ## Migrations: edges between contract hashes A migration is a step from one contract hash to another. Together they form a graph, not a timestamped list. Every migration records the hash it starts from and the hash it produces. -`migration plan` diffs two contracts and writes a migration package. The target is always your emitted contract. The origin is, in order: `--from` if you pass it, otherwise the `db` ref, otherwise an empty database. +`migration plan` diffs two contracts and writes a migration package. The target is always your emitted contract. The origin is `--from` if you pass it, otherwise the `db` ref. With neither, the command refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`) when migrations already exist on disk, and plans from an empty database only when the migrations directory is empty. -The `db` **ref** is a named pointer to a contract hash, kept in the repo, meaning "the state I consider the database to be at". `db init`, `db update`, and `db migrate --advance-ref db` move it. `db sign` does not. +The `db` **ref** is a named pointer to a contract hash, kept in the repo, meaning "the state I consider the database to be at". `db init` and `db update` move it when the connection comes from `prisma.config.ts`; with an explicit `--db` they move it only if `--advance-ref db` is also passed. `db migrate --advance-ref db` moves it. `db sign` does not today; the design in `brief-db-ref-on-adoption.md` makes it do so, so that adopting a database is one step. -Why this matters more than it seems: a project with no `db` ref plans every migration from empty, which proposes recreating every table. This is the trap for anyone who adopts an existing database with `db sign` and then runs `migration plan`. The fix is a baseline migration plus `migration ref set db ` once, then `--advance-ref db` on each migrate. The incremental upgrade guide does this; the existing-project page does not. +Why this matters more than it seems: a project with no `db` ref and no migrations on disk plans its first migration from empty, which proposes recreating every table. This is the trap for anyone who adopts an existing database with `db sign` and then runs `migration plan`. The fix today is a baseline migration plus `migration ref set db ` once, then `--advance-ref db` on each migrate. When the graph is empty and the `db` ref names a stored snapshot, `migration plan` writes the baseline for you. Why a graph and not a list: two branches can each add a migration, and the graph resolves the merge by hashes instead of by timestamp order. Partial failures are safe to retry because each edge has a verifiable precondition. @@ -83,9 +83,9 @@ Why a graph and not a list: two branches can each add a migration, and the graph | `migration ref set` | a hash | the ref | after a baseline, or to repoint | | `contract infer` | live schema | a draft contract source | first contract for an existing database | -## What moved from Prisma 7, and why +## What moved from Prisma ORM 7, and why -| Prisma 7 | Prisma 8 | Why | +| Prisma ORM 7 | Prisma ORM 8 | Why | | --- | --- | --- | | `schema.prisma` | `contract.prisma` | the file describes an agreement, not the database | | `prisma generate` | `prisma contract emit` | data artifacts instead of a generated client | @@ -100,8 +100,8 @@ Why a graph and not a list: two branches can each add a migration, and the graph | `createMany` | `createAll` (rows back) or `createAndCount` (count back) | the return shape is in the name | | `$transaction([...])` | `db.transaction(async tx => ...)` | callback form only | | `@db.Text`, `@db.VarChar(n)` | `Text`, `VarChar(n)` in type position | native types are types, not attributes | -| `Prisma.UserGetPayload<...>` | `Shape<...>` (merged to prisma/orm `main` 2026-09-10, #30231) | not in a tagged release as of rc.9 | -| `skipDuplicates`, `increment`, `findUniqueOrThrow`, `mode: "insensitive"` | no equivalent yet | say so plainly | +| `Prisma.UserGetPayload<...>` | `Shape<...>`, with the `Models` namespace | in `prisma/orm` `main`; ships with the next tagged release | +| `skipDuplicates`, `increment`, `findUniqueOrThrow`, `mode: "insensitive"`, JSON path filters | no equivalent yet (`.all().firstOrThrow()` covers the throw case) | say so plainly | ## The eight words @@ -109,4 +109,4 @@ Why a graph and not a list: two branches can each add a migration, and the graph ## What the model costs, honestly -Two extra concepts before the first query: the emit step and the signature. Prisma 7 had neither. The docs must pay that cost back on the same page by showing what it buys: a deploy that refuses to run against the wrong database, a migration plan you can read before it runs, and a query you can inspect before it executes. If a page introduces the concept without the payoff, cut the concept from that page. +Two extra concepts before the first query: the emit step and the signature. Prisma ORM 7 had neither. The docs must pay that cost back on the same page by showing what it buys: a deploy that refuses to run against the wrong database, a migration plan you can read before it runs, and a query you can inspect before it executes. If a page introduces the concept without the payoff, cut the concept from that page. diff --git a/docs/orm-docs-audit/naming.md b/docs/orm-docs-audit/naming.md index 7e9752c14f7..c7de7922797 100644 --- a/docs/orm-docs-audit/naming.md +++ b/docs/orm-docs-audit/naming.md @@ -14,17 +14,15 @@ ## How to do it -Not a global replace. Each of the 109 files needs a read, because "Prisma 8" in a contrast sentence becomes "Prisma ORM 8" and elsewhere becomes "Prisma ORM". Do it per page as each page is touched by the restructure and the content fixes, and sweep the remainder at the end. The 96 titles are the visible part and should go first, since they are the sidebar and the browser tab. +One pass over the whole site, as its own PR. Not a global replace: each of the 109 files needs a read, because "Prisma 8" in a contrast sentence becomes "Prisma ORM 8" and elsewhere becomes "Prisma ORM". The 96 titles are the visible part and go first; they are the sidebar and the browser tab. ## What stays as is -- Identifiers: `prisma-next.md`, `// use prisma-next`, `@prisma/orm-postgres`, `/studio/prisma-next`, package names, error codes. 40 occurrences of `prisma-next` as an identifier; none as prose ("Prisma Next" appears zero times on the site). +- Identifiers: `prisma-next.md`, `// use prisma-next`, `@prisma/orm-postgres`, `/studio/prisma-next`, package names, error codes. 40 occurrences of `prisma-next` as an identifier; none as prose. - The "Prisma 7" group at the bottom of Getting Started and the v7 doc trees. - Release notes and changelogs, which name versions by nature. -## Scope on the site today - -Outside the v6 and v7 trees: +## Scope on the site (2026-09-10, outside the v6 and v7 trees) | Term | Occurrences | Files | | --- | --- | --- | @@ -34,4 +32,4 @@ Outside the v6 and v7 trees: By area: `orm/` 225, `guides/` 196, `(index)/` 135, `cli/` 81. 96 page titles or meta titles contain "Prisma 8". No sidebar label does; the labels come from titles. -The most common sentence shapes ("Add Prisma 8 to an ...", "Prisma 8 is the ...", "Prisma 8 app with ...", "Prisma 8 skills for ...") all take "Prisma ORM" as a drop-in replacement. The ones that do not are the contrast sentences, which should keep the number and add "ORM". +The common sentence shapes ("Add Prisma 8 to an ...", "Prisma 8 is the ...", "Prisma 8 app with ...", "Prisma 8 skills for ...") all take "Prisma ORM" as a drop-in replacement. The contrast sentences keep the number and add "ORM". diff --git a/docs/orm-docs-audit/personas.md b/docs/orm-docs-audit/personas.md index 7a95be649fe..a7244b5b6c2 100644 --- a/docs/orm-docs-audit/personas.md +++ b/docs/orm-docs-audit/personas.md @@ -1,6 +1,6 @@ -# Who reads the Prisma 8 docs +# Who reads the Prisma ORM docs -Four readers arrive at the docs. The first two produce almost all the complaints. The docs outside `orm/` are built for the third. The fourth never complains. +Four readers arrive. The first two produce almost all the complaints (Discord, GitHub, and support, August and September 2026). The docs outside `orm/` are built for the third. The fourth never complains. ## The Newcomer @@ -12,9 +12,9 @@ How they judge the docs: can I copy the example and does it run. ## The Upgrader -Has used Prisma 5, 6, or 7. Has a running app, a database with data in it, and a migration history. Arrived because `npx prisma` installed Prisma 8 without them choosing it, or because they saw the announcement. Most of the Discord complaints are from this reader. +Has used Prisma ORM 5, 6, or 7. Has a running app, a database with data in it, and a migration history. Arrived because `npx prisma` installed Prisma ORM 8 without them choosing it, or because they saw the announcement. Most of the complaints are from this reader. -What they need: first, a straight answer on whether to move now and how to stay on 7 if not. Second, the Prisma 8 name for every Prisma 7 thing they know, or a plain statement that it does not exist yet. Third, the exact sequence to bring an existing database under Prisma 8 control and make the next migration work. +What they need: first, a straight answer on whether to move now and how to stay on 7 if not. Second, the Prisma ORM 8 name for every Prisma ORM 7 thing they know, or a plain statement that it does not exist yet. Third, the exact sequence to bring an existing database under Prisma ORM 8 control and make the next migration work. How they judge the docs: against the mental model they already have. Every page that explains contracts before answering "where did `findMany` go" costs trust. @@ -22,12 +22,12 @@ How they judge the docs: against the mental model they already have. Every page Wants to ship a product on the Prisma platform: Composer, Compute, Postgres, Storage. May be technical, may lean on a coding agent. The ORM is one component. Happy to have tools scaffold the app and happy to hand a prompt to an agent. -The docs root, the framework guides, the agent prompts, and the full-stack tutorial serve this reader well. They are not the problem, but their content occupies the entry points the Newcomer and the Upgrader land on. +The docs root, the framework guides, the agent prompts, and the full-stack tutorial serve this reader well. The problem is that their content occupies the entry points the Newcomer and the Upgrader land on. ## The Agent -Reads the shipped skill, `llms.txt`, and the `.md` version of any page. Never complains. The skill is out of scope for this audit except where the human pages feed into it. +Reads the shipped `prisma-8` skill, `llms.txt`, and the `.md` rendition of any page. Never complains. The skill is out of scope for the docs work except where the human pages feed into it; its own defects are in `brief-skill-staleness.md`. -## What this means for the audit +## What this means for the docs -The ORM entry points must serve the Newcomer and the Upgrader before the Builder. Today the order is reversed: the root page is the Builder's, the ORM landing opens with an Agent prompt, and the Upgrader gets a two-line note saying Prisma 7 still exists. +The ORM entry points must serve the Newcomer and the Upgrader before the Builder. Today the order is reversed: the root page is the Builder's, the ORM landing opens with an agent prompt, and the Upgrader gets a two-line note saying Prisma ORM 7 still exists. diff --git a/docs/orm-docs-audit/slice-corrections.md b/docs/orm-docs-audit/slice-corrections.md index e7d5d50e5ac..a439e4b7bf3 100644 --- a/docs/orm-docs-audit/slice-corrections.md +++ b/docs/orm-docs-audit/slice-corrections.md @@ -1,83 +1,22 @@ -# Slice 1: corrections to published pages +# The corrections slice: what shipped, and the decisions behind it -Scope: fix what is wrong on pages that exist today, without moving, adding, or removing pages. Everything in `changes.md` section B, plus A4 (two label edits). Sections A, C, D are out of scope and come after the IA discussion. Each fix cites the rc.9 source line it was verified against; the audit files under `audit/` hold the line lists. +Before any restructure, every factual error on the published Prisma ORM 8 pages was fixed in place. Three PRs to `prisma/web`, each reviewed independently against the rc.9 source, each commit citing the line it was verified against: -## Proposed batches - -Three PRs to `prisma/web`, in this order. Each is reviewable on its own and does not depend on the others. - -### PR 1: mechanical renames (about 350 lines, 20 pages) - -Search-and-replace with a known correct form. Low judgement, high volume. Reviewer checks the diff is uniform. - -| Item | What changes | Pages | +| PR | What | Size | |---|---|---| -| B11 | `execute(plan)` to `query(plan)` for row reads; Mongo `db.execute(plan)` to `(await db.runtime()).query(plan)`; `ps.execute` to `ps.query`; drop `executePrepared`. Writes with no returned rows stay on `execute`. | 14 | -| B1 | `.take()`/`.skip()` to `.limit()`/`.offset()`; keep Mongo pipeline `skip` stages | 8 | -| B2 | `createCount` and siblings to `createAndCount` and siblings, including headings | 2 | -| B12 | drop the `sha256:` prefix on every hash | 9 | -| B13 | `extensionPacks` to `extensions` | 2 | -| B14 | migration directory listing and `migration.ts` imports to the `migrations/snapshots//` layout | 3 | -| B4 | remove `@db.Uuid`; re-point the named-types example at a real alias | 1 | -| B21 | stale flags, codes, command names, and printed output (`--skip-skills`, `CLI.INIT_SKILL_INSTALL_FAILED`, bare `ref set`, `prisma-cli` hints, `PN-RUN-3000`, `from: null`, the "Applied 1 migration(s)" line, `cd prisma`, top-level `migrate`, hyphenated slugs, `--db` shown as required) | 10 | -| B23 | `db.runtime().close()` to `db.close()` | 4 | -| B26 | enum ordering note updated for rc.9 | 1 | - -### PR 2: page rewrites (about 12 pages) - -Sentences change, not just names. Each page gets one commit so the reviewer can read it as prose. - -| Item | Page | What changes | -|---|---|---| -| B15 + B3 + B10 | both `add-to-existing-project` pages | default path is `src/prisma/`; `orm init` writes no skills; `.env` is a prompt; show `db.ts` once; one `DATABASE_URL` story; Temporal polyfill note; `--write-env` / `--schema-path`; `db.orm.public.User` | -| B16 | six `orm/migrations/*`, `cli/migration-plan`, `cli/db-init`, `cli/db-update`, `cli/migration-ref`, `cli/index`, upgrade guide | `migration plan` refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN`; `db init` / `db update` advance the ref only without `--db`; `NO_TARGET` belongs to `migration new`; the automatic baseline and `--from @empty` | -| B17 | five `orm/middleware/*` | two lifecycles, no `intercept`; rewrite the logger example on `afterQuery`; fix lint keys, budgets latency, cache hooks; drop "permissive mode" on Postgres | -| B18 | `orm/reference/raw-queries`, `advanced-queries` | whole-query raw SQL exists; `db.raw.sql`; drop the "unversioned ids" callout | -| B19 | `relations-and-joins`, `data-modeling/relational-databases` | 1:1 back side, N:M include and nested writes, referential actions, `.variant()` all work; stop sending readers to the SQL builder | -| B20 | `sql-query-builder`, `advanced-queries`, `orm-client` | aggregates return numbers; the `BigInt` / `Decimal` variants; `min` / `max` typing | -| B22 | `editing-a-migration` | add `rawCodecInferer` so the data-transform example typechecks | -| B24 | `writing-data` | upsert needs `conflictOn` | -| B27 | `transactions-and-runtime`, `pipeline-builder` | structured error codes, not plain `Error`; fix the `prepare` then `connect()` sample | -| B31 | `data-modeling/index` | scalar table: `Json` vs `Jsonb`, add `Decimal`, `Bytes` | -| B35 | `using-extensions` | the recipe does not fit Supabase; catalog links lead to `@internal` install commands | - -### PR 3: start pages and guides, small facts (about 20 pages) - -One-line or one-paragraph facts on the getting-started pages and guides. - -| Item | What changes | -|---|---| -| B5 | SQLite ships; `orm/index` and `sql-query-builder` | -| B6 | upgrade guides: version pins, `Database signed` output, the CREATE TABLE symptom that no longer appears | -| B8 | one Node floor, stated once (needs decision 2) | -| B9 | explain `// use prisma-next` where the contract is introduced | -| B28 | `create-prisma` page: `minimal` template, no `.env` for Postgres, `--force`, deploy defaults, Deno flag, script list | -| B29 | MongoDB pages: replica set is not required | -| B30 | Bun guide build and dev scripts; NestJS `@Inject` note; TypeScript authoring paths; Deno page staleness | -| B32 + A4 | guides index and the upgrade guide's sidebar label | -| B33 | `ai/tools/skills` page: one skill, no `--skip-skills`, `orm init` does not install | -| B34 | full-stack tutorial: `TimestamptzString`, no `postinstall` | -| B7 | the agent-files line on four pages (needs decision 1) | -| B25 | streaming claim on `reading-data` (needs decision 3) | - -## What this slice does not do - -- It does not touch the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7). They are wrong for a Prisma ORM 8 reader, but fixing them means moving or rewriting whole pages, which is the IA discussion. If you want something now, the smallest honest change is a one-line banner at the top of each saying it is written for Prisma ORM 7; say so and I will add it to PR 3. -- It does not add missing content (C). Where a fix would leave a hole (for example B18 removes "raw SQL does not exist" but the page still needs a section on what does), the fix states the fact in one paragraph and stops. -- It does not touch the skill (D14) or the monorepo docs (D17). -- It does not rename "Prisma 8" to "Prisma ORM" (naming.md). That is a site-wide pass and cleaner as its own PR after this slice; mixing it in would bury the corrections in a 700-line diff. +| #8236 | Names, flags, paths, codes, and printed output that no longer exist at rc.9, replaced by the form that does | 12 commits, 39 files | +| #8237 | Pages whose explanations were wrong (the `db` ref, middleware, raw SQL, relations, aggregates, the existing-project pages) | 12 commits, 30 files | +| #8238 | Facts on the getting-started pages and guides (Node floor, MongoDB replica set, create-prisma flags and scripts, the skills page, the tutorial, streaming, `npm create prisma@latest`) | 18 commits, 40 files | -## Decisions before PR 3 +Out of scope by design: the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7, now with Ankur), new content (C), the agent skill (D14), the monorepo docs (D17), and the "Prisma 8" to "Prisma ORM" rename. -Will answered on 2026-09-10: 1 and 4 as proposed; 2 and 3 checked as below. +## Four decisions taken along the way -1. **B7, agent files.** Write the `skills: { agents: [] }` workaround now; replace it when the opt-out brief lands. -2. **B8, Node floor.** Checked by running rc.9 end to end (`contract emit`, `db init`, ORM create and read, `for await`, SQL builder) in a scratch project under Node 22.12.0, 22.18.0, and 22.22.3: all pass. Node release schedule (`nodejs/Release/schedule.json`): 22 "Jod" is Maintenance LTS until 2027-04-30; 23 reached end of life 2025-06-01; 24 "Krypton" is Active LTS, Maintenance from 2026-10-20, end of life 2028-04-30; 26 becomes LTS 2026-10-28. So Node 22 is supported and in LTS for another seven months, and 23 is dead. The scaffold's `engines` range `^22.18.0 || >=24.11.0` is what `create-prisma` enforces; the excluded 24.0 to 24.10 band is odd and worth asking the create-prisma owner about, but the site should not contradict what the scaffold refuses. Site wording: "Node.js 22.18 or newer; Node.js 24 recommended." The monorepo's `Supported Versions.md` says 24 and is wrong about what runs. -3. **B25, streaming.** What the page says: `for await` over `.all()` "streams" rows with a "steady, flat memory footprint" for millions of rows, you "start working on the first record before the last one has arrived", and on early exit "unprocessed records are never buffered". What the implementation does: `postgres()` creates its driver with `cursor: { disabled: true }` (`packages/3-extensions/postgres/src/runtime/postgres.ts:245`), and the driver's own comment calls that "buffered execution": the whole result set is fetched into memory before iteration starts; only decoding through the codecs happens per row as your loop pulls. Cursor batches (`batchSize`, default 100) exist in the driver and are only reachable through the serverless facade's `cursor` option. Measured on a 400,006-row table under Node 22.18: `for await` that breaks after the first row took 186 ms and grew the heap by 64 MB (every row was fetched), versus 824 ms for `await ...all()` (fetch plus decode of every row). So `for await` saves the decode work and the decoded array, not the fetch. The page's three claims about memory and arrival order are false on `postgres()`; the "read once" rule and the per-row hand-off are true. Fix for this slice: rewrite the section to say what actually happens (rows are fetched in full, decoded one at a time as you iterate, use `limit()` or the serverless facade with cursors for genuinely large results). Whether `postgres()` should expose `cursor` is D8 and is out of this slice. -4. **B16, the `--db` quirk.** Document the current behaviour as-is, with `--advance-ref db` shown in every example that passes `--db`. +1. **Agent files.** The scaffold pages carry one line saying Prisma writes skill files for coding agents and that `skills: { agents: [] }` in `prisma.config.ts` stops it. That is the only correct answer until create-prisma grows an opt-out flag (D3), at which point the line is replaced. +2. **Node floor.** The site says "Node.js 22.18 or newer (on the 24 line, 24.11 or newer); 24 recommended". Checked by running rc.9 end to end (`contract emit`, `db init`, ORM create and read, `for await`, SQL builder) under Node 22.12.0, 22.18.0, and 22.22.3: all pass. Node 22 is Maintenance LTS until 2027-04-30; 23 reached end of life 2025-06-01; 24 is Active LTS until 2028-04-30. The `prisma` CLI and create-prisma both declare `>=22.18.0`; only the `package.json` create-prisma writes into a project narrows to `^22.18.0 || >=24.11.0`, which is why the 24 sub-range is stated. The monorepo's `docs/Supported Versions.md` says 24 and is wrong about what runs. +3. **Streaming.** The reading-data page promised that `for await` streams rows with a flat memory footprint. It does not on `postgres()`: the facade creates its driver with `cursor: { disabled: true }`, so the whole result is fetched before iteration and only decoding is per row. Measured on a 400,006-row table under Node 22.18: `for await` that breaks after the first row took 186 ms and grew the heap by 64 MB (every row fetched), against 824 ms for `await ...all()` (fetch plus decode). The page now says what happens and points large-result readers at `limit()` or the serverless facade, which reads through a cursor in batches of 100. Whether `postgres()` should expose cursors is D8. +4. **The `--db` quirk.** `db init` and `db update` advance the `db` ref only when the URL comes from config; with `--db` they do not unless `--advance-ref db` is also passed. Documented as-is, with the flag shown on every dev-loop example that passes `--db`; deploy and CI examples are left without it on purpose. Whether the rule should change is D9. -## How the work runs +## Two audit claims the source overruled -- One implementer per PR, working from the audit files and `changes.md`, in this worktree on a branch off `main`. Every changed code sample cites the source line in the commit message. Where a sample can be typechecked against `wip/prisma-src/examples/prisma-8-demo`, it is. -- I review each PR against the source before it goes to you. You do the prose pass. -- No push and no PR until you say so; the branches sit here until then. +Left as the pages had them: `migration plan` can raise `MIGRATION.NO_TARGET` after a rollback cycle (the planner does resolve a leaf), and `min` / `max` over a `DateTime` column type-checks at rc.9 (there is no `pg/timestamptz@1` codec; `DateTime` is the temporal codec, which `min`/`max` accept). From 328bcf1be6f366a0a251576c27149b880e75b0e4 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 16:02:17 +0200 Subject: [PATCH 06/68] docs: state the real reason for the naming rule, brand separation Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/naming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/naming.md b/docs/orm-docs-audit/naming.md index c7de7922797..2b67920647a 100644 --- a/docs/orm-docs-audit/naming.md +++ b/docs/orm-docs-audit/naming.md @@ -10,7 +10,7 @@ - The release status page says "Prisma ORM 8 is a release candidate; Prisma ORM 7 is supported until ...". - The Prisma 7 docs trees (`orm/v7`, `(index)/v7`, `guides/v7`, `cli/v7`) keep their version label in the nav, because that is what they are. -"Prisma 8" as a bare product name reads as a different product from "Prisma ORM", which is the Upgrader's fear stated back to them. It also collides with the platform, where "Prisma" alone means the whole stack. +Why: the Prisma brand identity is being separated from the ORM. Prisma is the company and the platform; the ORM is one product on it. Calling the ORM "Prisma 8" ties the whole brand to one product's release cycle, and it leaves no name for the platform, where "Prisma" alone already means the stack. So the ORM is never "Prisma" plus a version; it is "Prisma ORM", and that name is what gets a version number. ## How to do it From 476adee8587715caf4109f8594a44753f05cd2d0 Mon Sep 17 00:00:00 2001 From: "reviewer (Program)" Date: Fri, 11 Sep 2026 14:24:26 +0000 Subject: [PATCH 07/68] docs: reconcile the ORM docs audit with #8242 and make the naming counts reproducible changes.md, ia.md, README.md: A7 landed as #8242 on 2026-09-11 in a different shape (fifteen guides rewritten for Prisma ORM 8 in place with Prisma 7 copies under guides/v7, Cloudflare D1 moved to v7 only), so the status, the A7 item, and C9/C11/C12 no longer describe main; record what landed and mark those items for re-scoping. naming.md: the scope table mixed corpora, occurrences counted with the v6/v7 trees included (690/198/2816) while the file counts and the heading excluded them. Restate both from one corpus with the method and the commit: 679/135/487, by area 221/196/131/77, 96 titles = 7 title + 89 metaTitle. changes.md carries the same number. journeys.md, changes.md: the Prisma 7 mapping is fourteen inline diff blocks across six orm/ pages (twelve led by 'For Prisma 7 users'), not sixteen across nine. ia.md: the Prisma 7 note box is on all four getting-started pages, /prisma-orm/create-prisma, /prisma-orm (titled 'Prisma 7'), /orm and /cli (titled 'Prisma 7 users'), not only the PostgreSQL pages. README.md: only audit/ still uses the wip/ citation prefixes. --- docs/orm-docs-audit/README.md | 4 ++-- docs/orm-docs-audit/changes.md | 20 +++++++++++--------- docs/orm-docs-audit/ia.md | 6 ++++-- docs/orm-docs-audit/journeys.md | 2 +- docs/orm-docs-audit/naming.md | 10 ++++++---- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index b41a63e6f84..1081ba2e4dd 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -2,7 +2,7 @@ Working documents behind the Prisma ORM 8 docs corrections (prisma/web #8236, #8237, #8238) and the proposed restructure. Written September 2026 against `@prisma/orm-postgres@8.0.0-rc.9`; source paths refer to the prisma/orm monorepo at that tag (`packages/`, `docs/releases/`, `examples/`, `skills/prisma-8/`) and to prisma/create-prisma. Site paths are relative to `apps/docs/content/docs/`. -Citations in `audit/`, `changes.md`, and the briefs use the worktree layout the audit was run in: `wip/prisma-src/` is prisma/orm (formerly prisma/prisma; the old name still redirects) at `v8.0.0-rc.9`, `wip/create-prisma-src/` is prisma/create-prisma, `wip/web/` is this repository, and `wip/docs-audit/` is this directory. Strip the prefix to get the path in the named repository. +Citations in `audit/` use the worktree layout the audit was run in: `wip/prisma-src/` is prisma/orm (formerly prisma/prisma; the old name still redirects) at `v8.0.0-rc.9`, `wip/create-prisma-src/` is prisma/create-prisma, and `wip/docs-audit/` is this directory. Strip the prefix to get the path in the named repository. Read in this order: @@ -14,6 +14,6 @@ Read in this order: 6. `naming.md` — the "Prisma ORM" naming rule. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. 8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). -9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. +9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. The audit is a snapshot of the site on 2026-09-10; the guides pages it flags as Prisma 7 content were rewritten for Prisma ORM 8 in #8242 on 2026-09-11. Prose is a draft throughout; the structure and the cited facts are what has been verified. diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 347e6b4cf76..448ba7770f6 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -10,17 +10,19 @@ Status as of 2026-09-11. **Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -**In progress.** A7 (moving the sixteen Prisma 7 guides out of the Latest tree) is with Ankur. D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. +**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. + +**In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. **Not started.** The naming pass, the restructure (A1 to A3, A5, A6, A8), every new page (C), and the rest of D. ## Recommended order for the open work -1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (691 occurrences in 109 files). Mechanical, one PR, done after A7 lands so the two do not conflict. +1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (679 occurrences in 109 files). Mechanical, one PR. A7 has landed (#8242), so nothing blocks it. 2. **C4, release status page.** Half a page; unblocks J4 (the reader who got upgraded by accident). Needs the GA window and the Prisma ORM 7 support policy from Will. 3. **C2, add Prisma ORM to an app you already started.** The J1 page and the complaint that started this work. One page, written from `mental-model.md`. 4. **C1, coming from Prisma 7.** The mapping table and the "not yet" list. Unblocks J3. -5. **C9, deployment.** The largest hole: zero Prisma ORM 8 coverage for any host, and the six pages A7 removes had been standing in for it. +5. **C9, deployment.** Was the largest hole; #8242 shipped Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces. What remains is what those pages do not cover (see C9). 6. **The restructure** (A1, A2, A3, A5, A6) as one piece of work, after the pages above exist to be organised. 7. **Everything else in C** as its dependency in D clears. @@ -42,11 +44,11 @@ Status as of 2026-09-11. The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. - **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. -- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. +- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. - **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. -- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** In progress (Ankur). `guides/frameworks/react-router-7`, `solid-start`, all of `guides/deployment/*`, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` are Prisma 7 end to end and have no copy under `guides/v7/`. Move with the same slugs and redirects; the Latest sidebar loses those labels until C9, C11, and C12 replace them. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. - **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. @@ -84,9 +86,9 @@ Grouped by where the page lives. Each says what the page is for, what it must co ### Guides -- **C9. Deploying Prisma ORM 8.** Zero coverage today for any host. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. -- **C11. CI.** `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. -- **C12. Switching from another ORM; team schema workflow.** Replaces the six Prisma 7 guides A7 removes. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. +- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. +- **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. +- **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. - **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. ### Reference completeness @@ -142,7 +144,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ## Naming -The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR after A7. +The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR (A7 has landed, so nothing blocks it). ## Open questions diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index f0652d43280..2844c9898f2 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -49,7 +49,7 @@ Upgrade Prisma ORM GitHub Actions, AI SDK, React Router 7, SolidStart ``` -The six Guides labels that leave come back as Prisma ORM 8 pages when C9 (deployment), C11 (CI), and C12 (switching, team workflow) are written. +The Prisma ORM 8 replacements for those labels sit at the same slugs; C9 (deployment), C11 (CI), and C12 (switching, team workflow) in `changes.md` say what they must cover. ### The ORM root page (`/orm`) @@ -162,6 +162,8 @@ Reference ### Guides (ORM-relevant parts) +Snapshot of 2026-09-10. On 2026-09-11, #8242 rewrote the Deployment, Database, Switch to Prisma ORM, GitHub Actions, AI SDK, React Router 7, and SolidStart pages for Prisma ORM 8 at the same slugs, moved their Prisma 7 versions (and Cloudflare D1) under `guides/v7`, and gave the overview an Upgrading section. + ``` Overview /guides says "Upgrading: moving from Prisma 7" is coming v7 @@ -180,5 +182,5 @@ Making guides ### Where Prisma 7 readers are pointed today - Root page: one line, "Here for the ORM? Jump straight to Prisma 7 or Prisma 8". -- A "Using Prisma 7?" note box on `/orm`, `/prisma-orm`, both PostgreSQL getting-started pages, and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. +- A note box ("Using Prisma 7?", "Prisma 7", or "Prisma 7 users") on `/orm`, `/prisma-orm`, `/prisma-orm/create-prisma`, all four getting-started pages (PostgreSQL and MongoDB), and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. - Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides, where the label is "PostgreSQL". diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index ca47fac5435..c4682668e7f 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -34,7 +34,7 @@ Done: for every Prisma ORM 7 call in their code, they know the Prisma ORM 8 call What the docs must provide: one mapping page in four sections (schema and types, CLI commands, client API, not-yet list with a status per item), reachable from every ORM entry point. The not-yet list is the part readers ask for most: `createMany` and `skipDuplicates`, `findUniqueOrThrow`, atomic `increment`/`decrement`, case-insensitive filters, JSON path filters, `$transaction` arrays, the payload types. -Where the structure fails: there is no node. The mapping exists as sixteen inline "For Prisma 7 users" blocks across nine pages, so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. +Where the structure fails: there is no node. The mapping exists as fourteen inline diff blocks across six `orm/` pages (twelve of them introduced with "For Prisma 7 users"), so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. Verdict: **red**. IA node: "Coming from Prisma 7" (C1, placed by A2); the not-yet list depends on D4. diff --git a/docs/orm-docs-audit/naming.md b/docs/orm-docs-audit/naming.md index 2b67920647a..c85cd0beada 100644 --- a/docs/orm-docs-audit/naming.md +++ b/docs/orm-docs-audit/naming.md @@ -24,12 +24,14 @@ One pass over the whole site, as its own PR. Not a global replace: each of the 1 ## Scope on the site (2026-09-10, outside the v6 and v7 trees) +Counted with `git grep -o` over the `.mdx` and `meta.json` files under `apps/docs/content/docs/`, excluding every `v6/` and `v7/` directory, on `main` as of 2026-09-10 (`684dcbf6`). + | Term | Occurrences | Files | | --- | --- | --- | -| "Prisma 8" | 691 | 109 | -| "Prisma 7" | 198 | 33 | -| "Prisma ORM" | 2816 | 95 | +| "Prisma 8" | 679 | 109 | +| "Prisma 7" | 135 | 33 | +| "Prisma ORM" | 487 | 95 | -By area: `orm/` 225, `guides/` 196, `(index)/` 135, `cli/` 81. 96 page titles or meta titles contain "Prisma 8". No sidebar label does; the labels come from titles. +By area: `orm/` 221, `guides/` 196, `(index)/` 131, `cli/` 77. 96 frontmatter titles contain "Prisma 8": 7 `title:` values, which are also the sidebar labels of those pages, and 89 `metaTitle:` values. No `meta.json` group title does. The common sentence shapes ("Add Prisma 8 to an ...", "Prisma 8 is the ...", "Prisma 8 app with ...", "Prisma 8 skills for ...") all take "Prisma ORM" as a drop-in replacement. The contrast sentences keep the number and add "ORM". From dc1ca337312516a531291aad8d106afc656448d5 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 16:28:50 +0200 Subject: [PATCH 08/68] docs: correct the Temporal-by-Node.js-version fact Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 448ba7770f6..ef0458832df 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -8,21 +8,19 @@ Status as of 2026-09-11. ## Where things stand -**Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. +**Shipped.** Every correction to an existing page (section B, 35 items) went out in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist), #8237 (pages whose explanations were wrong), and #8238 (facts on the getting-started pages and guides). Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. - -**In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. +**In progress.** A7 (moving the sixteen Prisma 7 guides out of the Latest tree) is with Ankur. D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. **Not started.** The naming pass, the restructure (A1 to A3, A5, A6, A8), every new page (C), and the rest of D. ## Recommended order for the open work -1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (679 occurrences in 109 files). Mechanical, one PR. A7 has landed (#8242), so nothing blocks it. +1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (691 occurrences in 109 files). Mechanical, one PR, done after A7 lands so the two do not conflict. 2. **C4, release status page.** Half a page; unblocks J4 (the reader who got upgraded by accident). Needs the GA window and the Prisma ORM 7 support policy from Will. 3. **C2, add Prisma ORM to an app you already started.** The J1 page and the complaint that started this work. One page, written from `mental-model.md`. 4. **C1, coming from Prisma 7.** The mapping table and the "not yet" list. Unblocks J3. -5. **C9, deployment.** Was the largest hole; #8242 shipped Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces. What remains is what those pages do not cover (see C9). +5. **C9, deployment.** The largest hole: zero Prisma ORM 8 coverage for any host, and the six pages A7 removes had been standing in for it. 6. **The restructure** (A1, A2, A3, A5, A6) as one piece of work, after the pages above exist to be organised. 7. **Everything else in C** as its dependency in D clears. @@ -44,17 +42,17 @@ Status as of 2026-09-11. The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. - **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. -- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. +- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. - **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. -- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** In progress (Ankur). `guides/frameworks/react-router-7`, `solid-start`, all of `guides/deployment/*`, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` are Prisma 7 end to end and have no copy under `guides/v7/`. Move with the same slugs and redirects; the Latest sidebar loses those labels until C9, C11, and C12 replace them. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. -- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. +- **A4** (sidebar labels and the guides index) shipped in #8238. -## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) +## B. Corrections to existing pages (shipped) -Thirty-five items, all verified against rc.9 source, in #8236 and #8237 (merged) and #8238 (open as of 2026-09-11). What they fixed, in order of how many readers they hit: +Thirty-five items, all verified against rc.9 source and shipped in #8236, #8237, #8238. What they fixed, in order of how many readers they hit: | Theme | What was wrong | Items | |---|---|---| @@ -86,16 +84,16 @@ Grouped by where the page lives. Each says what the page is for, what it must co ### Guides -- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. -- **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. -- **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. +- **C9. Deploying Prisma ORM 8.** Zero coverage today for any host. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. +- **C11. CI.** `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. +- **C12. Switching from another ORM; team schema workflow.** Replaces the six Prisma 7 guides A7 removes. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. - **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. ### Reference completeness - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. -- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on prisma/orm `main` (#30231 and #30236 merged 2026-09-10); publish when the first tagged release after rc.9 ships them. #30158 (reusable where filter types) is already in rc.9. Also what `contract.d.ts` already exports today. Unblocks J9. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch; publish when prisma/orm#30231, #30236, #30158 ship. Also what `contract.d.ts` already exports today. Unblocks J9. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. - **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. @@ -124,7 +122,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work is merged: the where filter types (#30158) are in rc.9; `Models` and `Shape<>` (#30231, #30236) are on `main` awaiting a tagged release. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work (`Models`, `Shape<>`) is in PRs. - **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. ### create-prisma @@ -144,7 +142,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ## Naming -The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR (A7 has landed, so nothing blocks it). +The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR after A7. ## Open questions From 5ed9a9a26c4d45f6a6ddf2099bfa120f8b18aca8 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 16:29:39 +0200 Subject: [PATCH 09/68] docs: restore the change list's A7 and C6 updates; keep the Temporal correction The previous commit replaced the branch copy of changes.md with an older working copy and lost the notes that #8242 landed A7 by rewriting the guides rather than moving them. Restored, with only the Temporal wording changed on top. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/brief-skill-staleness.md | 2 +- docs/orm-docs-audit/changes.md | 32 +++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/orm-docs-audit/brief-skill-staleness.md b/docs/orm-docs-audit/brief-skill-staleness.md index a93628008e8..52641b656e0 100644 --- a/docs/orm-docs-audit/brief-skill-staleness.md +++ b/docs/orm-docs-audit/brief-skill-staleness.md @@ -30,7 +30,7 @@ Line numbers are from the rc.9 tag. "Source" is the file that proves the correct 18. **Streaming.** `queries.md:146` says there is no streaming surface and recommends holding a `pg.Client`. The read terminals return an `AsyncIterableResult` you can `for await`; but on the long-lived `postgres()` facade the driver runs with cursors disabled, so the full result is fetched before iteration and only decoding is per row. The serverless facade (`@prisma/orm-postgres/serverless`) reads through a cursor in batches of 100. Say exactly that. Source: `packages/3-extensions/sql-orm-client/src/collection.ts:998-1022`, `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`, `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:39-53`, `postgres-serverless.ts:28-42`. 19. **`migration show` with no argument.** `migrations.md:189` runs it bare; the `` positional is required. Source: `cli/src/orm/migration/show.ts:3-6`. 20. **`--from` grammar.** `migration-model.md:67` lists `@contract | @db | @empty` for `migration plan --from`. The command is offline: only `@empty` resolves there (`@db` needs the live marker, `@contract` needs a contract hash the plan resolver does not pass). Source: `cli/src/control-api/operations/plan-resolution.ts:224-229`, `packages/1-framework/3-tooling/migration/src/refs/contract-ref.ts:39-56`. -21. **Node.js floor for Temporal.** Wherever the skill says Temporal-backed types need a polyfill "on Node", say: Node.js 26.8.2 and later ship `globalThis.Temporal`; 26.8.1 and earlier, including every 22 and 24, do not, so `temporal-polyfill/full/global` must be imported before the first read or the column authored as a `*String` type. Checked empirically on 22.22.3, 24.16.0, 26.8.1, 26.8.2. +21. **Node.js floor for Temporal.** Wherever the skill says Temporal-backed types need a polyfill "on Node", say: Node.js 26 and later ship `globalThis.Temporal` (Homebrew's Node.js 26 build omits it); 25 and earlier, including every 22 and 24, do not, so `temporal-polyfill/full/global` must be imported before the first read or the column authored as a `*String` type. Checked empirically on 22.22.3, 24.16.0, 25.8.0, 26.0.0, 26.8.1 (official and Homebrew), 26.8.2. Things the skill gets right that the site had wrong (keep them): `db.raw.sql` as the raw tag and whole-query raw SQL with `.returnsRow()` / `.affectedCount()` (`queries.md:143`, `queries-postgres.md:392, 415`); `extensions` not `extensionPacks` in `defineContract` (`contract.md:51, 386`); the five lint severity keys (`runtime.md`); `../../snapshots//contract.json` imports (`migrations.md:225, 253`); `db.close()` for teardown (`runtime.md:66-78`); the `prebuild` emit for Next.js (`build.md:466`). diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index ef0458832df..448ba7770f6 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -8,19 +8,21 @@ Status as of 2026-09-11. ## Where things stand -**Shipped.** Every correction to an existing page (section B, 35 items) went out in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist), #8237 (pages whose explanations were wrong), and #8238 (facts on the getting-started pages and guides). Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. +**Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -**In progress.** A7 (moving the sixteen Prisma 7 guides out of the Latest tree) is with Ankur. D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. +**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. + +**In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. **Not started.** The naming pass, the restructure (A1 to A3, A5, A6, A8), every new page (C), and the rest of D. ## Recommended order for the open work -1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (691 occurrences in 109 files). Mechanical, one PR, done after A7 lands so the two do not conflict. +1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (679 occurrences in 109 files). Mechanical, one PR. A7 has landed (#8242), so nothing blocks it. 2. **C4, release status page.** Half a page; unblocks J4 (the reader who got upgraded by accident). Needs the GA window and the Prisma ORM 7 support policy from Will. 3. **C2, add Prisma ORM to an app you already started.** The J1 page and the complaint that started this work. One page, written from `mental-model.md`. 4. **C1, coming from Prisma 7.** The mapping table and the "not yet" list. Unblocks J3. -5. **C9, deployment.** The largest hole: zero Prisma ORM 8 coverage for any host, and the six pages A7 removes had been standing in for it. +5. **C9, deployment.** Was the largest hole; #8242 shipped Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces. What remains is what those pages do not cover (see C9). 6. **The restructure** (A1, A2, A3, A5, A6) as one piece of work, after the pages above exist to be organised. 7. **Everything else in C** as its dependency in D clears. @@ -42,17 +44,17 @@ Status as of 2026-09-11. The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. - **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. -- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The sixteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. +- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. - **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. -- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** In progress (Ankur). `guides/frameworks/react-router-7`, `solid-start`, all of `guides/deployment/*`, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` are Prisma 7 end to end and have no copy under `guides/v7/`. Move with the same slugs and redirects; the Latest sidebar loses those labels until C9, C11, and C12 replace them. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. -- **A4** (sidebar labels and the guides index) shipped in #8238. +- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. -## B. Corrections to existing pages (shipped) +## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) -Thirty-five items, all verified against rc.9 source and shipped in #8236, #8237, #8238. What they fixed, in order of how many readers they hit: +Thirty-five items, all verified against rc.9 source, in #8236 and #8237 (merged) and #8238 (open as of 2026-09-11). What they fixed, in order of how many readers they hit: | Theme | What was wrong | Items | |---|---|---| @@ -84,16 +86,16 @@ Grouped by where the page lives. Each says what the page is for, what it must co ### Guides -- **C9. Deploying Prisma ORM 8.** Zero coverage today for any host. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. -- **C11. CI.** `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. -- **C12. Switching from another ORM; team schema workflow.** Replaces the six Prisma 7 guides A7 removes. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. +- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. +- **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. +- **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. - **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. ### Reference completeness - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. -- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on the PR branch; publish when prisma/orm#30231, #30236, #30158 ship. Also what `contract.d.ts` already exports today. Unblocks J9. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on prisma/orm `main` (#30231 and #30236 merged 2026-09-10); publish when the first tagged release after rc.9 ships them. #30158 (reusable where filter types) is already in rc.9. Also what `contract.d.ts` already exports today. Unblocks J9. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. - **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. @@ -122,7 +124,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work (`Models`, `Shape<>`) is in PRs. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work is merged: the where filter types (#30158) are in rc.9; `Models` and `Shape<>` (#30231, #30236) are on `main` awaiting a tagged release. - **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. ### create-prisma @@ -142,7 +144,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ## Naming -The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR after A7. +The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR (A7 has landed, so nothing blocks it). ## Open questions From b46e8988e14dc370579d8e19c45dd7768774a878 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 16:29:55 +0200 Subject: [PATCH 10/68] docs: Temporal ships in Node.js 26; the polyfill is for 25 and earlier Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 448ba7770f6..d43d02a0d38 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -119,7 +119,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. - **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. - **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. -- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js before 26.8.2 every read throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. - **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. ### Product decisions From f4266e719ce69067a7ffae7383cdc2234a3e182e Mon Sep 17 00:00:00 2001 From: "reviewer (Program)" Date: Fri, 11 Sep 2026 14:53:33 +0000 Subject: [PATCH 11/68] docs: reconcile the audit's counts with the tree and the same PR's Temporal fact ia.md still said the Prisma 7 mapping was spread over nine pages after journeys.md was corrected to fourteen diff blocks on six orm/ pages; naming.md's prisma-next count (40) only reproduces with the v6/v7 trees included, the stated corpus gives 39. changes.md counted thirteen pages kept with the 'This guide uses Prisma 7' note, from the #8242 description; the tree on main has fourteen, and the two Accelerate integration guides moved to guides/v7 alongside Cloudflare D1. slice-corrections.md carried pre-merge PR sizes and said A7 was still with Ankur. audit/start-guides.md said no stable Node ships Temporal, which brief-skill-staleness.md and D10 in the same PR now contradict; Node.js 26 does. D10's parenthetical was moved so it no longer splits 'throws' from the error code. --- docs/orm-docs-audit/audit/start-guides.md | 2 +- docs/orm-docs-audit/changes.md | 6 +++--- docs/orm-docs-audit/ia.md | 2 +- docs/orm-docs-audit/naming.md | 2 +- docs/orm-docs-audit/slice-corrections.md | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/orm-docs-audit/audit/start-guides.md b/docs/orm-docs-audit/audit/start-guides.md index 7c3dfa0291b..9732217a85a 100644 --- a/docs/orm-docs-audit/audit/start-guides.md +++ b/docs/orm-docs-audit/audit/start-guides.md @@ -32,7 +32,7 @@ Monorepo paths below are relative to `wip/prisma-src/` unless they start with `w ## Missing -- Temporal requirement for inferred contracts — `contract infer` maps `timestamp`/`timestamptz` columns to `Timestamp`/`Timestamptz`, which are Temporal-backed; on a runtime without a global `Temporal` (no stable Node ships one) every read of such a column fails with `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported first or the type is changed to `TimestamptzString`. create-prisma installs the polyfill for this reason; `orm init` does not. Neither existing-project page nor the Prisma 7 upgrade guide (whose real-world schemas have `DateTime` columns) mentions it — evidence: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`, `packages/3-targets/3-targets/postgres/src/core/errors.ts:74-86`, `skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.5-to-8.0.0-rc.6/instructions.md:38-47`, `wip/create-prisma-src/src/constants/dependencies.ts:21-23`, `wip/create-prisma-src/templates/create/_shared/src/prisma/db.ts.hbs:15` — belongs on `add-to-existing-project/postgresql.mdx` step 4 and `guides/upgrade-prisma-orm/postgresql.mdx` section 2.4 +- Temporal requirement for inferred contracts — `contract infer` maps `timestamp`/`timestamptz` columns to `Timestamp`/`Timestamptz`, which are Temporal-backed; on a runtime without a global `Temporal` (Node.js 25 and earlier ship none; 26 does) every read of such a column fails with `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported first or the type is changed to `TimestamptzString`. create-prisma installs the polyfill for this reason; `orm init` does not. Neither existing-project page nor the Prisma 7 upgrade guide (whose real-world schemas have `DateTime` columns) mentions it — evidence: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`, `packages/3-targets/3-targets/postgres/src/core/errors.ts:74-86`, `skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.5-to-8.0.0-rc.6/instructions.md:38-47`, `wip/create-prisma-src/src/constants/dependencies.ts:21-23`, `wip/create-prisma-src/templates/create/_shared/src/prisma/db.ts.hbs:15` — belongs on `add-to-existing-project/postgresql.mdx` step 4 and `guides/upgrade-prisma-orm/postgresql.mdx` section 2.4 - `create-prisma --json` — non-interactive machine-readable mode for agents; not in the flag table — evidence: `wip/create-prisma-src/src/index.ts:73-76`, `wip/create-prisma-src/README.md:66-81` — belongs in the `create-prisma.mdx` flag table and the agent prompts on `getting-started.mdx` / `index.mdx` - The full set of generated package scripts — the scaffold adds `db:update`, `db:verify`, `migration:status`, `migration:show`, `skills:sync`, `composer:dev`, `composer:deploy`, and `deploy` alongside the four the site mentions — evidence: `wip/create-prisma-src/src/tasks/install.ts:47-70` — belongs in `create-prisma.mdx` "Start the app" - `orm init` flags — `--schema-path`, `--write-env`, `--probe-db`, `--strict-probe`, `--skip-install`, `--keep-previous-facade`, plus `--confirm ` for re-running init in an already scaffolded directory — evidence: `packages/1-framework/3-tooling/cli/src/orm/init.ts:87-112`, `packages/1-framework/3-tooling/cli/src/orm/init-inputs.ts:218-227` — `--write-env` and `--schema-path` belong on both add-to-existing-project pages, which currently rely on the defaults they describe wrongly diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index d43d02a0d38..ef1fe3f7177 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -10,7 +10,7 @@ Status as of 2026-09-11. **Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. +**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect (the Neon and Supabase Accelerate guides moved with it); fourteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. **In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. @@ -48,7 +48,7 @@ The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These a - **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. -- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Fourteen further pages stay in Latest with a "This guide uses Prisma 7" note (the #8242 description counts thirteen; the tree has fourteen); #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. - **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. @@ -119,7 +119,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. - **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. - **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. -- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it). `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. - **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. ### Product decisions diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 2844c9898f2..884d5096388 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -96,7 +96,7 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | --- | --- | --- | | J1 existing app, empty database | Add to Existing Project > PostgreSQL | page assumes tables exist; no node for this state | | J2 existing database with data | Add to Existing Project > PostgreSQL | right node, page stops before the ref step | -| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; content spread over nine pages | +| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; fourteen diff blocks spread over six pages | | J4 should I move now | root, `/prisma-orm` | no node; note box only says 7 is supported | | J5 incremental upgrade | Guides > Upgrade Prisma ORM > PostgreSQL | not linked from any ORM node; label hides it | | J6 data types | Data Modeling > Overview | right node; one stale example | diff --git a/docs/orm-docs-audit/naming.md b/docs/orm-docs-audit/naming.md index c85cd0beada..c288bf19c88 100644 --- a/docs/orm-docs-audit/naming.md +++ b/docs/orm-docs-audit/naming.md @@ -18,7 +18,7 @@ One pass over the whole site, as its own PR. Not a global replace: each of the 1 ## What stays as is -- Identifiers: `prisma-next.md`, `// use prisma-next`, `@prisma/orm-postgres`, `/studio/prisma-next`, package names, error codes. 40 occurrences of `prisma-next` as an identifier; none as prose. +- Identifiers: `prisma-next.md`, `// use prisma-next`, `@prisma/orm-postgres`, `/studio/prisma-next`, package names, error codes. 39 occurrences of `prisma-next` as an identifier; none as prose. - The "Prisma 7" group at the bottom of Getting Started and the v7 doc trees. - Release notes and changelogs, which name versions by nature. diff --git a/docs/orm-docs-audit/slice-corrections.md b/docs/orm-docs-audit/slice-corrections.md index a439e4b7bf3..b283c636cbf 100644 --- a/docs/orm-docs-audit/slice-corrections.md +++ b/docs/orm-docs-audit/slice-corrections.md @@ -4,11 +4,11 @@ Before any restructure, every factual error on the published Prisma ORM 8 pages | PR | What | Size | |---|---|---| -| #8236 | Names, flags, paths, codes, and printed output that no longer exist at rc.9, replaced by the form that does | 12 commits, 39 files | -| #8237 | Pages whose explanations were wrong (the `db` ref, middleware, raw SQL, relations, aggregates, the existing-project pages) | 12 commits, 30 files | -| #8238 | Facts on the getting-started pages and guides (Node floor, MongoDB replica set, create-prisma flags and scripts, the skills page, the tutorial, streaming, `npm create prisma@latest`) | 18 commits, 40 files | +| #8236 | Names, flags, paths, codes, and printed output that no longer exist at rc.9, replaced by the form that does | 40 files, merged 2026-09-10 | +| #8237 | Pages whose explanations were wrong (the `db` ref, middleware, raw SQL, relations, aggregates, the existing-project pages) | 31 files, merged 2026-09-11 | +| #8238 | Facts on the getting-started pages and guides (Node floor, MongoDB replica set, create-prisma flags and scripts, the skills page, the tutorial, streaming, `npm create prisma@latest`) | 32 files, open as of 2026-09-11 | -Out of scope by design: the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7, now with Ankur), new content (C), the agent skill (D14), the monorepo docs (D17), and the "Prisma 8" to "Prisma ORM" rename. +Out of scope by design: the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7, since landed as #8242), new content (C), the agent skill (D14), the monorepo docs (D17), and the "Prisma 8" to "Prisma ORM" rename. ## Four decisions taken along the way From 5dce14b6ad0a80da6709020e3effaef30892cd16 Mon Sep 17 00:00:00 2001 From: "reviewer (Program)" Date: Fri, 11 Sep 2026 15:09:03 +0000 Subject: [PATCH 12/68] docs: mark the audit's overruled streaming claim and fix the upgrade-guide label and A4 facts - audit/extras.md: Missing item 9 and the skill-vs-site bullet concluded streaming on postgres() is cursor-backed; orm-client.md, slice-corrections decision 3 (measured) and D8 say the facade disables the cursor. Note the overruling in place instead of leaving the two audit files contradicting. - ia.md: the PostgreSQL upgrade guide's sidebar label on main is its title, "Migrate from Prisma 7 to Prisma 8", not "PostgreSQL"; only the MongoDB twin is labelled by database name. Corrected the proposal, the why table, the current-state tree and the pointer list; added the '-' legend entry. - changes.md A4: the label changes are in #8238; the guides index part (Upgrading section replacing the coming-as-they-land list) landed in #8242. - audit/gaps.md: create-prisma dependencies.ts citation is lines 8-10 at 0.11.7, matching D11 and start-guides.md. --- docs/orm-docs-audit/audit/extras.md | 6 +++--- docs/orm-docs-audit/audit/gaps.md | 2 +- docs/orm-docs-audit/changes.md | 2 +- docs/orm-docs-audit/ia.md | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/orm-docs-audit/audit/extras.md b/docs/orm-docs-audit/audit/extras.md index 1aeeb54ed26..9acb7d23035 100644 --- a/docs/orm-docs-audit/audit/extras.md +++ b/docs/orm-docs-audit/audit/extras.md @@ -32,7 +32,7 @@ Ranked by how likely a user is to need it, most likely first. Items marked (know 6. `Decimal` (known) — PSL `Decimal` maps to Postgres `numeric` with optional `precision` (1..1000) and `scale` params; runtime value is a decimal string (`CANONICAL_NUMERIC_TEXT`); `@default` accepts numeric text; aggregates: `sum` over `numeric` returns a decimal `string | null`, `avgDecimal(field)` gives an exact decimal string, `sumBigInt` / `countBigInt` for integers, and `count()` / `sum` over integers throw `RUNTIME.DECODE_FAILED` past 2^53-1 — evidence: `packages/3-targets/3-targets/postgres/src/core/codecs.ts:121-175,547`; `codec-type-map.ts:73`; `default-normalizer.ts:18,221`; `psl-infer/infer-enum-blocks.ts:19`; `skills/prisma-8/references/queries-postgres.md:233-255,386,407` — `orm/data-modeling/index.mdx:152-160` omits `Decimal` from the scalar table and `:182` says to store money as integer minor units; nothing documents `avgDecimal` / `sumBigInt` / the overflow error — belongs on `orm/data-modeling/index.mdx` and `orm/fundamentals/advanced-queries.mdx` (aggregates). 7. SQLite target (known) — `@prisma/orm-sqlite` ships at rc.9 with `sqlite(...)` runtime, `[Symbol.asyncDispose]`, and its own capability limits (no `checkConstraint`, no `scalarList`, no `enums`, no `lateral`, no `avgDecimal`); the skill routes to it throughout — evidence: `packages/9-public/@prisma/orm-sqlite/package.json`; `packages/3-extensions/sqlite/src/runtime/sqlite.ts:85,354`; `skills/prisma-8/references/runtime.md:333`, `queries-postgres.md:255`, `contract.md` (`@@check` on SQLite) — site mentions are only `orm/reference/error-reference.mdx:598`, `cli/skills.mdx:38` and capability examples in `orm/contract-authoring/capabilities.mdx:46-70`; there is no getting-started, quickstart, or runtime section for SQLite — belongs in `(index)/prisma-orm/quickstart/`, `orm/reference/transactions-and-runtime.mdx`, `orm/index.mdx`. 8. Enabling a Postgres extension that has no pack (`pg_trgm`, `citext`, …) (known) — the migration authoring API has a structured `createExtension('')` op (renders `CREATE EXTENSION IF NOT EXISTS`), so a user can add it to a hand-written or edited `migration.ts`; there is no contract-level "requires extension" declaration, and no `pg_trgm` pack ships even though `docs/reference/capabilities.md:97-103` reserves a `pg_trgm` capability namespace — evidence: `packages/3-targets/3-targets/postgres/src/core/migrations/op-factory-call.ts:1443-1465` (`CreateExtensionCall`, `renderTypeScript` → `createExtension("...")`); `migrations/operations/dependencies.ts:7-22`; `packages/3-extensions/` has no `pg_trgm` — the site only mentions `CREATE EXTENSION` for packs that ship their own migration (`orm/extensions/using-extensions.mdx:76`) — belongs on `orm/migrations/editing-a-migration.mdx`. -9. Streaming is cursor-backed on Postgres — the site documents `for await` over `.all()` (`orm/fundamentals/reading-data.mdx:280-313`) but never says the Postgres driver reads through a server-side cursor in batches (`pg-cursor`, `cursorBatchSize`) nor that the serverless client takes `cursor` options; the skill wrongly says "No `.stream()` cursor today" — evidence: `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:24,374-384`, `named-cursor.ts`; `packages/3-extensions/postgres/src/runtime/postgres-serverless.ts:31` (`PostgresServerlessCursorOptions`); `packages/2-sql/5-runtime/src/sql-runtime.ts:387-399` — belongs on `orm/fundamentals/reading-data.mdx` and `orm/reference/transactions-and-runtime.mdx`. +9. Streaming is cursor-backed on Postgres — the site documents `for await` over `.all()` (`orm/fundamentals/reading-data.mdx:280-313`) but never says the Postgres driver reads through a server-side cursor in batches (`pg-cursor`, `cursorBatchSize`) nor that the serverless client takes `cursor` options; the skill wrongly says "No `.stream()` cursor today" — evidence: `packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:24,374-384`, `named-cursor.ts`; `packages/3-extensions/postgres/src/runtime/postgres-serverless.ts:31` (`PostgresServerlessCursorOptions`); `packages/2-sql/5-runtime/src/sql-runtime.ts:387-399` — belongs on `orm/fundamentals/reading-data.mdx` and `orm/reference/transactions-and-runtime.mdx`. Overruled: the driver has the cursor, but the `postgres()` facade constructs it with `cursor: { disabled: true }`, so on the long-lived client the whole result is fetched before iteration; only the serverless facade reads through a cursor. See `orm-client.md` (Misleading, first bullet), `slice-corrections.md` decision 3 (measured), and D8 in `changes.md`. 10. `create-prisma` flags used by the tutorial — the tutorial uses `create ... --template hono --provider postgres --yes`, and `--authoring`, `--package-manager`, `--deploy`, `--workspace`, `--force`, `--json`, `--verbose` also exist; the tutorial says "Answer the prompts for contract authoring style and package manager" without naming the flags that skip them — evidence: `wip/create-prisma-src/src/index.ts:39-86` — belongs on `(index)/full-stack-tutorial.mdx:45` (one line) and `(index)/prisma-orm/create-prisma.mdx`. ## Unverified @@ -45,7 +45,7 @@ Ranked by how likely a user is to need it, most likely first. Items marked (know ## Skill vs site -- `skills/prisma-8/references/queries.md:146` says "Streaming large result sets. No `.stream()` cursor today" and recommends holding a `pg.Client` to stream; the site (`orm/fundamentals/reading-data.mdx:280-313`) says `for await` over `.all()` streams without buffering. The source matches the site: `collection.ts:998-1022` exposes the async-iterable read terminal and the Postgres driver iterates via `pg-cursor` (`packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:374-384`). The skill is stale. +- `skills/prisma-8/references/queries.md:146` says "Streaming large result sets. No `.stream()` cursor today" and recommends holding a `pg.Client` to stream; the site (`orm/fundamentals/reading-data.mdx:280-313`) says `for await` over `.all()` streams without buffering. The source matches the site: `collection.ts:998-1022` exposes the async-iterable read terminal and the Postgres driver iterates via `pg-cursor` (`packages/3-targets/7-drivers/postgres/src/postgres-driver.ts:374-384`). The skill is stale. Overruled on the memory claim: `postgres()` disables the driver cursor (`packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`), so the result is buffered before `for await` starts; the skill is closer to the truth there. See `orm-client.md` and `slice-corrections.md` decision 3; the reading-data page was corrected in #8238. - `skills/prisma-8/references/runtime.md:11,135-158,315,322` tells users to import `createTelemetryMiddleware` from `@internal/middleware-telemetry`; no such package exists in the rc.9 tree (only comments and old plan docs mention it). The site's "Three middleware ship with Prisma 8 today" (`orm/middleware/how-middleware-works.mdx:82`: lints, budgets, cache) matches the source (`packages/2-sql/5-runtime/src/middleware/{lints,budgets}.ts`, `packages/3-extensions/middleware-cache/`). The skill is stale; also `runtime.md` never mentions the cache middleware the site documents. - `skills/prisma-8/references/contract.md:25,29,49` uses `cipherstash.EncryptedString(...)` as a canonical extension example; no cipherstash package exists in the rc.9 tree (`wip/prisma-src/CHANGELOG.md:1040` records `@prisma-next/extension-cipherstash` being dropped in favour of CipherStash's own `@cipherstash/prisma-next`, `README.md:82`). The site does not mention cipherstash, which is correct. - `skills/prisma-8/references/contract.md:179` writes `pgvector.Vector(length: 1536)`; the site (`orm/extensions/using-extensions.mdx`) and `examples/prisma-8-demo/src/prisma/contract.prisma:4` use positional `pgvector.Vector(1536)`. The examples compile against rc.9, so the site matches. @@ -65,7 +65,7 @@ Each item: is it supported at rc.9, where the evidence is, and whether the ORM 8 - SQLite target — ships (Missing item 7). Site: `orm/index.mdx:36` still says planned (known); no runtime or quickstart coverage. - Vite plugin — ships (Missing item 5). Site: none. - `@@control` policies — supported (Missing item 4). Site: none. -- Streaming — supported and documented; the cursor mechanics are not (Missing item 9). +- Streaming — `for await` is supported and documented, but on `postgres()` it does not stream: the facade disables the driver cursor and the result is buffered first (Missing item 9, overruled note; `slice-corrections.md` decision 3). ### Supported and documented diff --git a/docs/orm-docs-audit/audit/gaps.md b/docs/orm-docs-audit/audit/gaps.md index dff1ea2ff6b..f4815723ff0 100644 --- a/docs/orm-docs-audit/audit/gaps.md +++ b/docs/orm-docs-audit/audit/gaps.md @@ -55,7 +55,7 @@ Ten of the twenty-one pages in this area are Prisma ORM 7 content sitting under - `guides/runtimes/deno.mdx:29,65` — `npx create-db@latest --env .env --ttl 24h` — the `create-db` source is not in the worktree; flags not checked. - `guides/runtimes/deno.mdx:17` "Deno 2.0 or later" and `guides/frameworks/elysia.mdx:17` "Bun 1.1 or later" — no engine constraint for Deno or Bun in `create-prisma-src` or `prisma-src`. - `orm/contract-authoring/psl-syntax.mdx:39` and the framework guides' starter contract — the site writes `createdAt DateTime` while the rc.9 starter contract writes `createdAt TimestamptzString @default(now())` (`code-templates.ts:180`); I could not find the PSL scalar-name table in `packages/2-sql/2-authoring/contract-psl/src` by grep (`'DateTime'` and `TimestamptzString` have no hits there), so whether `DateTime` still parses is not confirmed. Another area owns `psl-syntax.mdx`. -- The scaffold pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` (`create-prisma-src/src/constants/dependencies.ts:9-11`, "Must match @prisma/composer-prisma-cloud's exact peerDependency") while this audit is against rc.9; whether the published `create-prisma@latest` has moved could not be checked offline. Any rc.9-only behaviour the framework pages describe would not hold on a fresh scaffold until it does. +- The scaffold pins `@prisma/orm-postgres` and `@prisma/orm-mongo` to `8.0.0-rc.8` (`create-prisma-src/src/constants/dependencies.ts:8-10`, "Must match @prisma/composer-prisma-cloud's exact peerDependency") while this audit is against rc.9; whether the published `create-prisma@latest` has moved could not be checked offline. Any rc.9-only behaviour the framework pages describe would not hold on a fresh scaffold until it does. ## Skill vs site diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index ef1fe3f7177..0df707144fc 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -50,7 +50,7 @@ The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These a - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. - **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Fourteen further pages stay in Latest with a "This guide uses Prisma 7" note (the #8242 description counts thirteen; the tree has fourteen); #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. -- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. +- **A4** (sidebar labels and the guides index). The two upgrade-guide labels ("Prisma 7 to 8 (PostgreSQL)", "Prisma 6 to 8 (MongoDB)") are in #8238, open as of 2026-09-11. The guides index part landed in #8242, which replaced the "Coming as they land" list with an Upgrading section linking both guides. ## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 884d5096388..b90a783a0d2 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -4,7 +4,7 @@ Proposal first, then why, then the current state it changes. Source: the `meta.j ## Proposed -Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. +Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, `-` is content leaving the tree, unmarked is unchanged. ### Getting Started > Prisma ORM @@ -42,7 +42,7 @@ Introduction ``` Overview no "coming soon" line for upgrading; it exists Upgrade Prisma ORM - ~ Prisma 7 to 8 (PostgreSQL) was "PostgreSQL" + ~ Prisma 7 to 8 (PostgreSQL) was "Migrate from Prisma 7 to Prisma 8" ~ Prisma 6 to 8 (MongoDB) was "MongoDB" v7, v6, v5, v4, v3, v1 - Deployment, Database, Switch to Prisma ORM, Prisma 7 content; lives under guides/v7 @@ -98,7 +98,7 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | J2 existing database with data | Add to Existing Project > PostgreSQL | right node, page stops before the ref step | | J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; fourteen diff blocks spread over six pages | | J4 should I move now | root, `/prisma-orm` | no node; note box only says 7 is supported | -| J5 incremental upgrade | Guides > Upgrade Prisma ORM > PostgreSQL | not linked from any ORM node; label hides it | +| J5 incremental upgrade | Guides > Upgrade Prisma ORM > Migrate from Prisma 7 to Prisma 8 | not linked from any ORM node; three levels down, and the MongoDB twin is labelled only "MongoDB" | | J6 data types | Data Modeling > Overview | right node; one stale example | | J7 editor setup | none | no node | | J8 advanced Postgres | none | no node; needs product answers | @@ -109,7 +109,7 @@ Two observations follow from the table. First, the Getting Started > Prisma ORM subtree is organised by the tool that runs (`create-prisma` for Quickstart, `orm init` for Add to Existing Project) and then by database. The reader does not know those tools yet. The failures in J1 and J2 both happen at the point where the reader's situation differs from the page's assumption about it. The reader knows their situation: do I have an app, do I have a database, does it have data, was it Prisma 7. That is why I proposed organising this subtree by starting state. The database split (PostgreSQL / MongoDB) stays inside each. -Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides with a database name as its label. +Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides, three levels down, and its MongoDB twin carries only a database name as its label. ## Current state @@ -173,7 +173,7 @@ Deployment, Authentication, Integrations, Postgres Database (Expand-and-contract migrations, Multiple databases, Schema management in teams) Switch to Prisma ORM, Switch to Prisma Postgres Upgrade Prisma ORM - PostgreSQL /guides/upgrade-prisma-orm/postgresql title: "Migrate from Prisma 7 to Prisma 8" + Migrate from Prisma 7 to Prisma 8 /guides/upgrade-prisma-orm/postgresql Prisma 7 to 8 MongoDB /guides/upgrade-prisma-orm/mongodb v6 Mongo to 8 v7, v6, v5, v4, v3, v1 older version-to-version guides Making guides @@ -183,4 +183,4 @@ Making guides - Root page: one line, "Here for the ORM? Jump straight to Prisma 7 or Prisma 8". - A note box ("Using Prisma 7?", "Prisma 7", or "Prisma 7 users") on `/orm`, `/prisma-orm`, `/prisma-orm/create-prisma`, all four getting-started pages (PostgreSQL and MongoDB), and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. -- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides, where the label is "PostgreSQL". +- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides > Upgrade Prisma ORM, where the PostgreSQL page is labelled "Migrate from Prisma 7 to Prisma 8" and the MongoDB page just "MongoDB" (#8238 relabels both). From df980a34cc338fafdc3695d5530126e93e42ea9c Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 18:09:41 +0200 Subject: [PATCH 13/68] docs: the release status facts are decided; drop the C4 decision row Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 0df707144fc..8be8185247b 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -10,7 +10,7 @@ Status as of 2026-09-11. **Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. -**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect (the Neon and Supabase Accelerate guides moved with it); fourteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. +**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. **In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. @@ -30,7 +30,6 @@ Status as of 2026-09-11. | Item | Decision | Who | |---|---|---| -| C4 | GA window to state publicly; Prisma ORM 7 support policy | Will | | D6 | Keep the release candidate on npm `latest`, or move it to `next` until GA | Will, with whoever owns publishing | | D4 | For each missing client API: build it, or document the workaround and say it is not planned | ORM product | | D1 | Which of the two designs for one-step adoption | ORM (brief in `brief-db-ref-on-adoption.md`) | @@ -48,9 +47,9 @@ The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These a - **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. -- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Fourteen further pages stay in Latest with a "This guide uses Prisma 7" note (the #8242 description counts thirteen; the tree has fourteen); #8242 says which are blocked on third-party adapters and which are portable follow-ups. +- **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. -- **A4** (sidebar labels and the guides index). The two upgrade-guide labels ("Prisma 7 to 8 (PostgreSQL)", "Prisma 6 to 8 (MongoDB)") are in #8238, open as of 2026-09-11. The guides index part landed in #8242, which replaced the "Coming as they land" list with an Upgrading section linking both guides. +- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. ## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) @@ -80,7 +79,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. - **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. - **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, the second migration with `--advance-ref db`. Unblocks J2. Waits on D1, which decides how short it can be. -- **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for twelve months; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. Waits on Will (facts) and D6 (whether the tag stays). +- **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; waits on D6 (whether the tag stays). - **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. - **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Waits on Serhii. @@ -119,7 +118,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. - **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. - **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. -- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it). `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. - **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. ### Product decisions From 63e942023952c8c42ca62bda3dd5b92e64136bdd Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 18:21:21 +0200 Subject: [PATCH 14/68] docs: add the plain-language rule and reader-review process Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 2 +- docs/orm-docs-audit/plain-language.md | 63 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 docs/orm-docs-audit/plain-language.md diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 1081ba2e4dd..35a2f7372e1 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -11,7 +11,7 @@ Read in this order: 3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. 4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. 5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; #8236 and #8237 are merged, #8238 is open as of 2026-09-11), new pages (C), ORM changes (D). Leads with the suggested order. -6. `naming.md` — the "Prisma ORM" naming rule. +6. `naming.md` — the "Prisma ORM" naming rule. `plain-language.md` — the rule every page must follow so it reads as written by a person for an ordinary user, with the banned-word list and the reader-review step. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. 8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). 9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. The audit is a snapshot of the site on 2026-09-10; the guides pages it flags as Prisma 7 content were rewritten for Prisma ORM 8 in #8242 on 2026-09-11. diff --git a/docs/orm-docs-audit/plain-language.md b/docs/orm-docs-audit/plain-language.md new file mode 100644 index 00000000000..4f8ae3498c5 --- /dev/null +++ b/docs/orm-docs-audit/plain-language.md @@ -0,0 +1,63 @@ +# Plain language: the rule for every page + +The reader is an ordinary developer who has used Prisma ORM before and has never seen the Prisma ORM 8 source code. Every sentence must be one they could restate in their own words on first reading. This is the largest complaint about the current docs and it overrides any other style preference. + +## The rule + +1. Say what the reader does and what happens. Not what the system is. +2. One idea per sentence. If a sentence needs a parenthetical, split it. +3. Use the reader's words for things: "the command-line tool", "the library your app imports", "your schema file", "the call that runs the query", "an error with a code". +4. A term from the source code may appear on a page only if the docs glossary already defines it for readers, or the sentence that first uses it says what it means in plain words. Otherwise use the plain words and drop the term. +5. Explain a mechanism only when the reader needs it to act. If they do not, cut it. +6. No sentence is finished if the reader has to guess what a word refers to. + +## Banned words and their replacements + +These come from `packages/` and the release notes and mean nothing to readers. Do not use them in prose; the replacement is the meaning. + +| Do not write | Write | +| --- | --- | +| terminal, terminal call, terminal method | the call that runs the query (`.all()`, `.first()`, `.create(...)`) | +| codec | how the value is stored and read; or just name the type | +| envelope, structured envelope, structured error | an error with a code (`RUNTIME.NO_ROWS`) | +| type position, "in type position" | written as the type (`VarChar(255)` instead of `@db.VarChar(255)`) | +| runtime (as a noun for the library) | the library your app imports; or `db` | +| release line, release cycle, runs ahead | released separately, on its own schedule | +| lane (SQL lane, raw lane) | the raw SQL API; the query builder | +| facade | the client; `postgres(...)` | +| junction model, join model | the model for the join table | +| plan, query plan | the query, before it runs; or the built query | +| emit, emitted artifacts (unexplained) | `prisma contract emit` writes `contract.json` and `contract.d.ts` | +| signature, marker (unexplained) | the record in the database of which contract it matches | +| ref (unexplained) | a named pointer to a migration state; explain on first use | +| capability | which database features the contract needs | +| buffers, buffered, materializes | loads every row into memory first | +| surface, API surface | the methods; the commands | +| lowered, lowering | turned into SQL | +| namespace-qualified, namespace coordinate | `db.orm.public.User` (`public` is the PostgreSQL schema) | +| reducer, refinement callback | a way to count or sum related records; a way to filter related records | +| dotted codes | a code such as `RUNTIME.NO_ROWS` | +| envelope config, CLI envelope | the config file | +| dev loop | while you are iterating | +| brownfield, greenfield | an existing database; a new project | +| deterministic | the same input always produces the same output | +| idempotent | safe to run more than once | +| topology, graph (for migrations, unexplained) | the chain of migrations | + +Also banned: "unblocks", "surfaces", "carries", "wires up", "sits", "lives at" (say "is at"), "spells", "hands back", "rides on", "routes on", "keys on", "the shape", "story" (as in "the `DATABASE_URL` story"). + +## Sentence shapes to avoid + +- A noun with three or more modifiers: "per-request cursor-enabled serverless facade". +- "X, so Y, which Z": three claims chained; split. +- A caveat in parentheses mid-sentence; make it its own sentence or cut it. +- Passive voice for what the reader does: "the version is pinned" becomes "lock the version". +- Starting with the mechanism: "Because emit is deterministic, hashing..." becomes what the reader sees. + +## Process + +1. Write the page from the facts. +2. Fact review against the source (as today). +3. Reader review: an agent with the persona above and only this file reads the page and marks every sentence it cannot restate and every word it had to guess. Fix every mark. Repeat until clean. +4. Run `check-plain.sh` on the changed files before pushing. +5. Will does the final pass. From babb53fdda1917926a7e53fbcb615afcb888b2ad Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 11 Sep 2026 18:23:02 +0200 Subject: [PATCH 15/68] docs: add the plain-language pass over the reference pages to the change list Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 8be8185247b..6e7a3e800e9 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -101,6 +101,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. - **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. - **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. +- **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. - **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. ## D. Change the ORM and its tooling From e1506b30ce88a4d6d6ae513e91377b4267d3d2ab Mon Sep 17 00:00:00 2001 From: willbot Date: Sat, 12 Sep 2026 08:52:00 +0200 Subject: [PATCH 16/68] docs: local database and runnable-example journeys, IA node, and change items C22 and C23 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 ++ docs/orm-docs-audit/ia.md | 24 ++++++++++++----------- docs/orm-docs-audit/journeys.md | 34 +++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 6e7a3e800e9..28f9cd1806c 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -81,6 +81,8 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, the second migration with `--advance-ref db`. Unblocks J2. Waits on D1, which decides how short it can be. - **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; waits on D6 (whether the tag stays). - **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. +- **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database: `prisma dev` first (a local Prisma Postgres, no install; the page under Local development already exists, link it), then the Composer local stack (`dev`), then a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. +- **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. - **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Waits on Serhii. ### Guides diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index b90a783a0d2..2d5362ea9e7 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -4,7 +4,7 @@ Proposal first, then why, then the current state it changes. Source: the `meta.j ## Proposed -Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, `-` is content leaving the tree, unmarked is unchanged. +Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. ### Getting Started > Prisma ORM @@ -22,12 +22,15 @@ Prisma ORM PostgreSQL MongoDB + Coming from Prisma 7 link to the ORM page below, so the Upgrader finds it from here + + A database on your machine prisma dev (no install) first; Composer's local stack; your own Postgres (Docker Compose); how to look at the rows + Editor setup create-prisma reference; moved to last ``` Four starting states, one group each. "Coming from Prisma 7" is a link node here because the page itself belongs with the API it maps. +"A database on your machine" answers the question every starting state runs into on the first page: where does `DATABASE_URL` come from when I have no hosted database. The site already has the answers, `prisma dev` under Local development and the Composer local stack, but a reader inside the ORM subtree never meets them; the quickstart's "Path A" is the only mention. The node names the three options in order of effort (`prisma dev`, Composer, a Postgres you run yourself with Docker Compose), links to the pages that already exist for the first two, gives the Docker Compose file and connection string for the third, and ends with how to look at the data (Studio against the local instance, or any Postgres client). + ### ORM > Introduction ``` @@ -42,14 +45,14 @@ Introduction ``` Overview no "coming soon" line for upgrading; it exists Upgrade Prisma ORM - ~ Prisma 7 to 8 (PostgreSQL) was "Migrate from Prisma 7 to Prisma 8" + ~ Prisma 7 to 8 (PostgreSQL) was "PostgreSQL" ~ Prisma 6 to 8 (MongoDB) was "MongoDB" v7, v6, v5, v4, v3, v1 - Deployment, Database, Switch to Prisma ORM, Prisma 7 content; lives under guides/v7 GitHub Actions, AI SDK, React Router 7, SolidStart ``` -The Prisma ORM 8 replacements for those labels sit at the same slugs; C9 (deployment), C11 (CI), and C12 (switching, team workflow) in `changes.md` say what they must cover. +The six Guides labels that leave come back as Prisma ORM 8 pages when C9 (deployment), C11 (CI), and C12 (switching, team workflow) are written. ### The ORM root page (`/orm`) @@ -80,6 +83,7 @@ The ORM line becomes a short row with the four starting states, linking into the | Add to an app you already have | J1 | | Adopt an existing database (rewritten) | J2 | | Coming from Prisma 7 | J3, J5 (links to the incremental guide), J6 (attribute map) | +| A database on your machine | J1, J11 | | Editor setup | J7 | | Guides labels and overview line | J5 | | Core concepts rewritten | the "written for AI" complaint, by giving the Newcomer a why-first page | @@ -96,9 +100,9 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | --- | --- | --- | | J1 existing app, empty database | Add to Existing Project > PostgreSQL | page assumes tables exist; no node for this state | | J2 existing database with data | Add to Existing Project > PostgreSQL | right node, page stops before the ref step | -| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; fourteen diff blocks spread over six pages | +| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; content spread over nine pages | | J4 should I move now | root, `/prisma-orm` | no node; note box only says 7 is supported | -| J5 incremental upgrade | Guides > Upgrade Prisma ORM > Migrate from Prisma 7 to Prisma 8 | not linked from any ORM node; three levels down, and the MongoDB twin is labelled only "MongoDB" | +| J5 incremental upgrade | Guides > Upgrade Prisma ORM > PostgreSQL | not linked from any ORM node; label hides it | | J6 data types | Data Modeling > Overview | right node; one stale example | | J7 editor setup | none | no node | | J8 advanced Postgres | none | no node; needs product answers | @@ -109,7 +113,7 @@ Two observations follow from the table. First, the Getting Started > Prisma ORM subtree is organised by the tool that runs (`create-prisma` for Quickstart, `orm init` for Add to Existing Project) and then by database. The reader does not know those tools yet. The failures in J1 and J2 both happen at the point where the reader's situation differs from the page's assumption about it. The reader knows their situation: do I have an app, do I have a database, does it have data, was it Prisma 7. That is why I proposed organising this subtree by starting state. The database split (PostgreSQL / MongoDB) stays inside each. -Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides, three levels down, and its MongoDB twin carries only a database name as its label. +Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides with a database name as its label. ## Current state @@ -162,8 +166,6 @@ Reference ### Guides (ORM-relevant parts) -Snapshot of 2026-09-10. On 2026-09-11, #8242 rewrote the Deployment, Database, Switch to Prisma ORM, GitHub Actions, AI SDK, React Router 7, and SolidStart pages for Prisma ORM 8 at the same slugs, moved their Prisma 7 versions (and Cloudflare D1) under `guides/v7`, and gave the overview an Upgrading section. - ``` Overview /guides says "Upgrading: moving from Prisma 7" is coming v7 @@ -173,7 +175,7 @@ Deployment, Authentication, Integrations, Postgres Database (Expand-and-contract migrations, Multiple databases, Schema management in teams) Switch to Prisma ORM, Switch to Prisma Postgres Upgrade Prisma ORM - Migrate from Prisma 7 to Prisma 8 /guides/upgrade-prisma-orm/postgresql Prisma 7 to 8 + PostgreSQL /guides/upgrade-prisma-orm/postgresql title: "Migrate from Prisma 7 to Prisma 8" MongoDB /guides/upgrade-prisma-orm/mongodb v6 Mongo to 8 v7, v6, v5, v4, v3, v1 older version-to-version guides Making guides @@ -182,5 +184,5 @@ Making guides ### Where Prisma 7 readers are pointed today - Root page: one line, "Here for the ORM? Jump straight to Prisma 7 or Prisma 8". -- A note box ("Using Prisma 7?", "Prisma 7", or "Prisma 7 users") on `/orm`, `/prisma-orm`, `/prisma-orm/create-prisma`, all four getting-started pages (PostgreSQL and MongoDB), and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. -- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides > Upgrade Prisma ORM, where the PostgreSQL page is labelled "Migrate from Prisma 7 to Prisma 8" and the MongoDB page just "MongoDB" (#8238 relabels both). +- A "Using Prisma 7?" note box on `/orm`, `/prisma-orm`, both PostgreSQL getting-started pages, and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. +- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides, where the label is "PostgreSQL". diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index c4682668e7f..080be2b7523 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -1,14 +1,14 @@ # Jobs readers come to the docs to do -Ten jobs. Each names who does it, what "done" looks like, what the docs must provide for it, and where the site's structure fails it. The jobs are the design input for `ia.md` (which node serves each job) and `changes.md` (which page or ORM change supplies what is missing). Verdicts describe the structure, not the state of any one sentence: **green** a page exists for the job and carries it end to end, **amber** the job can be done but the reader has to assemble it from several places or work around a gap, **red** no page is written for the job. +Twelve jobs. Each names who does it, what "done" looks like, what the docs must provide for it, and where the site's structure fails it. The jobs are the design input for `ia.md` (which node serves each job) and `changes.md` (which page or ORM change supplies what is missing). Verdicts describe the structure, not the state of any one sentence: **green** a page exists for the job and carries it end to end, **amber** the job can be done but the reader has to assemble it from several places or work around a gap, **red** no page is written for the job. ## J1. Add Prisma ORM to an app I already started, with an empty database Who: Newcomer, sometimes Upgrader. The most common Discord complaint is this job. -Done: models defined, tables created, one query returns rows, from inside the app they already have. +Done: models defined, tables created, one query returns rows, from inside the app they already have, and they can open the database and see those rows. -What the docs must provide: one page that starts from "you have a project directory and no tables", runs `orm init`, edit the contract, `contract emit`, `db init`, one query, and shows `db.ts` and where `DATABASE_URL` comes from. +What the docs must provide: one page that starts from "you have a project directory and no tables", runs `orm init`, edit the contract, `contract emit`, `db init`, one query, and shows `db.ts` and where `DATABASE_URL` comes from (linking J11 for a database on the reader's machine). It ends by showing the rows in the database, with Studio or a Postgres client, because that is how a beginner confirms the page worked. Where the structure fails: the getting-started subtree is organised by which tool runs (`create-prisma` for new apps, `orm init` for "existing project"). The reader's situation, an app with no database yet, falls between the two: the scaffold page creates a new app, and the existing-project page assumes tables exist and starts with `contract infer`. The three commands that fit exist only as a snippet on the CLI overview. @@ -34,7 +34,7 @@ Done: for every Prisma ORM 7 call in their code, they know the Prisma ORM 8 call What the docs must provide: one mapping page in four sections (schema and types, CLI commands, client API, not-yet list with a status per item), reachable from every ORM entry point. The not-yet list is the part readers ask for most: `createMany` and `skipDuplicates`, `findUniqueOrThrow`, atomic `increment`/`decrement`, case-insensitive filters, JSON path filters, `$transaction` arrays, the payload types. -Where the structure fails: there is no node. The mapping exists as fourteen inline diff blocks across six `orm/` pages (twelve of them introduced with "For Prisma 7 users"), so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. +Where the structure fails: there is no node. The mapping exists as sixteen inline "For Prisma 7 users" blocks across nine pages, so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. Verdict: **red**. IA node: "Coming from Prisma 7" (C1, placed by A2); the not-yet list depends on D4. @@ -122,6 +122,30 @@ Where the structure fails: the reader meets the files on the scaffold pages and Verdict: docs **amber**, tool **red**. Tool change D3. +## J11. Run Prisma ORM against a database on my machine + +Who: Newcomer, often a junior or a learner who does not want a hosted database yet. Reported on Discord by a reader who spent several days getting a local setup running and ended up reading example repositories on GitHub instead of the site. + +Done: a database runs locally, `DATABASE_URL` points at it, the first migration or `db init` has run, and the reader can see the tables and rows. + +What the docs must provide: one page in the ORM subtree that names the three ways to get a local database, in order of effort, and links or shows each: `prisma dev` (a local Prisma Postgres, no install), the Composer local stack (`dev`, which also runs the app), and a PostgreSQL the reader runs themselves, with a Docker Compose file and the matching connection string. It ends with how to look at the data: Studio against the local instance, or any Postgres client such as pgAdmin. + +Where the structure fails: the answers exist on the site, under Local development and Composer, but those are top-level platform sections. Nothing in the ORM subtree points at them except the quickstart's "Path A", which a reader who arrived at the ORM section from a search result never sees. A reader who wants Docker Compose finds only the Docker deployment guide, which is about shipping, not developing. + +Verdict: **red**. IA node: "A database on your machine". + +## J12. Learn from a runnable example + +Who: Newcomer. The same Discord reader: "I would recommend tutorials which can be cloned, run locally, and have a lot of comments in the code to understand what files need to be created and coded, which files are generated and why." + +Done: the reader has cloned a repository, run it against a local database, and can tell from comments in the code which files they wrote, which files Prisma generated, and what each command in `package.json` does. + +What the docs must provide: one small example repository per starting state (new app, app you already have, existing database), each with a README that says which files are yours (`contract.prisma`, `db.ts`, `prisma.config.ts`, your queries), which are generated (`contract.json`, `contract.d.ts`, `migrations/`), and the command that produces each generated file. Every quickstart and starting-state page links the matching repository. The monorepo's `examples/prisma-8-demo` is the seed. + +Where the structure fails: no page links a runnable repository. The quickstarts are copy-and-paste sequences with no way to check a broken local setup against a known-good one. + +Verdict: **red**. IA node: links from every starting-state page; no new node. + ## Summary | Job | Verdict | What serves it | @@ -136,3 +160,5 @@ Verdict: docs **amber**, tool **red**. Tool change D3. | J8 advanced Postgres | red | Advanced Postgres (C7) | | J9 types | red | Types (C6) on the next tagged release | | J10 agent files | amber / red | the line on scaffold pages; D3 | +| J11 local database | red | A database on your machine (C22) | +| J12 runnable example | red | example repositories linked from every starting state (C23) | From f0996aae528ef1bd4104951e61fcc3eac39663dd Mon Sep 17 00:00:00 2001 From: willbot Date: Sat, 12 Sep 2026 08:52:34 +0200 Subject: [PATCH 17/68] docs: keep the branch's newer ia and journeys text; add only J11, J12, the IA node, C22 and C23 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/ia.md | 20 +++++++++++--------- docs/orm-docs-audit/journeys.md | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 2d5362ea9e7..8a7585f1425 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -4,7 +4,7 @@ Proposal first, then why, then the current state it changes. Source: the `meta.j ## Proposed -Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, unmarked is unchanged. +Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, and the Guides tree (two labels, and the Prisma 7 pages leaving it). Nothing else moves. `+` is a new node, `~` is a renamed or rewritten node, `-` is content leaving the tree, unmarked is unchanged. ### Getting Started > Prisma ORM @@ -45,14 +45,14 @@ Introduction ``` Overview no "coming soon" line for upgrading; it exists Upgrade Prisma ORM - ~ Prisma 7 to 8 (PostgreSQL) was "PostgreSQL" + ~ Prisma 7 to 8 (PostgreSQL) was "Migrate from Prisma 7 to Prisma 8" ~ Prisma 6 to 8 (MongoDB) was "MongoDB" v7, v6, v5, v4, v3, v1 - Deployment, Database, Switch to Prisma ORM, Prisma 7 content; lives under guides/v7 GitHub Actions, AI SDK, React Router 7, SolidStart ``` -The six Guides labels that leave come back as Prisma ORM 8 pages when C9 (deployment), C11 (CI), and C12 (switching, team workflow) are written. +The Prisma ORM 8 replacements for those labels sit at the same slugs; C9 (deployment), C11 (CI), and C12 (switching, team workflow) in `changes.md` say what they must cover. ### The ORM root page (`/orm`) @@ -100,9 +100,9 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | --- | --- | --- | | J1 existing app, empty database | Add to Existing Project > PostgreSQL | page assumes tables exist; no node for this state | | J2 existing database with data | Add to Existing Project > PostgreSQL | right node, page stops before the ref step | -| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; content spread over nine pages | +| J3 Prisma 7 query mapping | Fundamentals > Reading data | no node; fourteen diff blocks spread over six pages | | J4 should I move now | root, `/prisma-orm` | no node; note box only says 7 is supported | -| J5 incremental upgrade | Guides > Upgrade Prisma ORM > PostgreSQL | not linked from any ORM node; label hides it | +| J5 incremental upgrade | Guides > Upgrade Prisma ORM > Migrate from Prisma 7 to Prisma 8 | not linked from any ORM node; three levels down, and the MongoDB twin is labelled only "MongoDB" | | J6 data types | Data Modeling > Overview | right node; one stale example | | J7 editor setup | none | no node | | J8 advanced Postgres | none | no node; needs product answers | @@ -113,7 +113,7 @@ Two observations follow from the table. First, the Getting Started > Prisma ORM subtree is organised by the tool that runs (`create-prisma` for Quickstart, `orm init` for Add to Existing Project) and then by database. The reader does not know those tools yet. The failures in J1 and J2 both happen at the point where the reader's situation differs from the page's assumption about it. The reader knows their situation: do I have an app, do I have a database, does it have data, was it Prisma 7. That is why I proposed organising this subtree by starting state. The database split (PostgreSQL / MongoDB) stays inside each. -Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides with a database name as its label. +Second, the Upgrader has no node anywhere in Getting Started or ORM. Every Prisma 7 pointer is for staying on 7. The one page written for moving to 8 is filed under Guides, three levels down, and its MongoDB twin carries only a database name as its label. ## Current state @@ -166,6 +166,8 @@ Reference ### Guides (ORM-relevant parts) +Snapshot of 2026-09-10. On 2026-09-11, #8242 rewrote the Deployment, Database, Switch to Prisma ORM, GitHub Actions, AI SDK, React Router 7, and SolidStart pages for Prisma ORM 8 at the same slugs, moved their Prisma 7 versions (and Cloudflare D1) under `guides/v7`, and gave the overview an Upgrading section. + ``` Overview /guides says "Upgrading: moving from Prisma 7" is coming v7 @@ -175,7 +177,7 @@ Deployment, Authentication, Integrations, Postgres Database (Expand-and-contract migrations, Multiple databases, Schema management in teams) Switch to Prisma ORM, Switch to Prisma Postgres Upgrade Prisma ORM - PostgreSQL /guides/upgrade-prisma-orm/postgresql title: "Migrate from Prisma 7 to Prisma 8" + Migrate from Prisma 7 to Prisma 8 /guides/upgrade-prisma-orm/postgresql Prisma 7 to 8 MongoDB /guides/upgrade-prisma-orm/mongodb v6 Mongo to 8 v7, v6, v5, v4, v3, v1 older version-to-version guides Making guides @@ -184,5 +186,5 @@ Making guides ### Where Prisma 7 readers are pointed today - Root page: one line, "Here for the ORM? Jump straight to Prisma 7 or Prisma 8". -- A "Using Prisma 7?" note box on `/orm`, `/prisma-orm`, both PostgreSQL getting-started pages, and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. -- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides, where the label is "PostgreSQL". +- A note box ("Using Prisma 7?", "Prisma 7", or "Prisma 7 users") on `/orm`, `/prisma-orm`, `/prisma-orm/create-prisma`, all four getting-started pages (PostgreSQL and MongoDB), and `/cli`. It says Prisma 7 remains supported and links to `/orm/v7` and `/v7/getting-started`. Both links are for staying on 7. +- Nothing under Getting Started or ORM links to the upgrade guide. It is reachable only through Guides > Upgrade Prisma ORM, where the PostgreSQL page is labelled "Migrate from Prisma 7 to Prisma 8" and the MongoDB page just "MongoDB" (#8238 relabels both). diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index 080be2b7523..f8ef9eb5c4a 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -8,7 +8,7 @@ Who: Newcomer, sometimes Upgrader. The most common Discord complaint is this job Done: models defined, tables created, one query returns rows, from inside the app they already have, and they can open the database and see those rows. -What the docs must provide: one page that starts from "you have a project directory and no tables", runs `orm init`, edit the contract, `contract emit`, `db init`, one query, and shows `db.ts` and where `DATABASE_URL` comes from (linking J11 for a database on the reader's machine). It ends by showing the rows in the database, with Studio or a Postgres client, because that is how a beginner confirms the page worked. +What the docs must provide: one page that starts from "you have a project directory and no tables", runs `orm init`, edit the contract, `contract emit`, `db init`, one query, and shows `db.ts` and where `DATABASE_URL` comes from. Where the structure fails: the getting-started subtree is organised by which tool runs (`create-prisma` for new apps, `orm init` for "existing project"). The reader's situation, an app with no database yet, falls between the two: the scaffold page creates a new app, and the existing-project page assumes tables exist and starts with `contract infer`. The three commands that fit exist only as a snippet on the CLI overview. @@ -34,7 +34,7 @@ Done: for every Prisma ORM 7 call in their code, they know the Prisma ORM 8 call What the docs must provide: one mapping page in four sections (schema and types, CLI commands, client API, not-yet list with a status per item), reachable from every ORM entry point. The not-yet list is the part readers ask for most: `createMany` and `skipDuplicates`, `findUniqueOrThrow`, atomic `increment`/`decrement`, case-insensitive filters, JSON path filters, `$transaction` arrays, the payload types. -Where the structure fails: there is no node. The mapping exists as sixteen inline "For Prisma 7 users" blocks across nine pages, so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. +Where the structure fails: there is no node. The mapping exists as fourteen inline diff blocks across six `orm/` pages (twelve of them introduced with "For Prisma 7 users"), so the reader finds it by luck, and nothing admits what does not exist. The accessor change (`prisma.user` to `db.orm.public.User`) is stated once. Verdict: **red**. IA node: "Coming from Prisma 7" (C1, placed by A2); the not-yet list depends on D4. From c02aa1533b125c94d914dacc68d52a1978b9b658 Mon Sep 17 00:00:00 2001 From: willbot Date: Sat, 12 Sep 2026 09:04:43 +0200 Subject: [PATCH 18/68] docs: handover brief for the next agent Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 docs/orm-docs-audit/HANDOVER.md diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md new file mode 100644 index 00000000000..2cc0fa14a25 --- /dev/null +++ b/docs/orm-docs-audit/HANDOVER.md @@ -0,0 +1,55 @@ +# Handover: Prisma ORM 8 docs audit and plain-language pass + +Written 2026-09-12 by the previous agent for the next one. Read this first, then `changes.md` in this directory. + +## Transcript of the previous session + +`/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` + +Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a page name. The session was compacted once; the first user message after compaction carries a summary of everything before it. + +## Where things are + +- `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). +- Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. +- Draft PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 in progress on `apps/docs/content/docs/orm/reference/orm-client.mdx`. See "Current task". +- The Prisma ORM 8 source used for every fact check is `prisma/orm` at tag `8.0.0-rc.9` (`f889eeb89e`). The previous worktree had it at `wip/prisma-src/`; in a fresh worktree, `git -C /Users/will/Projects/prisma/prisma worktree add f889eeb89e`. The published CLI is newer than that tree: `prisma@8.0.0-rc.13` exists, `npx prisma skills sync` exists, and `prisma/config` is the config import. ORM packages are still rc.9. + +## How to work (rules Will has given, in his words where possible) + +- Act as the `wmadden-electric` bot: commit with `git commit -s --trailer "Signed-off-by: Will Madden "`, end the message with `Co-Authored-By: Claude Fable 5.1 `, push only through the `bot` remote. +- "NOT EVERY FUCKING CHANGE NEEDS A SEPARATE PR": follow-ups go on the open PR. +- Address every review comment and every CI failure without being asked. Resolve CodeRabbit threads via GraphQL `resolveReviewThread` after replying. CodeRabbit's "changes requested" verdict blocks the merge even when all threads are resolved; dismissing it is blocked for the agent, so Will dismisses it or merges with `--admin`. +- PR descriptions: a grounding before/after example first, then the decision, then how it was checked, then what a reviewer should know, alternatives considered last. +- Plain English, no invented jargon, short sentences. Never use the question UI. +- The design docs carry no status ("they are not a fucking to do list"). Progress lives in PRs. +- The product is "Prisma ORM"; a version number only when contrasting ("Prisma ORM 7 to 8"). The reason is separating the Prisma brand from the ORM. +- Use Opus for implementer and reviewer subagents. +- Do not paste the readers' reports into pages; extract each agent's final message from its task output with the small script in `c21-orm-client/` (`extract.py` in the previous scratchpad; it prints the last assistant text block of a task JSONL). + +## The C21 method (what worked on the fundamentals pages) + +The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: + +1. Run `scripts/check-plain.sh` and fix hits. +2. Dispatch a fresh Opus reader with `references/reader-persona.md` verbatim and only the page (a long page in slices by `##` heading, 400 to 700 lines each). Save its report with the extract script. +3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; in `c21-orm-client/` on #8260), the page's own conventions file if any, the report, and the rc.9 source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. +4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a "no longer than it is now" budget, because pages grow and readers then trip on the additions. +5. Fact re-check by a separate Opus agent against the source, claim by claim, before the PR. On the fundamentals pages this caught seven real errors that the wording rounds had introduced or left standing. Do not skip it. +6. Commit each round. Link check: `cd apps/docs && node_modules/.bin/fumadocs-mdx && node_modules/.bin/tsx ./scripts/lint-links.ts`. Spelling: `node_modules/.bin/cspell "content/docs/orm/**/*.mdx"` (random sample ids fail it; use `cuid2000...` style). Revert any `meta.json` the formatter touches. + +Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. + +## Current task: C21 on `orm/reference/orm-client.mdx` (draft PR #8260) + +Done: banned terms replaced (headings "Read terminals" and "Mutation terminals" are now "Read methods" and "Write methods" with the old anchors pinned); round one read in four slices; round one fixes applied to all four slices and reassembled (2,058 lines; plain check, cspell, and link check pass). + +Not done, and the reason it matters: the four fixer agents were stopped before they reported, so their factual changes are unverified. The page rules gave them a list of facts to look up (see `c21-orm-client/page-conventions.md`, last bullet). Start with a full fact re-check of the reassembled page against rc.9, apply corrections, then rounds two to four, then the final fact re-check, then take #8260 out of draft with a description in Will's format. Delete `docs/orm-docs-audit/c21-orm-client/` from the branch before it merges. + +## After that, in order + +1. The other seven pages under `orm/reference/`, one PR for the section. +2. `orm/contract-authoring/`, `orm/data-modeling/`, `orm/migrations/`, `orm/middleware/`, `orm/extensions/` (20 pages), one PR per section. +3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. +4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. +5. Briefs waiting for an ORM-side owner: `brief-skill-staleness.md` (D14), D17 in `changes.md`. Add to D14: the scorecard marks `contains`/`startsWith`/`endsWith` as reachable when they are not, and the skill still says N:M includes fail when they work. From 35d116861054b9fb395c73a28ead96dd7cb120b3 Mon Sep 17 00:00:00 2001 From: willbot Date: Sat, 12 Sep 2026 11:13:26 +0200 Subject: [PATCH 19/68] docs: handover brief, orm-client page finished, next is the rest of orm/reference Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index 2cc0fa14a25..ec639f609c7 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -12,7 +12,7 @@ Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a pa - `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). - Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. -- Draft PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 in progress on `apps/docs/content/docs/orm/reference/orm-client.mdx`. See "Current task". +- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, finished on 2026-09-12 and out of draft: two fact re-checks against rc.9 and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5; they were removed from the tree before review. - The Prisma ORM 8 source used for every fact check is `prisma/orm` at tag `8.0.0-rc.9` (`f889eeb89e`). The previous worktree had it at `wip/prisma-src/`; in a fresh worktree, `git -C /Users/will/Projects/prisma/prisma worktree add f889eeb89e`. The published CLI is newer than that tree: `prisma@8.0.0-rc.13` exists, `npx prisma skills sync` exists, and `prisma/config` is the config import. ORM packages are still rc.9. ## How to work (rules Will has given, in his words where possible) @@ -40,15 +40,16 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. -## Current task: C21 on `orm/reference/orm-client.mdx` (draft PR #8260) +## Current task: the other seven pages under `orm/reference/` -Done: banned terms replaced (headings "Read terminals" and "Mutation terminals" are now "Read methods" and "Write methods" with the old anchors pinned); round one read in four slices; round one fixes applied to all four slices and reassembled (2,058 lines; plain check, cspell, and link check pass). +`orm-client.mdx` is done (PR #8260). Next is item 1 below. Two things learned on the orm-client page that the fundamentals pages did not show: -Not done, and the reason it matters: the four fixer agents were stopped before they reported, so their factual changes are unverified. The page rules gave them a list of facts to look up (see `c21-orm-client/page-conventions.md`, last bullet). Start with a full fact re-check of the reassembled page against rc.9, apply corrections, then rounds two to four, then the final fact re-check, then take #8260 out of draft with a description in Will's format. Delete `docs/orm-docs-audit/c21-orm-client/` from the branch before it merges. +- On a reference page, readers keep asking for getting-started material (installing, `prisma orm init`, creating tables). Answer with one sentence and a link; do not add it. +- From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts after four wording rounds, so do not skip it. ## After that, in order -1. The other seven pages under `orm/reference/`, one PR for the section. +1. The other seven pages under `orm/reference/`, one PR for the section (the current task). 2. `orm/contract-authoring/`, `orm/data-modeling/`, `orm/migrations/`, `orm/middleware/`, `orm/extensions/` (20 pages), one PR per section. 3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. 4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. From cfbf40650512a760cf733f9b6d284e202544bbee Mon Sep 17 00:00:00 2001 From: willbot Date: Sun, 13 Sep 2026 09:29:37 +0200 Subject: [PATCH 20/68] docs: brief for documenting intermediate contracts in data transform migrations (C25) Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 2 +- .../brief-intermediate-contracts.md | 47 +++++++++++++++++++ docs/orm-docs-audit/changes.md | 1 + 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 docs/orm-docs-audit/brief-intermediate-contracts.md diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 35a2f7372e1..0c54744868e 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -13,7 +13,7 @@ Read in this order: 5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; #8236 and #8237 are merged, #8238 is open as of 2026-09-11), new pages (C), ORM changes (D). Leads with the suggested order. 6. `naming.md` — the "Prisma ORM" naming rule. `plain-language.md` — the rule every page must follow so it reads as written by a person for an ordinary user, with the banned-word list and the reader-review step. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. -8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). +8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents; `brief-intermediate-contracts.md` — a docs page to write (C25) (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). 9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. The audit is a snapshot of the site on 2026-09-10; the guides pages it flags as Prisma 7 content were rewritten for Prisma ORM 8 in #8242 on 2026-09-11. Prose is a draft throughout; the structure and the cited facts are what has been verified. diff --git a/docs/orm-docs-audit/brief-intermediate-contracts.md b/docs/orm-docs-audit/brief-intermediate-contracts.md new file mode 100644 index 00000000000..50920cebaa5 --- /dev/null +++ b/docs/orm-docs-audit/brief-intermediate-contracts.md @@ -0,0 +1,47 @@ +# Docs update for intermediate contracts in data transform migrations + +Recorded 2026-09-13 from a brief written on another branch. Target page: `apps/docs/content/docs/orm/migrations/editing-a-migration.mdx`, next to `dataTransform`. Change item C25 in `changes.md`. + +# For the docs site: data transforms that need an intermediate contract + +Audience: an agent writing or extending the Prisma 8 migrations documentation. This describes a technique that exists in the ORM today and is specified in ADR 197 ("Migration packages snapshot their own contract", section "Intermediate contracts") in `prisma/orm`. It should be documented next to `dataTransform`, because it answers the first question anyone hits when a migration both changes a column and has to move data through it. + +## The problem the reader has + +A migration in Prisma 8 is an edge between two contracts: the start contract and the end contract. Its `dataTransform` step runs typed ORM queries, and those queries are typed and planned against a contract the author hands in. The natural choice is the end contract, and for a pure backfill it is right: add a nullable column, fill it, the end contract has the column. + +It stops working the moment the transform has to read something the migration removes. Example: replacing a boolean `needsReply` with an enum column `state`. The transform must read `needsReply` to decide each row's `state`, but the end contract no longer has `needsReply`, so a query against it cannot name that column; the planner rejects it (`PN-MIG-2005`, a reference to something not in the contract). The start contract has `needsReply` but not `state`, so a query against it cannot write the new column either. Neither contract describes the database at the moment the transform runs. + +Authors who hit this reach for raw SQL inside the migration, which throws away the typing the contract-first design exists to give them. + +## The technique + +Describe the in-between state as a contract of its own, inside the migration directory, and type the transform against it. + +1. Copy the schema authoring file (the `.prisma` file, or the TypeScript builder) into the migration directory as `intermediate.prisma`. +2. Edit it to the shape the database has at the moment the transform runs: in the example, `ConversationReplyState` carries both `needsReply Boolean` and `state reply_state?` (nullable, because it is not yet filled). +3. Emit it: `prisma contract emit` pointed at that file, producing `intermediate.json` and `intermediate.d.ts` next to it. These are snapshots; they never change after the migration is written, which is the same rule ADR 197 applies to the migration's own `contract.json`. +4. In `migration.ts`, import both the end contract snapshot and the intermediate one, and order the operations as: schema steps that reach the intermediate state (add the nullable `state` column), then `this.dataTransform(intermediateContract, 'fill reply state', { run: () => })`, then the schema steps that reach the end state (set `state` not null, drop `needsReply`, drop anything else the migration removes). + +The transform's queries are now typed: `needsReply` and `state` both exist in the contract they are built from, the plan's storage hash matches the contract the transform was handed (the runner checks this and refuses a mismatch with `MIGRATION.DATA_TRANSFORM_CONTRACT_MISMATCH`), and nothing is raw text. + +Multiple intermediate contracts are allowed; the author names and emits each one. Every migration directory is self-contained: it never reaches outside itself for type information, so it keeps type-checking however the project's schema evolves afterwards. + +## A trap the page must warn about + +A column declared with `temporal.updatedAtString()` makes the query builder set it on every update, and it does so by putting the current time into the plan as a parameter. A migration's transform is lowered into `ops.json` when the migration is planned, not when it is applied, so that timestamp is baked into `ops.json`, and every re-emit of the migration produces different bytes while `migration.json` keeps the same hash. `migration status` then reports `MIGRATION.CONTRACT_SPACE_VIOLATION` and the author has no idea why. In the intermediate contract, declare such columns as a plain timestamp type (`TimestamptzString`) rather than the auto-updating form; the intermediate contract only types the transform, so the end contract's `updatedAt` behaviour is untouched. Found while writing the first such migration in `prisma/asks` (2026-09-12). + +## What the docs page should show + +- A worked example with three files: `intermediate.prisma` (the relevant model only), `migration.ts` with the imports and the operation order, and the directory listing after `contract emit`. +- The rule of thumb: type a transform against the end contract when the transform only writes columns the end contract has and reads columns it keeps; use an intermediate contract when the transform reads anything the migration removes or renames, or writes a column before its final constraints are applied. +- The failure the reader sees without it (`PN-MIG-2005` against the end contract) and why raw SQL is the wrong fix. +- The alternative of two migrations (add and fill in the first, drop in the second), when a team prefers not to keep an intermediate snapshot, with its cost: an extra contract version that exists only to make the transform expressible. + +## References for the writer + +- `prisma/orm`, `docs/architecture docs/adrs/ADR 197 - Migration packages snapshot their own contract.md`, section "Intermediate contracts" (the directory layout and the import pattern are there, written for Mongo; the Postgres form is identical apart from the builder). +- `prisma/orm`, `packages/3-targets/3-targets/postgres/src/core/migrations/operations/data-transform.ts`, the Postgres `dataTransform(contract, name, { run, check })` signature and its contract-mismatch check. +- `prisma/orm`, `examples/retail-store/migrations/app/20260513T0508_backfill_product_status/migration.ts`, a backfill transform (Mongo) showing the operation order and the snapshot imports. +- ADR 028 ("Migration Structure & Operations") for migrations as edges between contract hashes, and ADR 192 for why no TypeScript runs at apply time: the intermediate contract matters at plan time only; the runner executes the lowered `ops.json`. +- Status note from ADR 197: the scaffolder's automatic snapshot copy is target state; the intermediate-contract workflow itself is done by hand with `contract emit` and works with the current CLI. Verify against the release the page documents. diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 28f9cd1806c..f677c29f5ee 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -104,6 +104,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. - **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. - **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. +- **C25. Data transforms that need an intermediate contract.** A migration that both removes a column and has to read it in `dataTransform` cannot type the transform against either the start or the end contract; the planner rejects the query with `PN-MIG-2005`, and authors fall back to raw SQL. The technique that exists today: emit an `intermediate.prisma` inside the migration directory describing the in-between shape, and type the transform against it. Goes on `orm/migrations/editing-a-migration.mdx` next to `dataTransform`, with the `updatedAtString()` trap that makes `ops.json` non-deterministic. Brief: `brief-intermediate-contracts.md`. - **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. ## D. Change the ORM and its tooling From 82ddf61a48a82c18b2953ba6715b6d67b4644b4d Mon Sep 17 00:00:00 2001 From: willbot Date: Sun, 13 Sep 2026 14:27:47 +0200 Subject: [PATCH 21/68] docs: handover after the orm/reference section (#8267) Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index ec639f609c7..c18dac26d45 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -1,6 +1,6 @@ # Handover: Prisma ORM 8 docs audit and plain-language pass -Written 2026-09-12 by the previous agent for the next one. Read this first, then `changes.md` in this directory. +Written 2026-09-12, updated 2026-09-13, by the previous agent for the next one. Read this first, then `changes.md` in this directory. ## Transcript of the previous session @@ -12,8 +12,9 @@ Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a pa - `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). - Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. -- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, finished on 2026-09-12 and out of draft: two fact re-checks against rc.9 and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5; they were removed from the tree before review. -- The Prisma ORM 8 source used for every fact check is `prisma/orm` at tag `8.0.0-rc.9` (`f889eeb89e`). The previous worktree had it at `wip/prisma-src/`; in a fresh worktree, `git -C /Users/will/Projects/prisma/prisma worktree add f889eeb89e`. The published CLI is newer than that tree: `prisma@8.0.0-rc.13` exists, `npx prisma skills sync` exists, and `prisma/config` is the config import. ORM packages are still rc.9. +- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5. +- PR #8267 (branch `docs/orm8-plain-language-orm-reference`) is C21 on the rest of `orm/reference/` (`sql-query-builder`, `raw-queries`, `pipeline-builder`, `transactions-and-runtime`, `index`), merged 2026-09-13: a fact check against rc.10, four reader rounds, a final fact re-check, and CodeRabbit's six comments. The reports are in the branch history at 13f900ad2. The error reference page is generated from prisma/orm and out of scope. +- The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`), since #8261 moved the docs to rc.10. The previous worktree had it at `wip/prisma-src/`; in a fresh worktree, `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Check whether a newer rc has landed before starting a section. ## How to work (rules Will has given, in his words where possible) @@ -25,6 +26,10 @@ Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a pa - The design docs carry no status ("they are not a fucking to do list"). Progress lives in PRs. - The product is "Prisma ORM"; a version number only when contrasting ("Prisma ORM 7 to 8"). The reason is separating the Prisma brand from the ORM. - Use Opus for implementer and reviewer subagents. +- Never fix one sentence Will points at in isolation. Reread the whole page and check the claims around it; a bad sentence has always meant more was wrong nearby ("NEVER REWRITE SENTENCES IN ISOLATION. REREAD THE WHOLE DOCUMENT"). +- No commentary about the docs inside the docs: no "this page documents", no "each method has a Remarks list", no "examples carry over between pages". Write the reference itself. +- Never interleave PostgreSQL and MongoDB sentence by sentence. Give each database its own example and its own paragraph. +- Resolving CodeRabbit threads: zsh does not word-split `$ids`, so loop with `while read -r id`, and keep the GraphQL query in a file under `wip/` and pass it with `-f query="$(cat file)"`. - Do not paste the readers' reports into pages; extract each agent's final message from its task output with the small script in `c21-orm-client/` (`extract.py` in the previous scratchpad; it prints the last assistant text block of a task JSONL). ## The C21 method (what worked on the fundamentals pages) @@ -33,24 +38,26 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: 1. Run `scripts/check-plain.sh` and fix hits. 2. Dispatch a fresh Opus reader with `references/reader-persona.md` verbatim and only the page (a long page in slices by `##` heading, 400 to 700 lines each). Save its report with the extract script. -3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; in `c21-orm-client/` on #8260), the page's own conventions file if any, the report, and the rc.9 source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. +3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; in `c21-orm-client/` on #8260), the page's own conventions file if any, the report, and the source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. 4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a "no longer than it is now" budget, because pages grow and readers then trip on the additions. 5. Fact re-check by a separate Opus agent against the source, claim by claim, before the PR. On the fundamentals pages this caught seven real errors that the wording rounds had introduced or left standing. Do not skip it. 6. Commit each round. Link check: `cd apps/docs && node_modules/.bin/fumadocs-mdx && node_modules/.bin/tsx ./scripts/lint-links.ts`. Spelling: `node_modules/.bin/cspell "content/docs/orm/**/*.mdx"` (random sample ids fail it; use `cuid2000...` style). Revert any `meta.json` the formatter touches. Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. -## Current task: the other seven pages under `orm/reference/` +## Current task: `orm/contract-authoring/` -`orm-client.mdx` is done (PR #8260). Next is item 1 below. Two things learned on the orm-client page that the fundamentals pages did not show: +`orm/reference/` is done (#8260, #8267). Next is item 1 below, one PR per section. Things learned on the reference pages that the fundamentals pages did not show: - On a reference page, readers keep asking for getting-started material (installing, `prisma orm init`, creating tables). Answer with one sentence and a link; do not add it. -- From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts after four wording rounds, so do not skip it. +- From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts on the orm-client page and twenty-six on the other reference pages after four wording rounds, so do not skip it. +- Fact checkers infer motives and defaults the source does not state (why a helper was renamed, what a driver returns). Trim to what a source line says. +- When a section's pages run in parallel, a `page-conventions.md` beside `conventions.md` keeps them agreeing on setup lines, the example schema, and phrasing such as "PostgreSQL only". ## After that, in order -1. The other seven pages under `orm/reference/`, one PR for the section (the current task). -2. `orm/contract-authoring/`, `orm/data-modeling/`, `orm/migrations/`, `orm/middleware/`, `orm/extensions/` (20 pages), one PR per section. +1. `orm/contract-authoring/` (the current task), then `orm/data-modeling/`, `orm/migrations/`, `orm/middleware/`, `orm/extensions/` (20 pages in all), one PR per section. +2. C25, `brief-intermediate-contracts.md`: intermediate contracts in data transform migrations. Fits the `orm/migrations/` section pass. 3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. 4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. 5. Briefs waiting for an ORM-side owner: `brief-skill-staleness.md` (D14), D17 in `changes.md`. Add to D14: the scorecard marks `contains`/`startsWith`/`endsWith` as reachable when they are not, and the skill still says N:M includes fail when they work. From 056dcc62ef7d727ea1e63e129fb8b89af0fc2623 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 14 Sep 2026 16:15:34 +0200 Subject: [PATCH 22/68] docs: handover after the contract-authoring section (#8271) Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index c18dac26d45..3ac82862bbb 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -1,20 +1,23 @@ # Handover: Prisma ORM 8 docs audit and plain-language pass -Written 2026-09-12, updated 2026-09-13, by the previous agent for the next one. Read this first, then `changes.md` in this directory. +Written 2026-09-12, updated 2026-09-14, by the previous agent for the next one. Read this first, then `changes.md` in this directory. ## Transcript of the previous session -`/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` +`/Users/wmadden/.claude/projects/-Users-wmadden-Projects-prisma-web--claude-worktrees-error-reference-follow-ups-81a8e7/29b9a58b-bb9f-48f4-8639-597b84cf76f8.jsonl` (about 15 MB; 2026-09-13 to 2026-09-14, the orm/reference and contract-authoring passes). If your sandbox cannot read it, tell Will straight away and wait: he will copy it into your worktree. Do not continue without it. The session before that one is at `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` (the audit and the fundamentals pass). -Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a page name. The session was compacted once; the first user message after compaction carries a summary of everything before it. +Search the transcript for `C21`, `reader review`, `fact re-check`, `factcheck2`, `conventions.md`, or a page name. It was compacted once; the first user message after compaction carries a summary of everything before it. ## Where things are - `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). - Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. - PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5. +- PR #8271 (branch `docs/orm8-plain-language-contract-authoring`) is C21 on `orm/contract-authoring/` (the data contract, PSL, TypeScript builder, the two emitted files, and the page now titled Supported database features), plus three things Will asked for while it ran: the Supported databases page at `/prisma-orm/supported-databases` (PostgreSQL release candidate, MongoDB early access, everything else coming soon; it replaces the database section of prisma/orm#25843), the upgrade guides linked from the ORM section's Introduction and the v7 guides nav, and a sidebar fix (folders in the version-filtered Guides tree never opened for their own page; they now match by id). It is approved on GitHub and green; the agent could not merge it because the tool refused a merge, so Will merges it. The reports are in the branch history at 40c5394e3. The plain-language checker (`check-plain.sh`) now skips link targets, pinned anchors, `href` attributes, and the front-matter `url` line. - PR #8267 (branch `docs/orm8-plain-language-orm-reference`) is C21 on the rest of `orm/reference/` (`sql-query-builder`, `raw-queries`, `pipeline-builder`, `transactions-and-runtime`, `index`), merged 2026-09-13: a fact check against rc.10, four reader rounds, a final fact re-check, and CodeRabbit's six comments. The reports are in the branch history at 13f900ad2. The error reference page is generated from prisma/orm and out of scope. -- The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`), since #8261 moved the docs to rc.10. The previous worktree had it at `wip/prisma-src/`; in a fresh worktree, `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Check whether a newer rc has landed before starting a section. +- The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. +- The published `prisma` package (8.0.0-rc.15 on 2026-09-14) exports `./config`, so the docs import `definePrismaConfig` from `prisma/config`. The rc.10 source tree only has `@prisma/cli-engine` and every fact checker "corrects" it; revert them. Check with `npm view prisma@latest exports`. +- The design branch is checked out in the previous worktree at `wip/design/` (a git worktree under the gitignored `wip/`). In a fresh worktree, `git worktree add wip/design docs/orm8-docs-audit-design` after `git fetch bot` and `git branch -f docs/orm8-docs-audit-design bot/docs/orm8-docs-audit-design`. ## How to work (rules Will has given, in his words where possible) @@ -29,6 +32,8 @@ Search it for `C21`, `reader review`, `fact re-check`, `conventions.md`, or a pa - Never fix one sentence Will points at in isolation. Reread the whole page and check the claims around it; a bad sentence has always meant more was wrong nearby ("NEVER REWRITE SENTENCES IN ISOLATION. REREAD THE WHOLE DOCUMENT"). - No commentary about the docs inside the docs: no "this page documents", no "each method has a Remarks list", no "examples carry over between pages". Write the reference itself. - Never interleave PostgreSQL and MongoDB sentence by sentence. Give each database its own example and its own paragraph. +- Merging: when Will says "approved" in chat, squash-merge with `gh pr merge N --squash --delete-branch`. Auto-merge is off for the repo. On 2026-09-14 the tool refused a merge on a GitHub approval alone; ask Will. +- The dev server in a worktree needs `pnpm turbo run build --filter=@prisma/eclipse` first and `rm -rf apps/docs/.next`; the launch config is `docs` on port 3105. Verify nav changes by reading the sidebar without clicking anything open, and check the live site with the folder collapsed as a reader sees it. Do not report "it is in the nav" from the presence of text in the HTML. - Resolving CodeRabbit threads: zsh does not word-split `$ids`, so loop with `while read -r id`, and keep the GraphQL query in a file under `wip/` and pass it with `-f query="$(cat file)"`. - Do not paste the readers' reports into pages; extract each agent's final message from its task output with the small script in `c21-orm-client/` (`extract.py` in the previous scratchpad; it prints the last assistant text block of a task JSONL). @@ -45,9 +50,9 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. -## Current task: `orm/contract-authoring/` +## Current task: `orm/data-modeling/` -`orm/reference/` is done (#8260, #8267). Next is item 1 below, one PR per section. Things learned on the reference pages that the fundamentals pages did not show: +`orm/reference/` (#8260, #8267) and `orm/contract-authoring/` (#8271) are done. Next is item 1 below, one PR per section. The contract-authoring pass is the model for a section of explanation pages: `docs/orm-docs-audit/c21-contract-authoring/` at 40c5394e3 on the #8271 branch has its `conventions.md`, `page-conventions.md`, the checker brief (`wip/c21/ca/factcheck-brief.md` in the old worktree; its text is quoted in the transcript), and every report. Copy `page-conventions.md` and adapt it: it bans commentary about the docs, interleaved PostgreSQL and MongoDB sentences, and the words capability, gate, codec, canonical, deterministic, pure, source of truth. Things learned on the reference pages that the fundamentals pages did not show: - On a reference page, readers keep asking for getting-started material (installing, `prisma orm init`, creating tables). Answer with one sentence and a link; do not add it. - From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts on the orm-client page and twenty-six on the other reference pages after four wording rounds, so do not skip it. @@ -56,8 +61,17 @@ Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggreg ## After that, in order -1. `orm/contract-authoring/` (the current task), then `orm/data-modeling/`, `orm/migrations/`, `orm/middleware/`, `orm/extensions/` (20 pages in all), one PR per section. +1. `orm/data-modeling/` (the current task, 3 pages), then `orm/migrations/` (6 pages, where C25 fits), `orm/middleware/`, `orm/extensions/`, one PR per section. 2. C25, `brief-intermediate-contracts.md`: intermediate contracts in data transform migrations. Fits the `orm/migrations/` section pass. 3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. 4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. 5. Briefs waiting for an ORM-side owner: `brief-skill-staleness.md` (D14), D17 in `changes.md`. Add to D14: the scorecard marks `contains`/`startsWith`/`endsWith` as reachable when they are not, and the skill still says N:M includes fail when they work. + +## Open questions from the last session, for Will + +- **SQLite.** `@prisma/orm-sqlite` is published at the same version as the PostgreSQL and MongoDB packages and the source has a SQLite target, but Will's brief for the Supported databases page said everything except PostgreSQL and MongoDB is coming soon, so the page lists SQLite as coming soon and the Release status page no longer names the SQLite library. Will decides whether SQLite gets a status. +- **A JavaScript `Date` codec.** Will and Serhii are discussing one beside the Temporal codecs. There is no real-user evidence logged anywhere in this project; the evidence is D10 in `changes.md` (inferred contracts throw at read time without a global `Temporal`, which Node.js 22 and 24 lack), the raw-queries readers stumbling on `Temporal.Instant` in four rounds, raw SQL rejecting a `Date` outright, MongoDB returning a `Date` while PostgreSQL returns Temporal, and the `DateString` family being the only escape hatch. Discord and GitHub issues were not searched. +- **Implicit many-to-many** is not supported at rc.10 or rc.11: two bare list fields raise `PSL_ORPHANED_BACKRELATION` and the message says to write a join model. The docs say so correctly. Serhii read the upgrade guide as saying many-to-many is unsupported; only the implicit form is. +- **Operating contexts.** The Supported databases page covers only the database section of prisma/orm#25843. Runtimes, frameworks, deployment platforms, and languages have no Prisma ORM 8 page. +- A team-facing summary of the whole project is published at https://claude.ai/code/artifact/3516e640-e939-4c4a-9db6-ff858027cf93 (Will's private artifact). + From 07800c515251d3fbba9139b2fdc944085916c77b Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 14 Sep 2026 16:40:02 +0200 Subject: [PATCH 23/68] docs: absolute paths in the handover Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index 3ac82862bbb..91a995de705 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -8,11 +8,22 @@ Written 2026-09-12, updated 2026-09-14, by the previous agent for the next one. Search the transcript for `C21`, `reader review`, `fact re-check`, `factcheck2`, `conventions.md`, or a page name. It was compacted once; the first user message after compaction carries a summary of everything before it. +## Absolute paths + +The previous agent's worktree is `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7`. It still exists and holds everything below that is not in git: + +- This file: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/design/docs/orm-docs-audit/HANDOVER.md` (the design branch checked out at `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/design/`). +- The rc.10 source checkout: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/prisma-src/` (a worktree of `/Users/wmadden/Projects/prisma/prisma` at `cfccb09be2`). +- The contract-authoring briefs: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck-brief.md`, `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck2-brief.md`, `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/fixer-brief.md`, and the PR body `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/pr-body.md`. The reference-section briefs are beside them in `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/`. +- The report extractor: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/extract.py`. +- The reports of every round, as files: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/r1/` to `r4/` and `fc2/` hold the page copies; the reader and checker reports are in git at commit 40c5394e3 of `docs/orm8-plain-language-contract-authoring` under `docs/orm-docs-audit/c21-contract-authoring/`, and at 13f900ad2 of `docs/orm8-plain-language-orm-reference` under `docs/orm-docs-audit/c21-orm-reference/`. Read them with `git show :` from any worktree of prisma/web. +- The docs-reader-review skill: `.claude/skills/docs-reader-review/` at the root of any prisma/web checkout, on `main`. + ## Where things are - `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). - Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. -- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5. +- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5 under `docs/orm-docs-audit/c21-orm-client/`. - PR #8271 (branch `docs/orm8-plain-language-contract-authoring`) is C21 on `orm/contract-authoring/` (the data contract, PSL, TypeScript builder, the two emitted files, and the page now titled Supported database features), plus three things Will asked for while it ran: the Supported databases page at `/prisma-orm/supported-databases` (PostgreSQL release candidate, MongoDB early access, everything else coming soon; it replaces the database section of prisma/orm#25843), the upgrade guides linked from the ORM section's Introduction and the v7 guides nav, and a sidebar fix (folders in the version-filtered Guides tree never opened for their own page; they now match by id). It is approved on GitHub and green; the agent could not merge it because the tool refused a merge, so Will merges it. The reports are in the branch history at 40c5394e3. The plain-language checker (`check-plain.sh`) now skips link targets, pinned anchors, `href` attributes, and the front-matter `url` line. - PR #8267 (branch `docs/orm8-plain-language-orm-reference`) is C21 on the rest of `orm/reference/` (`sql-query-builder`, `raw-queries`, `pipeline-builder`, `transactions-and-runtime`, `index`), merged 2026-09-13: a fact check against rc.10, four reader rounds, a final fact re-check, and CodeRabbit's six comments. The reports are in the branch history at 13f900ad2. The error reference page is generated from prisma/orm and out of scope. - The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. @@ -35,7 +46,7 @@ Search the transcript for `C21`, `reader review`, `fact re-check`, `factcheck2`, - Merging: when Will says "approved" in chat, squash-merge with `gh pr merge N --squash --delete-branch`. Auto-merge is off for the repo. On 2026-09-14 the tool refused a merge on a GitHub approval alone; ask Will. - The dev server in a worktree needs `pnpm turbo run build --filter=@prisma/eclipse` first and `rm -rf apps/docs/.next`; the launch config is `docs` on port 3105. Verify nav changes by reading the sidebar without clicking anything open, and check the live site with the folder collapsed as a reader sees it. Do not report "it is in the nav" from the presence of text in the HTML. - Resolving CodeRabbit threads: zsh does not word-split `$ids`, so loop with `while read -r id`, and keep the GraphQL query in a file under `wip/` and pass it with `-f query="$(cat file)"`. -- Do not paste the readers' reports into pages; extract each agent's final message from its task output with the small script in `c21-orm-client/` (`extract.py` in the previous scratchpad; it prints the last assistant text block of a task JSONL). +- Do not paste the readers' reports into pages; extract each agent's final message from its task output with `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/extract.py` (usage: `python3 extract.py `; it prints the last assistant text block of a task JSONL). ## The C21 method (what worked on the fundamentals pages) @@ -43,7 +54,7 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: 1. Run `scripts/check-plain.sh` and fix hits. 2. Dispatch a fresh Opus reader with `references/reader-persona.md` verbatim and only the page (a long page in slices by `##` heading, 400 to 700 lines each). Save its report with the extract script. -3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; in `c21-orm-client/` on #8260), the page's own conventions file if any, the report, and the source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. +3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; the latest is `docs/orm-docs-audit/c21-contract-authoring/conventions.md` at commit 40c5394e3), the page's own conventions file if any, the report, and the source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. 4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a "no longer than it is now" budget, because pages grow and readers then trip on the additions. 5. Fact re-check by a separate Opus agent against the source, claim by claim, before the PR. On the fundamentals pages this caught seven real errors that the wording rounds had introduced or left standing. Do not skip it. 6. Commit each round. Link check: `cd apps/docs && node_modules/.bin/fumadocs-mdx && node_modules/.bin/tsx ./scripts/lint-links.ts`. Spelling: `node_modules/.bin/cspell "content/docs/orm/**/*.mdx"` (random sample ids fail it; use `cuid2000...` style). Revert any `meta.json` the formatter touches. @@ -52,7 +63,7 @@ Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggreg ## Current task: `orm/data-modeling/` -`orm/reference/` (#8260, #8267) and `orm/contract-authoring/` (#8271) are done. Next is item 1 below, one PR per section. The contract-authoring pass is the model for a section of explanation pages: `docs/orm-docs-audit/c21-contract-authoring/` at 40c5394e3 on the #8271 branch has its `conventions.md`, `page-conventions.md`, the checker brief (`wip/c21/ca/factcheck-brief.md` in the old worktree; its text is quoted in the transcript), and every report. Copy `page-conventions.md` and adapt it: it bans commentary about the docs, interleaved PostgreSQL and MongoDB sentences, and the words capability, gate, codec, canonical, deterministic, pure, source of truth. Things learned on the reference pages that the fundamentals pages did not show: +`orm/reference/` (#8260, #8267) and `orm/contract-authoring/` (#8271) are done. Next is item 1 below, one PR per section. The contract-authoring pass is the model for a section of explanation pages: `docs/orm-docs-audit/c21-contract-authoring/` at 40c5394e3 on the #8271 branch has its `conventions.md`, `page-conventions.md`, the checker brief (`/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck-brief.md`), and every report. Copy `page-conventions.md` and adapt it: it bans commentary about the docs, interleaved PostgreSQL and MongoDB sentences, and the words capability, gate, codec, canonical, deterministic, pure, source of truth. Things learned on the reference pages that the fundamentals pages did not show: - On a reference page, readers keep asking for getting-started material (installing, `prisma orm init`, creating tables). Answer with one sentence and a link; do not add it. - From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts on the orm-client page and twenty-six on the other reference pages after four wording rounds, so do not skip it. From 4613d6f1301b72a2d4d86c3ab3abac81ea3a4fa4 Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 15 Sep 2026 15:59:01 +0200 Subject: [PATCH 24/68] docs: handover after the data-modeling section Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index 91a995de705..b5647ff9569 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -1,10 +1,12 @@ # Handover: Prisma ORM 8 docs audit and plain-language pass -Written 2026-09-12, updated 2026-09-14, by the previous agent for the next one. Read this first, then `changes.md` in this directory. +Written 2026-09-12, updated 2026-09-15, by the previous agent for the next one. Read this first, then `changes.md` in this directory. ## Transcript of the previous session -`/Users/wmadden/.claude/projects/-Users-wmadden-Projects-prisma-web--claude-worktrees-error-reference-follow-ups-81a8e7/29b9a58b-bb9f-48f4-8639-597b84cf76f8.jsonl` (about 15 MB; 2026-09-13 to 2026-09-14, the orm/reference and contract-authoring passes). If your sandbox cannot read it, tell Will straight away and wait: he will copy it into your worktree. Do not continue without it. The session before that one is at `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` (the audit and the fundamentals pass). +The most recent session (2026-09-14 to 2026-09-15, the data-modeling pass and the Supported databases consolidation) is `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-pr-conflicts-review-fb93f7/ce65cd59-a425-4754-9e75-9f9f740b388b.jsonl` (about 6 MB). Its worktree is `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7`, which holds `wip/c21/dm/` (the data-modeling briefs, page copies per round, and `extract.py` in `wip/c21/`), `wip/prisma-src/` (a plain `git archive` export of rc.10, not a worktree, because that session only had read access to `/Users/wmadden/Projects/prisma/prisma`), `wip/orm/` (a shallow clone of prisma/orm through the bot remote), and `wip/migrations-before-queries.md` (a brief for the ORM team, see below). Note that the two transcripts belong to two macOS users, `will` and `wmadden`, who are both Will; if a path is unreadable, tell Will and he grants access with an ACL. + +The session before that is `/Users/wmadden/.claude/projects/-Users-wmadden-Projects-prisma-web--claude-worktrees-error-reference-follow-ups-81a8e7/29b9a58b-bb9f-48f4-8639-597b84cf76f8.jsonl` (about 15 MB; 2026-09-13 to 2026-09-14, the orm/reference and contract-authoring passes). If your sandbox cannot read it, tell Will straight away and wait: he will copy it into your worktree. Do not continue without it. The session before that one is at `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` (the audit and the fundamentals pass). Search the transcript for `C21`, `reader review`, `fact re-check`, `factcheck2`, `conventions.md`, or a page name. It was compacted once; the first user message after compaction carries a summary of everything before it. @@ -26,8 +28,13 @@ The previous agent's worktree is `/Users/wmadden/Projects/prisma/web/.claude/wor - PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5 under `docs/orm-docs-audit/c21-orm-client/`. - PR #8271 (branch `docs/orm8-plain-language-contract-authoring`) is C21 on `orm/contract-authoring/` (the data contract, PSL, TypeScript builder, the two emitted files, and the page now titled Supported database features), plus three things Will asked for while it ran: the Supported databases page at `/prisma-orm/supported-databases` (PostgreSQL release candidate, MongoDB early access, everything else coming soon; it replaces the database section of prisma/orm#25843), the upgrade guides linked from the ORM section's Introduction and the v7 guides nav, and a sidebar fix (folders in the version-filtered Guides tree never opened for their own page; they now match by id). It is approved on GitHub and green; the agent could not merge it because the tool refused a merge, so Will merges it. The reports are in the branch history at 40c5394e3. The plain-language checker (`check-plain.sh`) now skips link targets, pinned anchors, `href` attributes, and the front-matter `url` line. - PR #8267 (branch `docs/orm8-plain-language-orm-reference`) is C21 on the rest of `orm/reference/` (`sql-query-builder`, `raw-queries`, `pipeline-builder`, `transactions-and-runtime`, `index`), merged 2026-09-13: a fact check against rc.10, four reader rounds, a final fact re-check, and CodeRabbit's six comments. The reports are in the branch history at 13f900ad2. The error reference page is generated from prisma/orm and out of scope. +- PR #8279 (branch `docs/orm8-plain-language-data-modeling`) is C21 on `orm/data-modeling/` (`index`, `relational-databases`, `mongodb`), merged 2026-09-15: a fact check against rc.10, four reader rounds, a final fact re-check (five drifts), seven CodeRabbit threads. The reports, `conventions.md`, and `page-conventions.md` are in the branch history at 19138ba09. The same PR moved Release status and Supported databases from the Getting Started tree into the ORM section (`/orm/release-status`, `/orm/supported-databases`, old URLs redirect, Getting Started keeps link entries), and merged the older `orm/reference/supported-databases` page into `/orm/supported-databases` (Ankur's feature table, hosted-provider table, and community-package note kept; SQLite is Experimental with `@prisma/orm-sqlite`, MySQL is coming soon and planned next, MongoDB is early access; Will decided all three). +- Two things learned on the data-modeling pages: on MongoDB, `@map` renames the field in TypeScript as well as in the database, so the primary key is always `_id` in code. That is filed as a bug, TML-3247 on the Terminal team in Linear, related to TML-2961. And the `prisma-8` skill's `contract.md` says the default referential action is `Restrict`; the code writes no clause at all. Add that to D14. +- prisma/orm#30296 (branch `docs/readme-v7-support-window`) fixes the README, CONTRIBUTING, and SECURITY to say Prisma 7 gets bug fixes and security updates for eighteen months after `8.0.0` final, matching the Release status page. Approved, auto-merge armed behind the merge queue as of 2026-09-15. +- prisma/orm#30287 (open) makes `schema.prisma` a Prisma ORM 8 contract source (`prisma7Schema('prisma/schema.prisma')` in `prisma.config.ts`), so a Prisma 7 app runs `contract emit`, `db sign`, and `db verify` on the file it already has, with zero findings. When it ships (rc.12), the upgrade guide and Coming from Prisma ORM 7 are wrong where they describe `contract infer` plus hand edits, and the migrations section pass should know it is coming. `wip/migrations-before-queries.md` in the worktree above is the brief Will shared with the team on the route it enables (hand migrations to Prisma ORM 8 first, keep Prisma 7 queries); it lists what is still missing, including a `migrations: false` option for the Prisma 7 config. - The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. - The published `prisma` package (8.0.0-rc.15 on 2026-09-14) exports `./config`, so the docs import `definePrismaConfig` from `prisma/config`. The rc.10 source tree only has `@prisma/cli-engine` and every fact checker "corrects" it; revert them. Check with `npm view prisma@latest exports`. +- pnpm on Will's machine (user `will`) could not switch to the pinned 12.3.4 because its managed install under `~/Library/pnpm/.tools/pnpm/12.3.4` was a placeholder; running that package's `install.js` fixed it. If `pnpm` prints `ENOEXEC`, that is the cause. - The design branch is checked out in the previous worktree at `wip/design/` (a git worktree under the gitignored `wip/`). In a fresh worktree, `git worktree add wip/design docs/orm8-docs-audit-design` after `git fetch bot` and `git branch -f docs/orm8-docs-audit-design bot/docs/orm8-docs-audit-design`. ## How to work (rules Will has given, in his words where possible) @@ -61,18 +68,19 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. -## Current task: `orm/data-modeling/` +## Current task: `orm/migrations/` -`orm/reference/` (#8260, #8267) and `orm/contract-authoring/` (#8271) are done. Next is item 1 below, one PR per section. The contract-authoring pass is the model for a section of explanation pages: `docs/orm-docs-audit/c21-contract-authoring/` at 40c5394e3 on the #8271 branch has its `conventions.md`, `page-conventions.md`, the checker brief (`/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck-brief.md`), and every report. Copy `page-conventions.md` and adapt it: it bans commentary about the docs, interleaved PostgreSQL and MongoDB sentences, and the words capability, gate, codec, canonical, deterministic, pure, source of truth. Things learned on the reference pages that the fundamentals pages did not show: +`orm/reference/` (#8260, #8267), `orm/contract-authoring/` (#8271), and `orm/data-modeling/` (#8279) are done. Next is `orm/migrations/` (six pages: `how-migrations-work`, `generating-a-migration`, `applying-a-migration`, `editing-a-migration`, `rollbacks-and-recovery`, `the-migration-graph`), one PR for the section, where C25 (intermediate contracts, `brief-intermediate-contracts.md`) fits. The data-modeling pass is the closest model: `docs/orm-docs-audit/c21-data-modeling/` at 19138ba09 on the #8279 branch has its `conventions.md`, `page-conventions.md`, and every report, and the briefs are at `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/dm/` (`factcheck-brief.md`, `fixer-brief.md`, `factcheck2-brief.md`). Copy `page-conventions.md` and adapt it. Things learned on the data-modeling pages: -- On a reference page, readers keep asking for getting-started material (installing, `prisma orm init`, creating tables). Answer with one sentence and a link; do not add it. -- From round three on, fixers add answers and readers then trip on the additions. Give every fixer from round three a "no longer than now" budget, and tell round four's fixers to prefer cutting. The final fact re-check found thirteen drifts on the orm-client page and twenty-six on the other reference pages after four wording rounds, so do not skip it. -- Fact checkers infer motives and defaults the source does not state (why a helper was renamed, what a driver returns). Trim to what a source line says. -- When a section's pages run in parallel, a `page-conventions.md` beside `conventions.md` keeps them agreeing on setup lines, the example schema, and phrasing such as "PostgreSQL only". +- Readers ask for setup material (the config file, `prisma orm init`, the command loop) in every round. Answer with one sentence and a link each time; do not add a setup section. The one exception that paid off: naming the command sequence once, in a Next steps bullet, without flags (`apps/docs/CLAUDE.md` forbids flags on guide pages, and CodeRabbit enforces it). +- Error codes are noise to a first reader. Keep the one a Prisma ORM 7 reader will hit from habit (`PSL_ORPHANED_BACKRELATION`) and state the rule before the code; cut the rest. +- Prisma ORM 7 comparisons ("Prisma ORM 7 called this the back-relation") are facts the rc.10 source cannot confirm. State them as Prisma ORM 7 facts and tell the final checker so. +- On the migrations pages specifically: the `db` ref, `migrate dev` versus `db migrate`, `db sign` versus `db init`, and what `migration plan` writes (a directory, not a file) are the claims that drifted on other pages. Check them first. +- From round three on, no-growth budgets and "prefer cutting". The section ended seven lines shorter than it started and the final re-check still found five drifts. ## After that, in order -1. `orm/data-modeling/` (the current task, 3 pages), then `orm/migrations/` (6 pages, where C25 fits), `orm/middleware/`, `orm/extensions/`, one PR per section. +1. `orm/migrations/` (the current task, 6 pages, where C25 fits), then `orm/middleware/`, `orm/extensions/`, one PR per section. 2. C25, `brief-intermediate-contracts.md`: intermediate contracts in data transform migrations. Fits the `orm/migrations/` section pass. 3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. 4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. @@ -80,7 +88,11 @@ Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggreg ## Open questions from the last session, for Will -- **SQLite.** `@prisma/orm-sqlite` is published at the same version as the PostgreSQL and MongoDB packages and the source has a SQLite target, but Will's brief for the Supported databases page said everything except PostgreSQL and MongoDB is coming soon, so the page lists SQLite as coming soon and the Release status page no longer names the SQLite library. Will decides whether SQLite gets a status. +- **SQLite** is decided: Experimental, with `@prisma/orm-sqlite`, on the Supported databases page. The Release status page still does not name the SQLite library; make them agree when that page is next touched. +- **Default referential action.** When `onDelete` and `onUpdate` are both omitted, Prisma ORM writes no clause. The relational data-modeling page says "the database decides" and does not name PostgreSQL's `NO ACTION`. Will has not said whether to name it. +- **MongoDB before the first write.** The skill says `db migrate` writes a marker document in `_prisma_migrations`, but no marker check was found in the MongoDB runtime, so no page says whether an unmigrated database rejects a write. +- **`namespace` blocks** exist in the PSL interpreter (`interpreter.ts:197-231`) and no page documents them; the relational page mentions them in one clause without a link. +- **Node.js floor for `Temporal`.** The source and the raw-queries page say 26.8.2; `coming-from-prisma-orm-7.mdx` line 65 says "26 and later". Fix the latter when that page is next touched. - **A JavaScript `Date` codec.** Will and Serhii are discussing one beside the Temporal codecs. There is no real-user evidence logged anywhere in this project; the evidence is D10 in `changes.md` (inferred contracts throw at read time without a global `Temporal`, which Node.js 22 and 24 lack), the raw-queries readers stumbling on `Temporal.Instant` in four rounds, raw SQL rejecting a `Date` outright, MongoDB returning a `Date` while PostgreSQL returns Temporal, and the `DateString` family being the only escape hatch. Discord and GitHub issues were not searched. - **Implicit many-to-many** is not supported at rc.10 or rc.11: two bare list fields raise `PSL_ORPHANED_BACKRELATION` and the message says to write a join model. The docs say so correctly. Serhii read the upgrade guide as saying many-to-many is unsupported; only the implicit form is. - **Operating contexts.** The Supported databases page covers only the database section of prisma/orm#25843. Runtimes, frameworks, deployment platforms, and languages have no Prisma ORM 8 page. From dc7b37f2b1955887191de22fa179937c313c49f4 Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 15 Sep 2026 18:55:56 +0200 Subject: [PATCH 25/68] docs: handover after the migrations section Co-Authored-By: Claude Opus 5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 71 ++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index b5647ff9569..b570122872e 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -4,7 +4,7 @@ Written 2026-09-12, updated 2026-09-15, by the previous agent for the next one. ## Transcript of the previous session -The most recent session (2026-09-14 to 2026-09-15, the data-modeling pass and the Supported databases consolidation) is `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-pr-conflicts-review-fb93f7/ce65cd59-a425-4754-9e75-9f9f740b388b.jsonl` (about 6 MB). Its worktree is `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7`, which holds `wip/c21/dm/` (the data-modeling briefs, page copies per round, and `extract.py` in `wip/c21/`), `wip/prisma-src/` (a plain `git archive` export of rc.10, not a worktree, because that session only had read access to `/Users/wmadden/Projects/prisma/prisma`), `wip/orm/` (a shallow clone of prisma/orm through the bot remote), and `wip/migrations-before-queries.md` (a brief for the ORM team, see below). Note that the two transcripts belong to two macOS users, `will` and `wmadden`, who are both Will; if a path is unreadable, tell Will and he grants access with an ACL. +The most recent session (2026-09-14 to 2026-09-15, the data-modeling pass, the Supported databases consolidation, and the migrations pass) is `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-pr-conflicts-review-fb93f7/ce65cd59-a425-4754-9e75-9f9f740b388b.jsonl` (about 6 MB). Its worktree is `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7`, which holds `wip/c21/dm/` and `wip/c21/mig/` (the data-modeling and migrations briefs, shared answers, page copies per round, and reports; `extract.py` is in `wip/c21/`), `wip/prisma-src-rc11/` (a plain export of prisma/orm at rc.11, `ff47560c9f`), `wip/prisma-src/` (a plain `git archive` export of rc.10, not a worktree, because that session only had read access to `/Users/wmadden/Projects/prisma/prisma`), `wip/orm/` (a shallow clone of prisma/orm through the bot remote), and `wip/migrations-before-queries.md` (a brief for the ORM team, see below). Note that the two transcripts belong to two macOS users, `will` and `wmadden`, who are both Will; if a path is unreadable, tell Will and he grants access with an ACL. The session before that is `/Users/wmadden/.claude/projects/-Users-wmadden-Projects-prisma-web--claude-worktrees-error-reference-follow-ups-81a8e7/29b9a58b-bb9f-48f4-8639-597b84cf76f8.jsonl` (about 15 MB; 2026-09-13 to 2026-09-14, the orm/reference and contract-authoring passes). If your sandbox cannot read it, tell Will straight away and wait: he will copy it into your worktree. Do not continue without it. The session before that one is at `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` (the audit and the fundamentals pass). @@ -32,7 +32,7 @@ The previous agent's worktree is `/Users/wmadden/Projects/prisma/web/.claude/wor - Two things learned on the data-modeling pages: on MongoDB, `@map` renames the field in TypeScript as well as in the database, so the primary key is always `_id` in code. That is filed as a bug, TML-3247 on the Terminal team in Linear, related to TML-2961. And the `prisma-8` skill's `contract.md` says the default referential action is `Restrict`; the code writes no clause at all. Add that to D14. - prisma/orm#30296 (branch `docs/readme-v7-support-window`) fixes the README, CONTRIBUTING, and SECURITY to say Prisma 7 gets bug fixes and security updates for eighteen months after `8.0.0` final, matching the Release status page. Approved, auto-merge armed behind the merge queue as of 2026-09-15. - prisma/orm#30287 (open) makes `schema.prisma` a Prisma ORM 8 contract source (`prisma7Schema('prisma/schema.prisma')` in `prisma.config.ts`), so a Prisma 7 app runs `contract emit`, `db sign`, and `db verify` on the file it already has, with zero findings. When it ships (rc.12), the upgrade guide and Coming from Prisma ORM 7 are wrong where they describe `contract infer` plus hand edits, and the migrations section pass should know it is coming. `wip/migrations-before-queries.md` in the worktree above is the brief Will shared with the team on the route it enables (hand migrations to Prisma ORM 8 first, keep Prisma 7 queries); it lists what is still missing, including a `migrations: false` option for the Prisma 7 config. -- The Prisma ORM 8 source used for every fact check is `prisma/orm` at `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. +- The Prisma ORM 8 source for the migrations pass was `prisma/orm` at `8.0.0-rc.11` (`ff47560c9f`), exported at `wip/prisma-src-rc11/` in the worktree above; use rc.11 for the next section unless Will says otherwise. Earlier sections used `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. - The published `prisma` package (8.0.0-rc.15 on 2026-09-14) exports `./config`, so the docs import `definePrismaConfig` from `prisma/config`. The rc.10 source tree only has `@prisma/cli-engine` and every fact checker "corrects" it; revert them. Check with `npm view prisma@latest exports`. - pnpm on Will's machine (user `will`) could not switch to the pinned 12.3.4 because its managed install under `~/Library/pnpm/.tools/pnpm/12.3.4` was a placeholder; running that package's `install.js` fixed it. If `pnpm` prints `ENOEXEC`, that is the cause. - The design branch is checked out in the previous worktree at `wip/design/` (a git worktree under the gitignored `wip/`). In a fresh worktree, `git worktree add wip/design docs/orm8-docs-audit-design` after `git fetch bot` and `git branch -f docs/orm8-docs-audit-design bot/docs/orm8-docs-audit-design`. @@ -62,26 +62,59 @@ The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: 1. Run `scripts/check-plain.sh` and fix hits. 2. Dispatch a fresh Opus reader with `references/reader-persona.md` verbatim and only the page (a long page in slices by `##` heading, 400 to 700 lines each). Save its report with the extract script. 3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; the latest is `docs/orm-docs-audit/c21-contract-authoring/conventions.md` at commit 40c5394e3), the page's own conventions file if any, the report, and the source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. -4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a "no longer than it is now" budget, because pages grow and readers then trip on the additions. +4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a word budget counted with `wc -w` (not lines: on the migrations pages fixers met line budgets by writing longer lines), because pages grow and readers then trip on the additions. 5. Fact re-check by a separate Opus agent against the source, claim by claim, before the PR. On the fundamentals pages this caught seven real errors that the wording rounds had introduced or left standing. Do not skip it. 6. Commit each round. Link check: `cd apps/docs && node_modules/.bin/fumadocs-mdx && node_modules/.bin/tsx ./scripts/lint-links.ts`. Spelling: `node_modules/.bin/cspell "content/docs/orm/**/*.mdx"` (random sample ids fail it; use `cuid2000...` style). Revert any `meta.json` the formatter touches. Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. -## Current task: `orm/migrations/` - -`orm/reference/` (#8260, #8267), `orm/contract-authoring/` (#8271), and `orm/data-modeling/` (#8279) are done. Next is `orm/migrations/` (six pages: `how-migrations-work`, `generating-a-migration`, `applying-a-migration`, `editing-a-migration`, `rollbacks-and-recovery`, `the-migration-graph`), one PR for the section, where C25 (intermediate contracts, `brief-intermediate-contracts.md`) fits. The data-modeling pass is the closest model: `docs/orm-docs-audit/c21-data-modeling/` at 19138ba09 on the #8279 branch has its `conventions.md`, `page-conventions.md`, and every report, and the briefs are at `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/dm/` (`factcheck-brief.md`, `fixer-brief.md`, `factcheck2-brief.md`). Copy `page-conventions.md` and adapt it. Things learned on the data-modeling pages: - -- Readers ask for setup material (the config file, `prisma orm init`, the command loop) in every round. Answer with one sentence and a link each time; do not add a setup section. The one exception that paid off: naming the command sequence once, in a Next steps bullet, without flags (`apps/docs/CLAUDE.md` forbids flags on guide pages, and CodeRabbit enforces it). -- Error codes are noise to a first reader. Keep the one a Prisma ORM 7 reader will hit from habit (`PSL_ORPHANED_BACKRELATION`) and state the rule before the code; cut the rest. -- Prisma ORM 7 comparisons ("Prisma ORM 7 called this the back-relation") are facts the rc.10 source cannot confirm. State them as Prisma ORM 7 facts and tell the final checker so. -- On the migrations pages specifically: the `db` ref, `migrate dev` versus `db migrate`, `db sign` versus `db init`, and what `migration plan` writes (a directory, not a file) are the claims that drifted on other pages. Check them first. -- From round three on, no-growth budgets and "prefer cutting". The section ended seven lines shorter than it started and the final re-check still found five drifts. +## Done: `orm/migrations/` (PR #8281) + +PR #8281 (branch `docs/orm8-plain-language-migrations`) is C21 on the six `orm/migrations/` pages, plus C25, a new section in Editing a migration: "When a backfill reads a column the migration removes". Open as of 2026-09-15. + +The pass ran these steps: +1. A banned-term pass and a fact check against rc.11. +2. A real run of the pages' commands with `prisma` 8.0.0-rc.15 and a local PostgreSQL. +3. Four reader rounds. +4. A final fact re-check, which made 28 corrections. + +The briefs, shared answers, page copies per round, and every report are in `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/mig/`. None is in the PR, because Will said not to add dispatches to PRs. The most useful files there: +- `round2-notes.md`, which holds every final-check item and its resolution. +- `round1-shared-answers.md` to `round4-shared-answers.md`, which are sourced facts about migrations. +- `real-run-transcript.md`. +- `notes-for-handover.md`, which lists the product bugs. +- `fc2-drifts.md`, what the final check corrected. + +Things learned on this pass: +- **Budget in words, not lines.** Round three's fixers met line budgets by writing longer lines, and four pages grew by up to 13%. +- **Run the commands.** The real run caught several things that reading the source did not: + - a wrong rollback end state; + - an `updatedAt` column makes a backfill impossible to apply; + - the unfilled-placeholder failure was blamed on the wrong cause; + - the literal `{bin}` in CLI hints; + - `node migration.ts` works only from the project root. + + Do the same for any section whose pages show commands. +- **Shared answers every round.** Readers on all six pages asked the same questions. One shared-answers file per round kept the pages consistent. When a fact turns up while fixers run, send it to the affected fixer. +- **Cross-check one checker's finding on the other pages.** The How migrations work checker found that a MongoDB re-run stops at a collection the failed run created. Three other pages said the opposite, and their checkers had confirmed it. +- **Length.** The section went from 9997 words on `main` to 13749. Most of the growth answers questions readers asked every round, and C25 adds about 60 lines. Will has not said whether he wants a cutting round. ## After that, in order -1. `orm/migrations/` (the current task, 6 pages, where C25 fits), then `orm/middleware/`, `orm/extensions/`, one PR per section. -2. C25, `brief-intermediate-contracts.md`: intermediate contracts in data transform migrations. Fits the `orm/migrations/` section pass. +1. Handle review on #8281 (the migrations section), then `orm/middleware/`, `orm/extensions/`, one PR per section. +2. File the product bugs from the migrations pass, listed in `wip/c21/mig/notes-for-handover.md`, wherever Will decides. The list: + - `{bin}` is never replaced. + - Planner-written migrations don't type-check. + - An `updatedAt` backfill can never be applied. + - `migration new --from` writes a no-op migration that breaks planning. + - `node migration.ts` works only from the project root. + - `contract emit --config` misreports its output file names. + - The `db migrate` summary count is off. + - `npx prisma dev` needs an entry argument. + - `migration log` sorts rows applied in the same second by name. + - A MongoDB re-run after a partial failure stops at a collection the failed run created. + + Outside the section: `studio/prisma-next.mdx` line 112 describes `migration plan` with no `db` ref wrongly. Also add to D14: the `prisma-8` skill says an un-recompiled `migration.ts` edit causes a hash mismatch, and it does not. 3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. 4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. 5. Briefs waiting for an ORM-side owner: `brief-skill-staleness.md` (D14), D17 in `changes.md`. Add to D14: the scorecard marks `contains`/`startsWith`/`endsWith` as reachable when they are not, and the skill still says N:M includes fail when they work. @@ -97,4 +130,12 @@ Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggreg - **Implicit many-to-many** is not supported at rc.10 or rc.11: two bare list fields raise `PSL_ORPHANED_BACKRELATION` and the message says to write a join model. The docs say so correctly. Serhii read the upgrade guide as saying many-to-many is unsupported; only the implicit form is. - **Operating contexts.** The Supported databases page covers only the database section of prisma/orm#25843. Runtimes, frameworks, deployment platforms, and languages have no Prisma ORM 8 page. - A team-facing summary of the whole project is published at https://claude.ai/code/artifact/3516e640-e939-4c4a-9db6-ff858027cf93 (Will's private artifact). - +- **Migrations pass: committing refs.** Should `migrations/app/refs/db.json` be committed? The same question applies to a `prod` ref. The source is silent, and no migrations page says. +- **Migrations pass: `--advance-ref db`.** Why is it not the default in development? The source gives no reason. +- **Migrations pass: the `prod` ref.** Does it mean what is deployed or what should be deployed, and should deploys move it? +- **Migrations pass: merge workflow.** The graph page shows the diamond from the e2e test, with two merge migrations after both branches merge. `skills/prisma-8/references/migration-review.md` 116-130 recommends rebasing and replanning instead. +- **Migrations pass: adoption order.** Generating a migration says sign, then plan, then migrate. The PostgreSQL upgrade guide says plan a baseline, sign, then set the `db` ref. Both work. +- **Migrations pass: `db sign` failing on production.** Its error suggests running `db update` and then signing again. The pages do not recommend that on production. +- **Migrations pass: Discord.** Should the pages name the `#prisma-next` channel? They now say only "ask on Discord". +- **Migrations pass: Node.js version.** The published `prisma` 8.0.0-rc.15 declares `node >=22.18.0`, but the rc.11 monorepo declares `>=24`. The pages say 22.18. +- **Migrations pass: concurrent PostgreSQL runs.** After waiting for the lock, the second run fails with a marker mismatch. The page says only that one waits for the other. From a5eeb8f5c0ecfcf4b38df1a7ca9b9adbef8b68d8 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 16 Sep 2026 10:09:20 +0200 Subject: [PATCH 26/68] docs(audit): record the migrations cutting round and terminology decisions Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index b570122872e..ad61ededba6 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -77,6 +77,7 @@ The pass ran these steps: 2. A real run of the pages' commands with `prisma` 8.0.0-rc.15 and a local PostgreSQL. 3. Four reader rounds. 4. A final fact re-check, which made 28 corrections. +5. A language review by the operator, then a cutting round: one Opus fixer per page, a word ceiling, and the rule that facts stay fixed. Brief in `wip/c21/mig/cut-brief.md`. The briefs, shared answers, page copies per round, and every report are in `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/mig/`. None is in the PR, because Will said not to add dispatches to PRs. The most useful files there: - `round2-notes.md`, which holds every final-check item and its resolution. @@ -97,7 +98,9 @@ Things learned on this pass: Do the same for any section whose pages show commands. - **Shared answers every round.** Readers on all six pages asked the same questions. One shared-answers file per round kept the pages consistent. When a fact turns up while fixers run, send it to the affected fixer. - **Cross-check one checker's finding on the other pages.** The How migrations work checker found that a MongoDB re-run stops at a collection the failed run created. Three other pages said the opposite, and their checkers had confirmed it. -- **Length.** The section went from 9997 words on `main` to 13749. Most of the growth answers questions readers asked every round, and C25 adds about 60 lines. Will has not said whether he wants a cutting round. +- **Reader rounds bloat pages.** Each round answered readers by adding sentences, and each page ended up defining every term as if the reader arrived cold. The same eight facts were restated on every page. Plan a cutting round after the reader rounds, with the rule: define each term once per page at first use, link elsewhere, facts stay fixed. Fixers refuse ceilings they can only meet by deleting facts, which is right, so set ceilings as ceilings and accept the report. +- **Length.** The section went from 9997 words on `main` to 13749 after the reader rounds and 12606 after the cutting round. +- **Terminology.** Will banned movement metaphors for migrations (the database moves, the marker moves, the ref moves, the database is behind or catches up, where the database is). Say what a command changes and what the database ends up matching. "Database schema" is fine; only PostgreSQL namespaces make it ambiguous, and Will rejected reserving the word. Rules in `.claude/skills/docs-reader-review/references/banned-terms.md`, "Migration vocabulary". ## After that, in order From 414eaa85cd78be8415b07ca7dc41bfe1aebb6cfc Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 16 Sep 2026 10:25:33 +0200 Subject: [PATCH 27/68] docs(audit): record the explanation round and the explain-not-state rule Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md index ad61ededba6..2be939ce2b5 100644 --- a/docs/orm-docs-audit/HANDOVER.md +++ b/docs/orm-docs-audit/HANDOVER.md @@ -78,6 +78,7 @@ The pass ran these steps: 3. Four reader rounds. 4. A final fact re-check, which made 28 corrections. 5. A language review by the operator, then a cutting round: one Opus fixer per page, a word ceiling, and the rule that facts stay fixed. Brief in `wip/c21/mig/cut-brief.md`. +6. An explanation round after Will rejected the prose: one Opus fixer per page, no ceiling, rewriting against `.claude/skills/docs-reader-review/references/explain-not-state.md`. Brief in `wip/c21/mig/explain-brief.md`. The briefs, shared answers, page copies per round, and every report are in `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/mig/`. None is in the PR, because Will said not to add dispatches to PRs. The most useful files there: - `round2-notes.md`, which holds every final-check item and its resolution. @@ -99,7 +100,8 @@ Things learned on this pass: - **Shared answers every round.** Readers on all six pages asked the same questions. One shared-answers file per round kept the pages consistent. When a fact turns up while fixers run, send it to the affected fixer. - **Cross-check one checker's finding on the other pages.** The How migrations work checker found that a MongoDB re-run stops at a collection the failed run created. Three other pages said the opposite, and their checkers had confirmed it. - **Reader rounds bloat pages.** Each round answered readers by adding sentences, and each page ended up defining every term as if the reader arrived cold. The same eight facts were restated on every page. Plan a cutting round after the reader rounds, with the rule: define each term once per page at first use, link elsewhere, facts stay fixed. Fixers refuse ceilings they can only meet by deleting facts, which is right, so set ceilings as ceilings and accept the report. -- **Length.** The section went from 9997 words on `main` to 13749 after the reader rounds and 12606 after the cutting round. +- **Explain, do not state.** Will's biggest correction on this pass. The pages stated facts in short correct sentences and never said what they meant for the reader, with counting lead-ins ("Four things change it:") and fragment openers ("One name is special."). His model rewrite and the rules are in `.claude/skills/docs-reader-review/references/explain-not-state.md`, and `check-staccato.py` now flags the mechanical signs. Run that reference on every future section before the reader rounds, not after. Word ceilings make this habit worse: use them only against repetition. +- **Length.** The section went from 9997 words on `main` to 13749 after the reader rounds, 12606 after the cutting round, and 15875 after the explanation round. Will has not objected to the length, only to the prose. - **Terminology.** Will banned movement metaphors for migrations (the database moves, the marker moves, the ref moves, the database is behind or catches up, where the database is). Say what a command changes and what the database ends up matching. "Database schema" is fine; only PostgreSQL namespaces make it ambiguous, and Will rejected reserving the word. Rules in `.claude/skills/docs-reader-review/references/banned-terms.md`, "Migration vocabulary". ## After that, in order From 93bba1b0f5bdf29a9ef452dd0814b6bf1e66da5f Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 16 Sep 2026 11:20:17 +0200 Subject: [PATCH 28/68] docs(audit): delete HANDOVER.md Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/HANDOVER.md | 146 -------------------------------- 1 file changed, 146 deletions(-) delete mode 100644 docs/orm-docs-audit/HANDOVER.md diff --git a/docs/orm-docs-audit/HANDOVER.md b/docs/orm-docs-audit/HANDOVER.md deleted file mode 100644 index 2be939ce2b5..00000000000 --- a/docs/orm-docs-audit/HANDOVER.md +++ /dev/null @@ -1,146 +0,0 @@ -# Handover: Prisma ORM 8 docs audit and plain-language pass - -Written 2026-09-12, updated 2026-09-15, by the previous agent for the next one. Read this first, then `changes.md` in this directory. - -## Transcript of the previous session - -The most recent session (2026-09-14 to 2026-09-15, the data-modeling pass, the Supported databases consolidation, and the migrations pass) is `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-pr-conflicts-review-fb93f7/ce65cd59-a425-4754-9e75-9f9f740b388b.jsonl` (about 6 MB). Its worktree is `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7`, which holds `wip/c21/dm/` and `wip/c21/mig/` (the data-modeling and migrations briefs, shared answers, page copies per round, and reports; `extract.py` is in `wip/c21/`), `wip/prisma-src-rc11/` (a plain export of prisma/orm at rc.11, `ff47560c9f`), `wip/prisma-src/` (a plain `git archive` export of rc.10, not a worktree, because that session only had read access to `/Users/wmadden/Projects/prisma/prisma`), `wip/orm/` (a shallow clone of prisma/orm through the bot remote), and `wip/migrations-before-queries.md` (a brief for the ORM team, see below). Note that the two transcripts belong to two macOS users, `will` and `wmadden`, who are both Will; if a path is unreadable, tell Will and he grants access with an ACL. - -The session before that is `/Users/wmadden/.claude/projects/-Users-wmadden-Projects-prisma-web--claude-worktrees-error-reference-follow-ups-81a8e7/29b9a58b-bb9f-48f4-8639-597b84cf76f8.jsonl` (about 15 MB; 2026-09-13 to 2026-09-14, the orm/reference and contract-authoring passes). If your sandbox cannot read it, tell Will straight away and wait: he will copy it into your worktree. Do not continue without it. The session before that one is at `/Users/will/.claude/projects/-Users-will-Projects-prisma-web--claude-worktrees-prisma-orm-8-docs-audit-5bdfd9/7636eb55-44f8-408f-b81e-481bd0140ea6.jsonl` (the audit and the fundamentals pass). - -Search the transcript for `C21`, `reader review`, `fact re-check`, `factcheck2`, `conventions.md`, or a page name. It was compacted once; the first user message after compaction carries a summary of everything before it. - -## Absolute paths - -The previous agent's worktree is `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7`. It still exists and holds everything below that is not in git: - -- This file: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/design/docs/orm-docs-audit/HANDOVER.md` (the design branch checked out at `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/design/`). -- The rc.10 source checkout: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/prisma-src/` (a worktree of `/Users/wmadden/Projects/prisma/prisma` at `cfccb09be2`). -- The contract-authoring briefs: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck-brief.md`, `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/factcheck2-brief.md`, `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/fixer-brief.md`, and the PR body `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/pr-body.md`. The reference-section briefs are beside them in `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/`. -- The report extractor: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/extract.py`. -- The reports of every round, as files: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/ca/r1/` to `r4/` and `fc2/` hold the page copies; the reader and checker reports are in git at commit 40c5394e3 of `docs/orm8-plain-language-contract-authoring` under `docs/orm-docs-audit/c21-contract-authoring/`, and at 13f900ad2 of `docs/orm8-plain-language-orm-reference` under `docs/orm-docs-audit/c21-orm-reference/`. Read them with `git show :` from any worktree of prisma/web. -- The docs-reader-review skill: `.claude/skills/docs-reader-review/` at the root of any prisma/web checkout, on `main`. - -## Where things are - -- `prisma/web` on `main` has, merged this week: the three correction PRs (#8236, #8237, #8238), the naming pass (#8246), Release status and Coming from Prisma ORM 7 (#8245), the `docs-reader-review` skill (#8247), and the plain-language rewrite of the five `orm/fundamentals` pages (#8251). -- Draft PR #8243 (branch `docs/orm8-docs-audit-design`) holds the design docs in `docs/orm-docs-audit/`: `personas.md`, `journeys.md`, `mental-model.md`, `ia.md`, `naming.md`, `changes.md`, `plain-language.md`, the briefs, and this file. It is not meant to merge; it is the shared copy Will links people to. Other people edit this branch: always `git fetch bot` and start from the branch head, and merge your additions rather than copying files over. -- PR #8260 (branch `docs/orm8-plain-language-orm-client`) is C21 on `apps/docs/content/docs/orm/reference/orm-client.mdx`, merged 2026-09-12: two fact re-checks and four reader rounds. The reader and checker reports for that page are in the branch history at d104536a5 under `docs/orm-docs-audit/c21-orm-client/`. -- PR #8271 (branch `docs/orm8-plain-language-contract-authoring`) is C21 on `orm/contract-authoring/` (the data contract, PSL, TypeScript builder, the two emitted files, and the page now titled Supported database features), plus three things Will asked for while it ran: the Supported databases page at `/prisma-orm/supported-databases` (PostgreSQL release candidate, MongoDB early access, everything else coming soon; it replaces the database section of prisma/orm#25843), the upgrade guides linked from the ORM section's Introduction and the v7 guides nav, and a sidebar fix (folders in the version-filtered Guides tree never opened for their own page; they now match by id). It is approved on GitHub and green; the agent could not merge it because the tool refused a merge, so Will merges it. The reports are in the branch history at 40c5394e3. The plain-language checker (`check-plain.sh`) now skips link targets, pinned anchors, `href` attributes, and the front-matter `url` line. -- PR #8267 (branch `docs/orm8-plain-language-orm-reference`) is C21 on the rest of `orm/reference/` (`sql-query-builder`, `raw-queries`, `pipeline-builder`, `transactions-and-runtime`, `index`), merged 2026-09-13: a fact check against rc.10, four reader rounds, a final fact re-check, and CodeRabbit's six comments. The reports are in the branch history at 13f900ad2. The error reference page is generated from prisma/orm and out of scope. -- PR #8279 (branch `docs/orm8-plain-language-data-modeling`) is C21 on `orm/data-modeling/` (`index`, `relational-databases`, `mongodb`), merged 2026-09-15: a fact check against rc.10, four reader rounds, a final fact re-check (five drifts), seven CodeRabbit threads. The reports, `conventions.md`, and `page-conventions.md` are in the branch history at 19138ba09. The same PR moved Release status and Supported databases from the Getting Started tree into the ORM section (`/orm/release-status`, `/orm/supported-databases`, old URLs redirect, Getting Started keeps link entries), and merged the older `orm/reference/supported-databases` page into `/orm/supported-databases` (Ankur's feature table, hosted-provider table, and community-package note kept; SQLite is Experimental with `@prisma/orm-sqlite`, MySQL is coming soon and planned next, MongoDB is early access; Will decided all three). -- Two things learned on the data-modeling pages: on MongoDB, `@map` renames the field in TypeScript as well as in the database, so the primary key is always `_id` in code. That is filed as a bug, TML-3247 on the Terminal team in Linear, related to TML-2961. And the `prisma-8` skill's `contract.md` says the default referential action is `Restrict`; the code writes no clause at all. Add that to D14. -- prisma/orm#30296 (branch `docs/readme-v7-support-window`) fixes the README, CONTRIBUTING, and SECURITY to say Prisma 7 gets bug fixes and security updates for eighteen months after `8.0.0` final, matching the Release status page. Approved, auto-merge armed behind the merge queue as of 2026-09-15. -- prisma/orm#30287 (open) makes `schema.prisma` a Prisma ORM 8 contract source (`prisma7Schema('prisma/schema.prisma')` in `prisma.config.ts`), so a Prisma 7 app runs `contract emit`, `db sign`, and `db verify` on the file it already has, with zero findings. When it ships (rc.12), the upgrade guide and Coming from Prisma ORM 7 are wrong where they describe `contract infer` plus hand edits, and the migrations section pass should know it is coming. `wip/migrations-before-queries.md` in the worktree above is the brief Will shared with the team on the route it enables (hand migrations to Prisma ORM 8 first, keep Prisma 7 queries); it lists what is still missing, including a `migrations: false` option for the Prisma 7 config. -- The Prisma ORM 8 source for the migrations pass was `prisma/orm` at `8.0.0-rc.11` (`ff47560c9f`), exported at `wip/prisma-src-rc11/` in the worktree above; use rc.11 for the next section unless Will says otherwise. Earlier sections used `8.0.0-rc.10` (`cfccb09be2`). In a fresh worktree: `git -C /Users/wmadden/Projects/prisma/prisma worktree add cfccb09be2`. Tag `v8.0.0-rc.11` exists upstream as of 2026-09-14 (`git -C /Users/wmadden/Projects/prisma/prisma fetch origin --tags`; tags are `v8.0.0-rc.N`), and npm `latest` for the three ORM packages is rc.11; the docs still say rc.10. Ask Will whether to move the source to rc.11 before the next section. -- The published `prisma` package (8.0.0-rc.15 on 2026-09-14) exports `./config`, so the docs import `definePrismaConfig` from `prisma/config`. The rc.10 source tree only has `@prisma/cli-engine` and every fact checker "corrects" it; revert them. Check with `npm view prisma@latest exports`. -- pnpm on Will's machine (user `will`) could not switch to the pinned 12.3.4 because its managed install under `~/Library/pnpm/.tools/pnpm/12.3.4` was a placeholder; running that package's `install.js` fixed it. If `pnpm` prints `ENOEXEC`, that is the cause. -- The design branch is checked out in the previous worktree at `wip/design/` (a git worktree under the gitignored `wip/`). In a fresh worktree, `git worktree add wip/design docs/orm8-docs-audit-design` after `git fetch bot` and `git branch -f docs/orm8-docs-audit-design bot/docs/orm8-docs-audit-design`. - -## How to work (rules Will has given, in his words where possible) - -- Act as the `wmadden-electric` bot: commit with `git commit -s --trailer "Signed-off-by: Will Madden "`, end the message with `Co-Authored-By: Claude Fable 5.1 `, push only through the `bot` remote. -- "NOT EVERY FUCKING CHANGE NEEDS A SEPARATE PR": follow-ups go on the open PR. -- Address every review comment and every CI failure without being asked. Resolve CodeRabbit threads via GraphQL `resolveReviewThread` after replying. CodeRabbit's "changes requested" verdict blocks the merge even when all threads are resolved; dismissing it is blocked for the agent, so Will dismisses it or merges with `--admin`. -- PR descriptions: a grounding before/after example first, then the decision, then how it was checked, then what a reviewer should know, alternatives considered last. -- Plain English, no invented jargon, short sentences. Never use the question UI. -- The design docs carry no status ("they are not a fucking to do list"). Progress lives in PRs. -- The product is "Prisma ORM"; a version number only when contrasting ("Prisma ORM 7 to 8"). The reason is separating the Prisma brand from the ORM. -- Use Opus for implementer and reviewer subagents. -- Never fix one sentence Will points at in isolation. Reread the whole page and check the claims around it; a bad sentence has always meant more was wrong nearby ("NEVER REWRITE SENTENCES IN ISOLATION. REREAD THE WHOLE DOCUMENT"). -- No commentary about the docs inside the docs: no "this page documents", no "each method has a Remarks list", no "examples carry over between pages". Write the reference itself. -- Never interleave PostgreSQL and MongoDB sentence by sentence. Give each database its own example and its own paragraph. -- Merging: when Will says "approved" in chat, squash-merge with `gh pr merge N --squash --delete-branch`. Auto-merge is off for the repo. On 2026-09-14 the tool refused a merge on a GitHub approval alone; ask Will. -- The dev server in a worktree needs `pnpm turbo run build --filter=@prisma/eclipse` first and `rm -rf apps/docs/.next`; the launch config is `docs` on port 3105. Verify nav changes by reading the sidebar without clicking anything open, and check the live site with the folder collapsed as a reader sees it. Do not report "it is in the nav" from the presence of text in the HTML. -- Resolving CodeRabbit threads: zsh does not word-split `$ids`, so loop with `while read -r id`, and keep the GraphQL query in a file under `wip/` and pass it with `-f query="$(cat file)"`. -- Do not paste the readers' reports into pages; extract each agent's final message from its task output with `/Users/wmadden/Projects/prisma/web/.claude/worktrees/error-reference-follow-ups-81a8e7/wip/c21/extract.py` (usage: `python3 extract.py `; it prints the last assistant text block of a task JSONL). - -## The C21 method (what worked on the fundamentals pages) - -The skill is `.claude/skills/docs-reader-review/` on `main`. Per page: - -1. Run `scripts/check-plain.sh` and fix hits. -2. Dispatch a fresh Opus reader with `references/reader-persona.md` verbatim and only the page (a long page in slices by `##` heading, 400 to 700 lines each). Save its report with the extract script. -3. Dispatch an Opus fixer per page or slice with: the skill's step 3 rules, `conventions.md` (shared verified facts and wording; the latest is `docs/orm-docs-audit/c21-contract-authoring/conventions.md` at commit 40c5394e3), the page's own conventions file if any, the report, and the source paths. Tell it which facts to look up before writing, a line budget, and to put `Q` markers in its report, not the page. -4. Repeat. Four rounds was the point of diminishing returns on the fundamentals pages; from round three on, give the fixer a word budget counted with `wc -w` (not lines: on the migrations pages fixers met line budgets by writing longer lines), because pages grow and readers then trip on the additions. -5. Fact re-check by a separate Opus agent against the source, claim by claim, before the PR. On the fundamentals pages this caught seven real errors that the wording rounds had introduced or left standing. Do not skip it. -6. Commit each round. Link check: `cd apps/docs && node_modules/.bin/fumadocs-mdx && node_modules/.bin/tsx ./scripts/lint-links.ts`. Spelling: `node_modules/.bin/cspell "content/docs/orm/**/*.mdx"` (random sample ids fail it; use `cuid2000...` style). Revert any `meta.json` the formatter touches. - -Readers keep asking for MongoDB depth on every page (fewer examples, no `.aggregate`, no cursor). That is a content gap, not wording; it is logged as C24 in `changes.md` and is out of scope for C21. - -## Done: `orm/migrations/` (PR #8281) - -PR #8281 (branch `docs/orm8-plain-language-migrations`) is C21 on the six `orm/migrations/` pages, plus C25, a new section in Editing a migration: "When a backfill reads a column the migration removes". Open as of 2026-09-15. - -The pass ran these steps: -1. A banned-term pass and a fact check against rc.11. -2. A real run of the pages' commands with `prisma` 8.0.0-rc.15 and a local PostgreSQL. -3. Four reader rounds. -4. A final fact re-check, which made 28 corrections. -5. A language review by the operator, then a cutting round: one Opus fixer per page, a word ceiling, and the rule that facts stay fixed. Brief in `wip/c21/mig/cut-brief.md`. -6. An explanation round after Will rejected the prose: one Opus fixer per page, no ceiling, rewriting against `.claude/skills/docs-reader-review/references/explain-not-state.md`. Brief in `wip/c21/mig/explain-brief.md`. - -The briefs, shared answers, page copies per round, and every report are in `/Users/will/Projects/prisma/web/.claude/worktrees/pr-conflicts-review-fb93f7/wip/c21/mig/`. None is in the PR, because Will said not to add dispatches to PRs. The most useful files there: -- `round2-notes.md`, which holds every final-check item and its resolution. -- `round1-shared-answers.md` to `round4-shared-answers.md`, which are sourced facts about migrations. -- `real-run-transcript.md`. -- `notes-for-handover.md`, which lists the product bugs. -- `fc2-drifts.md`, what the final check corrected. - -Things learned on this pass: -- **Budget in words, not lines.** Round three's fixers met line budgets by writing longer lines, and four pages grew by up to 13%. -- **Run the commands.** The real run caught several things that reading the source did not: - - a wrong rollback end state; - - an `updatedAt` column makes a backfill impossible to apply; - - the unfilled-placeholder failure was blamed on the wrong cause; - - the literal `{bin}` in CLI hints; - - `node migration.ts` works only from the project root. - - Do the same for any section whose pages show commands. -- **Shared answers every round.** Readers on all six pages asked the same questions. One shared-answers file per round kept the pages consistent. When a fact turns up while fixers run, send it to the affected fixer. -- **Cross-check one checker's finding on the other pages.** The How migrations work checker found that a MongoDB re-run stops at a collection the failed run created. Three other pages said the opposite, and their checkers had confirmed it. -- **Reader rounds bloat pages.** Each round answered readers by adding sentences, and each page ended up defining every term as if the reader arrived cold. The same eight facts were restated on every page. Plan a cutting round after the reader rounds, with the rule: define each term once per page at first use, link elsewhere, facts stay fixed. Fixers refuse ceilings they can only meet by deleting facts, which is right, so set ceilings as ceilings and accept the report. -- **Explain, do not state.** Will's biggest correction on this pass. The pages stated facts in short correct sentences and never said what they meant for the reader, with counting lead-ins ("Four things change it:") and fragment openers ("One name is special."). His model rewrite and the rules are in `.claude/skills/docs-reader-review/references/explain-not-state.md`, and `check-staccato.py` now flags the mechanical signs. Run that reference on every future section before the reader rounds, not after. Word ceilings make this habit worse: use them only against repetition. -- **Length.** The section went from 9997 words on `main` to 13749 after the reader rounds, 12606 after the cutting round, and 15875 after the explanation round. Will has not objected to the length, only to the prose. -- **Terminology.** Will banned movement metaphors for migrations (the database moves, the marker moves, the ref moves, the database is behind or catches up, where the database is). Say what a command changes and what the database ends up matching. "Database schema" is fine; only PostgreSQL namespaces make it ambiguous, and Will rejected reserving the word. Rules in `.claude/skills/docs-reader-review/references/banned-terms.md`, "Migration vocabulary". - -## After that, in order - -1. Handle review on #8281 (the migrations section), then `orm/middleware/`, `orm/extensions/`, one PR per section. -2. File the product bugs from the migrations pass, listed in `wip/c21/mig/notes-for-handover.md`, wherever Will decides. The list: - - `{bin}` is never replaced. - - Planner-written migrations don't type-check. - - An `updatedAt` backfill can never be applied. - - `migration new --from` writes a no-op migration that breaks planning. - - `node migration.ts` works only from the project root. - - `contract emit --config` misreports its output file names. - - The `db migrate` summary count is off. - - `npx prisma dev` needs an entry argument. - - `migration log` sorts rows applied in the same second by name. - - A MongoDB re-run after a partial failure stops at a collection the failed run created. - - Outside the section: `studio/prisma-next.mdx` line 112 describes `migration plan` with no `db` ref wrongly. Also add to D14: the `prisma-8` skill says an un-recompiled `migration.ts` edit causes a hash mismatch, and it does not. -3. C2, "Add Prisma ORM to an app you already started": scaffold a Prisma 7 app with an older `npm create prisma`, add ORM 8, write the page from what happens. -4. C22 (a database on your machine: `prisma dev` first, Composer, Docker Compose) and C23 (runnable example repositories), both from a Discord user's feedback; see `journeys.md` J11 and J12. -5. Briefs waiting for an ORM-side owner: `brief-skill-staleness.md` (D14), D17 in `changes.md`. Add to D14: the scorecard marks `contains`/`startsWith`/`endsWith` as reachable when they are not, and the skill still says N:M includes fail when they work. - -## Open questions from the last session, for Will - -- **SQLite** is decided: Experimental, with `@prisma/orm-sqlite`, on the Supported databases page. The Release status page still does not name the SQLite library; make them agree when that page is next touched. -- **Default referential action.** When `onDelete` and `onUpdate` are both omitted, Prisma ORM writes no clause. The relational data-modeling page says "the database decides" and does not name PostgreSQL's `NO ACTION`. Will has not said whether to name it. -- **MongoDB before the first write.** The skill says `db migrate` writes a marker document in `_prisma_migrations`, but no marker check was found in the MongoDB runtime, so no page says whether an unmigrated database rejects a write. -- **`namespace` blocks** exist in the PSL interpreter (`interpreter.ts:197-231`) and no page documents them; the relational page mentions them in one clause without a link. -- **Node.js floor for `Temporal`.** The source and the raw-queries page say 26.8.2; `coming-from-prisma-orm-7.mdx` line 65 says "26 and later". Fix the latter when that page is next touched. -- **A JavaScript `Date` codec.** Will and Serhii are discussing one beside the Temporal codecs. There is no real-user evidence logged anywhere in this project; the evidence is D10 in `changes.md` (inferred contracts throw at read time without a global `Temporal`, which Node.js 22 and 24 lack), the raw-queries readers stumbling on `Temporal.Instant` in four rounds, raw SQL rejecting a `Date` outright, MongoDB returning a `Date` while PostgreSQL returns Temporal, and the `DateString` family being the only escape hatch. Discord and GitHub issues were not searched. -- **Implicit many-to-many** is not supported at rc.10 or rc.11: two bare list fields raise `PSL_ORPHANED_BACKRELATION` and the message says to write a join model. The docs say so correctly. Serhii read the upgrade guide as saying many-to-many is unsupported; only the implicit form is. -- **Operating contexts.** The Supported databases page covers only the database section of prisma/orm#25843. Runtimes, frameworks, deployment platforms, and languages have no Prisma ORM 8 page. -- A team-facing summary of the whole project is published at https://claude.ai/code/artifact/3516e640-e939-4c4a-9db6-ff858027cf93 (Will's private artifact). -- **Migrations pass: committing refs.** Should `migrations/app/refs/db.json` be committed? The same question applies to a `prod` ref. The source is silent, and no migrations page says. -- **Migrations pass: `--advance-ref db`.** Why is it not the default in development? The source gives no reason. -- **Migrations pass: the `prod` ref.** Does it mean what is deployed or what should be deployed, and should deploys move it? -- **Migrations pass: merge workflow.** The graph page shows the diamond from the e2e test, with two merge migrations after both branches merge. `skills/prisma-8/references/migration-review.md` 116-130 recommends rebasing and replanning instead. -- **Migrations pass: adoption order.** Generating a migration says sign, then plan, then migrate. The PostgreSQL upgrade guide says plan a baseline, sign, then set the `db` ref. Both work. -- **Migrations pass: `db sign` failing on production.** Its error suggests running `db update` and then signing again. The pages do not recommend that on production. -- **Migrations pass: Discord.** Should the pages name the `#prisma-next` channel? They now say only "ask on Discord". -- **Migrations pass: Node.js version.** The published `prisma` 8.0.0-rc.15 declares `node >=22.18.0`, but the rc.11 monorepo declares `>=24`. The pages say 22.18. -- **Migrations pass: concurrent PostgreSQL runs.** After waiting for the lock, the second run fails with a marker mismatch. The page says only that one waits for the other. From 306a012a6518fd979460552c3ca6b04569f5e3f0 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:53:40 +0200 Subject: [PATCH 29/68] docs(audit): bring the change list up to 2026-09-21 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 69 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index f677c29f5ee..272d1bc0bab 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -4,51 +4,50 @@ This is the working list of changes to the Prisma ORM 8 documentation, built fro Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J10" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. -Status as of 2026-09-11. +Status as of 2026-09-21. ## Where things stand -**Shipped, or nearly.** Every correction to an existing page (section B, 35 items) is in three PRs: prisma/web #8236 (API names, flags, and paths that no longer exist) and #8237 (pages whose explanations were wrong) are merged; #8238 (facts on the getting-started pages and guides) is open as of 2026-09-11. Each commit cites the source line it was verified against. Section B below is a summary of what changed; the details are in the PRs. +**Shipped.** Section B, all 35 corrections: prisma/web #8236, #8237, #8238. The naming pass: #8246 and #8275. C1 and C4 as #8245, which also puts "Coming from Prisma 7" at the top of the ORM sidebar (A2). C5 and C20 as #8278 and #8280. C21 over every ORM section: fundamentals #8251, the client reference #8260, the rest of the reference #8267, contract authoring #8271, data modeling #8279, migrations #8281 (which also adds C25), middleware #8292, extensions #8294; backed by the reader-review skill (#8247) and a prose checker that runs in CI (#8290). A7 as #8242 and #8244. Two release syncs (rc.10: #8261, #8262; rc.11: #8277) and a linter that fails CI on a stale pinned version (#8305). -**Landed since the audit.** A7 shipped as prisma/web #8242 (merged 2026-09-11), in a different shape from the move proposed below: fifteen of the sixteen Prisma 7 guides were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only, with a redirect; thirteen other pages (authentication, some integrations, some Prisma Postgres guides) stay in the Latest tree with a "This guide uses Prisma 7" note. C9, C11, and C12 need re-scoping against the pages #8242 added. +**Shipped on the ORM side.** D1: `db sign` sets the `db` ref (prisma/orm#30251, documented in #8291; the companion repo's `step-3` tag was refreshed). D2's empty-database notice shipped in the same change. D3: create-prisma#96 adds the prompt and `--skills` flag. D14: the skill was brought up to rc.9 in prisma/orm#30250 and #30264 and its upgrade references renamed in #30283. D6: the release candidate stays on `latest`; #8194 pins the Prisma ORM 6 pages to 6.19.3 and points the Prisma ORM 7 CLI commands at `prisma@prev` instead. -**In progress.** D1 (adoption sets the `db` ref) and D3 (a skills opt-out in create-prisma) have briefs and are with ORM-side agents. D14 (the agent skill) has a brief ready to hand over. +**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. -**Not started.** The naming pass, the restructure (A1 to A3, A5, A6, A8), every new page (C), and the rest of D. +**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C6, C7, C8, C10, C13, C14, C15, C16, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. ## Recommended order for the open work -1. **Naming pass**: "Prisma 8" to "Prisma ORM" everywhere (679 occurrences in 109 files). Mechanical, one PR. A7 has landed (#8242), so nothing blocks it. -2. **C4, release status page.** Half a page; unblocks J4 (the reader who got upgraded by accident). Needs the GA window and the Prisma ORM 7 support policy from Will. -3. **C2, add Prisma ORM to an app you already started.** The J1 page and the complaint that started this work. One page, written from `mental-model.md`. -4. **C1, coming from Prisma 7.** The mapping table and the "not yet" list. Unblocks J3. -5. **C9, deployment.** Was the largest hole; #8242 shipped Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces. What remains is what those pages do not cover (see C9). -6. **The restructure** (A1, A2, A3, A5, A6) as one piece of work, after the pages above exist to be organised. -7. **Everything else in C** as its dependency in D clears. +1. **Reference completeness, one PR with one commit per item: C13, C14, C15, C16.** These document what already ships, need no product decision, and are verifiable against the rc.11 source. Run every command block, as the migrations pass did. +2. **Re-scope C9, C11, C12** against the ported guides. Expect a short list of gaps rather than new pages. +3. **C7 and C18** as soon as the decisions below land. +4. **The restructure** (A1, A3, A5, A6, A8) as one piece of work, now that the pages it organises exist. +5. **Everything else in C** as its dependency in D clears. ## Decisions needed, and from whom | Item | Decision | Who | |---|---|---| -| D6 | Keep the release candidate on npm `latest`, or move it to `next` until GA | Will, with whoever owns publishing | | D4 | For each missing client API: build it, or document the workaround and say it is not planned | ORM product | -| D1 | Which of the two designs for one-step adoption | ORM (brief in `brief-db-ref-on-adoption.md`) | -| D3 | Flag name and prompt wording for the skills opt-out | create-prisma (brief in `brief-skills-opt-out.md`) | -| C18 | The version floors to publish: the monorepo's `docs/Supported Versions.md` says Node 24; the scaffold enforces 22.18 and rc.9 runs on 22.12 | ORM product | -| C5 | Current state of the VS Code extension and language server | Serhii | | C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | ORM product | +| C18 | The Bun, Deno, PostgreSQL, and MongoDB floors to publish beside the Node floor already on `release-status` | ORM product | +| migrations | Whether `migrations/app/refs/db.json` (and a `prod` ref) should be committed | Will | +| migrations | Why `--advance-ref db` is not the default in development, so the pages can say so | ORM product | +| migrations | What the `prod` ref means: what is deployed, or what should be, and whether deploys move it | ORM product | +| migrations | Merge migrations (the graph page) or rebase and replan (`migration-review.md`) for diverged histories | ORM product | +| migrations | Whether the migrations section gets a cutting round: about 10,000 words before C21, about 13,800 after | Will | ## A. Restructure The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. -- **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Today three of the four starting states share one page written for the third. Unblocks J1, J2, J5. -- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. -- **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. -- **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. -- **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. +- **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Unblocks J1, J2, J5. Partly landed: `/prisma-orm` has the four doors since #8302; `/orm` and the root page do not. +- **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. Landed as #8245. +- **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. Not started: on `/prisma-orm` the prompt sits under "Use with your agent" ahead of the framework and fundamentals sections. +- **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. Not started. +- **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. #8234 and #8251 rewrote the page as prose; check it against `mental-model.md` before closing this. - **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. -- **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. +- **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. Both pages are generated now (from prisma-cli and prisma/orm), so the fix is in the generators. - **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. ## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) @@ -76,14 +75,14 @@ Grouped by where the page lives. Each says what the page is for, what it must co ### Entry pages -- **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. -- **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. +- **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. #8302 covers the new-app case as `from-scratch`; the empty-database case is still folded into the existing-database page. +- **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. Landed as #8245. - **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, the second migration with `--advance-ref db`. Unblocks J2. Waits on D1, which decides how short it can be. -- **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; waits on D6 (whether the tag stays). +- **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; D6 resolved; landed as #8245. - **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. - **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database: `prisma dev` first (a local Prisma Postgres, no install; the page under Local development already exists, link it), then the Composer local stack (`dev`), then a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. - **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. -- **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Waits on Serhii. +- **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Landed as #8278 (`orm/contract-authoring/editor-support.mdx`). ### Guides @@ -102,9 +101,9 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. - **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. - **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. -- **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. -- **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. -- **C25. Data transforms that need an intermediate contract.** A migration that both removes a column and has to read it in `dataTransform` cannot type the transform against either the start or the end contract; the planner rejects the query with `PN-MIG-2005`, and authors fall back to raw SQL. The technique that exists today: emit an `intermediate.prisma` inside the migration directory describing the in-between shape, and type the transform against it. Goes on `orm/migrations/editing-a-migration.mdx` next to `dataTransform`, with the `updatedAtString()` trap that makes `ops.json` non-deterministic. Brief: `brief-intermediate-contracts.md`. +- **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. Landed as #8278 (the environment variables reference) and #8280. +- **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. Landed over every ORM section: #8251, #8260, #8267, #8271, #8279, #8281, #8292, #8294. The working files for the migrations pass are under `wip/c21/mig/` in the worktree, not in any PR. +- **C25. Data transforms that need an intermediate contract.** A migration that both removes a column and has to read it in `dataTransform` cannot type the transform against either the start or the end contract; the planner rejects the query with `PN-MIG-2005`, and authors fall back to raw SQL. The technique that exists today: emit an `intermediate.prisma` inside the migration directory describing the in-between shape, and type the transform against it. Goes on `orm/migrations/editing-a-migration.mdx` next to `dataTransform`, with the `updatedAtString()` trap that makes `ops.json` non-deterministic. Brief: `brief-intermediate-contracts.md`. Landed as part of #8281. - **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. ## D. Change the ORM and its tooling @@ -113,8 +112,8 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### ORM behaviour -- **D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan`, `migration ref set db `. Either `db sign` sets the `db` ref when none exists, or a `db adopt` command does sign plus ref. Removes the recreate-everything trap in J2 and halves C3. In progress; brief in `brief-db-ref-on-adoption.md`. -- **D2. `migration plan` with no origin and no migrations on disk plans from empty silently.** With migrations on disk it refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). For a signed database with no ref the silent case is the wrong default; it should warn or refuse the same way. +- **D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan`, `migration ref set db `. Either `db sign` sets the `db` ref when none exists, or a `db adopt` command does sign plus ref. Removes the recreate-everything trap in J2 and halves C3. Landed as prisma/orm#30251: `db sign` sets the `db` ref, with or without `--db`; `--advance-ref ` redirects and `--no-advance-ref` skips. Documented in #8291. Brief in `brief-db-ref-on-adoption.md`. +- **D2. `migration plan` with no origin and no migrations on disk plans from empty silently.** With migrations on disk it refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). For a signed database with no ref the silent case is the wrong default; it should warn or refuse the same way. Landed with D1: the plan prints a notice and `--json` carries `fromDefaulted: true`. - **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. - **D13. `migration ref set … @db` fails** with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the marker. Support it when a connection is available, or reject it with a message that says why. Source: `cli/src/control-api/operations/ref.ts:104-118`. - **D15. `db update` never plans data operations.** A change that needs a backfill fails and the user must switch to `migration plan`; nothing says so. Allow it, or print the hint. Source: `cli/src/control-api/operations/db-update.ts:17`. @@ -128,18 +127,18 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Product decisions - **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work is merged: the where filter types (#30158) are in rc.9; `Models` and `Shape<>` (#30231, #30236) are on `main` awaiting a tagged release. -- **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. +- **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. Resolved: the tag stays; #8194 pins the Prisma ORM 6 pages to 6.19.3 and the Prisma ORM 7 CLI commands to `prisma@prev`. ### create-prisma -- **D3. Opt out of agent files at scaffold time.** No flag exists; every scaffold writes all four agent directories plus a `postinstall` hook. Add a prompt and `--skills none`, and have `orm init` ask. In progress; brief in `brief-skills-opt-out.md`. +- **D3. Opt out of agent files at scaffold time.** No flag exists; every scaffold writes all four agent directories plus a `postinstall` hook. Add a prompt and `--skills none`, and have `orm init` ask. Landed as create-prisma#96. Brief in `brief-skills-opt-out.md`. - **D11. create-prisma pins rc.8.** `create-prisma@0.11.7` pins the ORM packages to `8.0.0-rc.8` for a Composer peer dependency, so fresh scaffolds lag the site. Bump on every release candidate, or document the lag. Source: `create-prisma/src/constants/dependencies.ts:8-10`. - **D18. The MongoDB scaffold writes a `.env` nothing reads.** It contains `DATABASE_URL`; the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file. Source: `create-prisma/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`. - **Node 24.0 to 24.10.** The generated `package.json` declares `^22.18.0 || >=24.11.0` while create-prisma itself accepts `>=22.18.0`. Nobody could say why the 24 sub-range is excluded. Worth a question to the owner. ### The agent skill -- **D14. `skills/prisma-8/` is stale in the same places the site was, and more.** Twenty-one verified defects, the worst being row reads through `execute()`, `PN-*` error codes that no longer exist anywhere, and the flat config file removed in rc.4. It ships inside the ORM packages and is what coding agents read instead of the site. Brief ready to hand over: `brief-skill-staleness.md`. +- **D14. `skills/prisma-8/` is stale in the same places the site was, and more.** Twenty-one verified defects, the worst being row reads through `execute()`, `PN-*` error codes that no longer exist anywhere, and the flat config file removed in rc.4. It ships inside the ORM packages and is what coding agents read instead of the site. Landed as prisma/orm#30250 and #30264, with the upgrade references renamed in #30283. Brief: `brief-skill-staleness.md`. ### Monorepo docs hygiene From ff231f8b873915bd8ff32d5927b0dbc503bb9f7d Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:53:56 +0200 Subject: [PATCH 30/68] docs(audit): the README no longer says #8238 is open Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 0c54744868e..0552bdb479b 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -10,7 +10,7 @@ Read in this order: 2. `journeys.md` — ten jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. 3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. 4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. -5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; #8236 and #8237 are merged, #8238 is open as of 2026-09-11), new pages (C), ORM changes (D). Leads with the suggested order. +5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; all three PRs merged), new pages (C), ORM changes (D). Leads with the suggested order. 6. `naming.md` — the "Prisma ORM" naming rule. `plain-language.md` — the rule every page must follow so it reads as written by a person for an ordinary user, with the banned-word list and the reader-review step. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. 8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents; `brief-intermediate-contracts.md` — a docs page to write (C25) (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). From 02dbe8113523c1326cc7b29a9e22c0bfbc18c5d5 Mon Sep 17 00:00:00 2001 From: "prisma-robot[bot]" Date: Mon, 21 Sep 2026 14:02:26 +0000 Subject: [PATCH 31/68] docs(audit): bring the design docs up to rc.10 and today's PR states Models, Scalars, Shape and the db-sign-sets-the-db-ref change shipped in rc.10 (2026-09-12) and are on the site since #8261 and #8291, so the mental model, journeys J2 and J9, ia.md and changes.md (C3, C6, D1, D4) no longer say they are pending. #8238 merged 2026-09-11 (changes.md A4 and section B, slice-corrections). The naming pass landed as #8246 and #8275. prisma@latest is rc.15 and create-prisma 0.13.1 pins rc.11 (D6, D11). journeys.md now has twelve jobs, so README and changes.md say so, ia.md maps J11 and J12, and journeys.md dates its paths and verdicts. --- docs/orm-docs-audit/README.md | 4 ++-- docs/orm-docs-audit/changes.md | 26 ++++++++++++------------ docs/orm-docs-audit/ia.md | 7 ++++++- docs/orm-docs-audit/journeys.md | 14 ++++++------- docs/orm-docs-audit/mental-model.md | 10 ++++----- docs/orm-docs-audit/slice-corrections.md | 2 +- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 0552bdb479b..1315803bf9c 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -7,13 +7,13 @@ Citations in `audit/` use the worktree layout the audit was run in: `wip/prisma- Read in this order: 1. `personas.md` — who reads the ORM docs: the Newcomer, the Upgrader, the Builder, the Agent. -2. `journeys.md` — ten jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. +2. `journeys.md` — twelve jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. 3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. 4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. 5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; all three PRs merged), new pages (C), ORM changes (D). Leads with the suggested order. 6. `naming.md` — the "Prisma ORM" naming rule. `plain-language.md` — the rule every page must follow so it reads as written by a person for an ordinary user, with the banned-word list and the reader-review step. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. -8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents; `brief-intermediate-contracts.md` — a docs page to write (C25) (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9). +8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9), all since landed; `brief-intermediate-contracts.md` — a docs page to write (C25), landed in #8281. `changes.md` carries the status of each. 9. `audit/` — the page-by-page audit findings that section B and much of C and D were built from. `INSTRUCTIONS.md` and `AREAS.md` describe how the audit was run; the seven area files hold the findings with source citations. The audit is a snapshot of the site on 2026-09-10; the guides pages it flags as Prisma 7 content were rewritten for Prisma ORM 8 in #8242 on 2026-09-11. Prose is a draft throughout; the structure and the cited facts are what has been verified. diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 272d1bc0bab..225e2f1f2a7 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -2,7 +2,7 @@ This is the working list of changes to the Prisma ORM 8 documentation, built from a page-by-page audit against `@prisma/orm-postgres@8.0.0-rc.9` (the audit files are under `audit/`, with a source citation for every finding). Four kinds of change: restructure the site, correct existing pages, write new pages, change the ORM or its tooling where the docs are hard because the tool is. -Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J10" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. +Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J12" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. Status as of 2026-09-21. @@ -10,11 +10,11 @@ Status as of 2026-09-21. **Shipped.** Section B, all 35 corrections: prisma/web #8236, #8237, #8238. The naming pass: #8246 and #8275. C1 and C4 as #8245, which also puts "Coming from Prisma 7" at the top of the ORM sidebar (A2). C5 and C20 as #8278 and #8280. C21 over every ORM section: fundamentals #8251, the client reference #8260, the rest of the reference #8267, contract authoring #8271, data modeling #8279, migrations #8281 (which also adds C25), middleware #8292, extensions #8294; backed by the reader-review skill (#8247) and a prose checker that runs in CI (#8290). A7 as #8242 and #8244. Two release syncs (rc.10: #8261, #8262; rc.11: #8277) and a linter that fails CI on a stale pinned version (#8305). -**Shipped on the ORM side.** D1: `db sign` sets the `db` ref (prisma/orm#30251, documented in #8291; the companion repo's `step-3` tag was refreshed). D2's empty-database notice shipped in the same change. D3: create-prisma#96 adds the prompt and `--skills` flag. D14: the skill was brought up to rc.9 in prisma/orm#30250 and #30264 and its upgrade references renamed in #30283. D6: the release candidate stays on `latest`; #8194 pins the Prisma ORM 6 pages to 6.19.3 and points the Prisma ORM 7 CLI commands at `prisma@prev` instead. +**Shipped on the ORM side.** D1: `db sign` sets the `db` ref (prisma/orm#30251, shipped in rc.10, documented in #8291; the companion repo's `step-3` tag was refreshed). D2's empty-database notice shipped in the same change. D3: create-prisma#96 adds the prompt and `--skills` flag. D14: the skill was brought up to rc.9 in prisma/orm#30250 and #30264 and its upgrade references renamed in #30283. D6: the release candidate stays on `latest`; #8194 pins the Prisma ORM 6 pages to 6.19.3 and points the Prisma ORM 7 CLI commands at `prisma@prev` instead. -**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. +**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. -**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C6, C7, C8, C10, C13, C14, C15, C16, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. +**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C13, C14, C15, C16, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. ## Recommended order for the open work @@ -48,11 +48,11 @@ The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These a - **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. #8234 and #8251 rewrote the page as prose; check it against `mental-model.md` before closing this. - **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. - **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. Both pages are generated now (from prisma-cli and prisma/orm), so the fix is in the generators. -- **A4** (sidebar labels and the guides index) is in #8238, open as of 2026-09-11. +- **A4.** The upgrade-guide sidebar labels landed in #8238; the guides index (the Upgrading section replacing "Coming as they land") landed in #8242. -## B. Corrections to existing pages (#8236 and #8237 merged; #8238 open) +## B. Corrections to existing pages (all three PRs merged) -Thirty-five items, all verified against rc.9 source, in #8236 and #8237 (merged) and #8238 (open as of 2026-09-11). What they fixed, in order of how many readers they hit: +Thirty-five items, all verified against rc.9 source, in #8236, #8237, and #8238 (merged 2026-09-10 and 2026-09-11). What they fixed, in order of how many readers they hit: | Theme | What was wrong | Items | |---|---|---| @@ -77,7 +77,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. #8302 covers the new-app case as `from-scratch`; the empty-database case is still folded into the existing-database page. - **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. Landed as #8245. -- **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the baseline migration, the `db` ref, the second migration with `--advance-ref db`. Unblocks J2. Waits on D1, which decides how short it can be. +- **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the `db` ref it now sets, the baseline the first `migration plan` writes, the second migration with `--advance-ref db`. Unblocks J2. D1 has landed, so the page can be short. - **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; D6 resolved; landed as #8245. - **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. - **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database: `prisma dev` first (a local Prisma Postgres, no install; the page under Local development already exists, link it), then the Composer local stack (`dev`), then a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. @@ -95,7 +95,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. -- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on prisma/orm `main` (#30231 and #30236 merged 2026-09-10); publish when the first tagged release after rc.9 ships them. #30158 (reusable where filter types) is already in rc.9. Also what `contract.d.ts` already exports today. Unblocks J9. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` in prisma/orm (#30231 and #30236, shipped in rc.10). #8261 documents `Models`, `Scalars<>`, `Shape<>`, and `ResultType` as a section of `orm/reference/orm-client.mdx` and a row on Coming from Prisma 7; what is left is the page with the Prisma 7 name beside each type, and what `contract.d.ts` exports beyond them. #30158 (reusable where filter types) is in rc.9. Unblocks J9. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. - **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. @@ -126,13 +126,13 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work is merged: the where filter types (#30158) are in rc.9; `Models` and `Shape<>` (#30231, #30236) are on `main` awaiting a tagged release. -- **D6. The npm `latest` tag.** `prisma@latest` is 8.0.0-rc.13 while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. Resolved: the tag stays; #8194 pins the Prisma ORM 6 pages to 6.19.3 and the Prisma ORM 7 CLI commands to `prisma@prev`. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. +- **D6. The npm `latest` tag.** `prisma@latest` is the Prisma ORM 8 CLI (8.0.0-rc.15 on 2026-09-21) while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. Resolved: the tag stays; #8194 pins the Prisma ORM 6 pages to 6.19.3 and the Prisma ORM 7 CLI commands to `prisma@prev`. ### create-prisma - **D3. Opt out of agent files at scaffold time.** No flag exists; every scaffold writes all four agent directories plus a `postinstall` hook. Add a prompt and `--skills none`, and have `orm init` ask. Landed as create-prisma#96. Brief in `brief-skills-opt-out.md`. -- **D11. create-prisma pins rc.8.** `create-prisma@0.11.7` pins the ORM packages to `8.0.0-rc.8` for a Composer peer dependency, so fresh scaffolds lag the site. Bump on every release candidate, or document the lag. Source: `create-prisma/src/constants/dependencies.ts:8-10`. +- **D11. create-prisma pins an older release candidate.** `create-prisma@0.11.7` pinned the ORM packages to `8.0.0-rc.8` for a Composer peer dependency while the site documented rc.9, so fresh scaffolds lagged the site. `0.13.1` (2026-09-17) pins rc.11, which is current today; the lag returns on every release candidate unless the bump is part of the release. Source: `create-prisma/src/constants/dependencies.ts` (lines 8-10 at 0.11.7). - **D18. The MongoDB scaffold writes a `.env` nothing reads.** It contains `DATABASE_URL`; the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file. Source: `create-prisma/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`. - **Node 24.0 to 24.10.** The generated `package.json` declares `^22.18.0 || >=24.11.0` while create-prisma itself accepts `>=22.18.0`. Nobody could say why the 24 sub-range is excluded. Worth a question to the owner. @@ -146,7 +146,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ## Naming -The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Not started; planned as its own PR (A7 has landed, so nothing blocks it). +The product is "Prisma ORM". A version number appears only when two versions are contrasted ("Prisma ORM 7 to 8"). Never "Prisma 8" as a product name. Rule, counts, and exceptions in `naming.md`. Applies to every item above and to the proposed nodes in `ia.md`. Landed as #8246 and #8275. ## Open questions diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 8a7585f1425..0637510798e 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -18,7 +18,7 @@ Prisma ORM + Add to an app you already have empty or no database: orm init, contract, emit, db init, first query, db.ts shown PostgreSQL MongoDB - ~ Adopt an existing database was "Add to Existing Project"; adds baseline, ref, second migration + ~ Adopt an existing database was "Add to Existing Project"; adds what infer produces, what sign checks, the second migration PostgreSQL MongoDB + Coming from Prisma 7 link to the ORM page below, so the Upgrader finds it from here @@ -31,6 +31,8 @@ Four starting states, one group each. "Coming from Prisma 7" is a link node here "A database on your machine" answers the question every starting state runs into on the first page: where does `DATABASE_URL` come from when I have no hosted database. The site already has the answers, `prisma dev` under Local development and the Composer local stack, but a reader inside the ORM subtree never meets them; the quickstart's "Path A" is the only mention. The node names the three options in order of effort (`prisma dev`, Composer, a Postgres you run yourself with Docker Compose), links to the pages that already exist for the first two, gives the Docker Compose file and connection string for the third, and ends with how to look at the data (Studio against the local instance, or any Postgres client). +Every starting-state page also links the runnable example repository for its state (C23), so a reader can check a broken local setup against a known-good one. + ### ORM > Introduction ``` @@ -84,6 +86,7 @@ The ORM line becomes a short row with the four starting states, linking into the | Adopt an existing database (rewritten) | J2 | | Coming from Prisma 7 | J3, J5 (links to the incremental guide), J6 (attribute map) | | A database on your machine | J1, J11 | +| Example repository links on every starting-state page | J12 | | Editor setup | J7 | | Guides labels and overview line | J5 | | Core concepts rewritten | the "written for AI" complaint, by giving the Newcomer a why-first page | @@ -108,6 +111,8 @@ No change to the top-level section list, to Data Modeling, Contract Authoring, F | J8 advanced Postgres | none | no node; needs product answers | | J9 types | none | no node; API in PRs | | J10 opt out of agent files | CLI > configuration | right node, unreachable from Getting Started | +| J11 local database | Local development, Composer (platform sections) | the answers exist; nothing in the ORM subtree points at them | +| J12 runnable example | none | no page links a runnable repository | Two observations follow from the table. diff --git a/docs/orm-docs-audit/journeys.md b/docs/orm-docs-audit/journeys.md index f8ef9eb5c4a..5cfd713d02d 100644 --- a/docs/orm-docs-audit/journeys.md +++ b/docs/orm-docs-audit/journeys.md @@ -1,6 +1,6 @@ # Jobs readers come to the docs to do -Twelve jobs. Each names who does it, what "done" looks like, what the docs must provide for it, and where the site's structure fails it. The jobs are the design input for `ia.md` (which node serves each job) and `changes.md` (which page or ORM change supplies what is missing). Verdicts describe the structure, not the state of any one sentence: **green** a page exists for the job and carries it end to end, **amber** the job can be done but the reader has to assemble it from several places or work around a gap, **red** no page is written for the job. +Twelve jobs. Each names who does it, what "done" looks like, what the docs must provide for it, and where the site's structure fails it. The jobs are the design input for `ia.md` (which node serves each job) and `changes.md` (which page or ORM change supplies what is missing). Verdicts describe the structure, not the state of any one sentence: **green** a page exists for the job and carries it end to end, **amber** the job can be done but the reader has to assemble it from several places or work around a gap, **red** no page is written for the job. Paths and verdicts describe the site on 2026-09-10; `changes.md` tracks what has landed since. ## J1. Add Prisma ORM to an app I already started, with an empty database @@ -22,7 +22,7 @@ Done: contract matches the database, database is signed, first query works, and What the docs must provide: the adoption sequence end to end, including what to expect from `contract infer` (removed attributes, non-`public` schemas, defaults it cannot express, Temporal-backed timestamp types), what `db sign` checks and what its exit codes mean, and whatever makes the next `migration plan` chain from the signed state. -Where the structure fails: the existing-project page stops at "sign, then query". The step that makes the next migration work (today: a baseline migration and `migration ref set db`) is taught only in the incremental upgrade guide, which this reader never sees. That step exists because `db sign` does not record where migrations start from; the design in `brief-db-ref-on-adoption.md` removes it. +Where the structure fails: the existing-project page stops at "sign, then query". At the snapshot, the step that made the next migration work (a baseline migration and `migration ref set db`) was taught only in the incremental upgrade guide, which this reader never sees, and existed because `db sign` did not record where migrations start from. D1 (`brief-db-ref-on-adoption.md`, shipped in rc.10) made `db sign` set the `db` ref, so the page has one step less to carry. Verdict: **red**. IA node: "Adopt an existing database" (C3); ORM change D1. @@ -104,11 +104,11 @@ Who: Newcomer and Upgrader. Done: `type User = ...` and the type of a query result, without reading `contract.d.ts`. -What the docs must provide: a types page with model, result, where, and input types, each beside its Prisma ORM 7 name. The `Models` namespace and `Shape<>` are in `prisma/orm` `main` and ship with the next tagged release; `ResultType` for SQL builder plans exists today. +What the docs must provide: a types page with model, result, where, and input types, each beside its Prisma ORM 7 name. The `Models` namespace, `Scalars<>`, and `Shape<>` shipped in rc.10, and `ResultType` works on ORM queries since the same release. Where the structure fails: no node. -Verdict: **red**. Page: C6, on the release that carries the types. +Verdict: **red**. Page: C6. ## J10. Stop Prisma from writing agent files into my repo @@ -132,7 +132,7 @@ What the docs must provide: one page in the ORM subtree that names the three way Where the structure fails: the answers exist on the site, under Local development and Composer, but those are top-level platform sections. Nothing in the ORM subtree points at them except the quickstart's "Path A", which a reader who arrived at the ORM section from a search result never sees. A reader who wants Docker Compose finds only the Docker deployment guide, which is about shipping, not developing. -Verdict: **red**. IA node: "A database on your machine". +Verdict: **red**. IA node: "A database on your machine" (C22). ## J12. Learn from a runnable example @@ -144,7 +144,7 @@ What the docs must provide: one small example repository per starting state (new Where the structure fails: no page links a runnable repository. The quickstarts are copy-and-paste sequences with no way to check a broken local setup against a known-good one. -Verdict: **red**. IA node: links from every starting-state page; no new node. +Verdict: **red**. IA node: links from every starting-state page (C23); no new node. ## Summary @@ -158,7 +158,7 @@ Verdict: **red**. IA node: links from every starting-state page; no new node. | J6 data types | amber | C1 schema section, C14, C8 | | J7 editor | red | Editor setup (C5) | | J8 advanced Postgres | red | Advanced Postgres (C7) | -| J9 types | red | Types (C6) on the next tagged release | +| J9 types | red | Types (C6) | | J10 agent files | amber / red | the line on scaffold pages; D3 | | J11 local database | red | A database on your machine (C22) | | J12 runnable example | red | example repositories linked from every starting state (C23) | diff --git a/docs/orm-docs-audit/mental-model.md b/docs/orm-docs-audit/mental-model.md index 0522ff5b83a..73157bdf5a9 100644 --- a/docs/orm-docs-audit/mental-model.md +++ b/docs/orm-docs-audit/mental-model.md @@ -59,11 +59,11 @@ Why `db.orm.public.User` and not `prisma.user`: Postgres tables live in schemas, A migration is a step from one contract hash to another. Together they form a graph, not a timestamped list. Every migration records the hash it starts from and the hash it produces. -`migration plan` diffs two contracts and writes a migration package. The target is always your emitted contract. The origin is `--from` if you pass it, otherwise the `db` ref. With neither, the command refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`) when migrations already exist on disk, and plans from an empty database only when the migrations directory is empty. +`migration plan` diffs two contracts and writes a migration package. The target is always your emitted contract. The origin is `--from` if you pass it, otherwise the `db` ref. With neither, the command refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`) when migrations already exist on disk, and plans from an empty database, printing a notice that it did so, only when the migrations directory is empty. -The `db` **ref** is a named pointer to a contract hash, kept in the repo, meaning "the state I consider the database to be at". `db init` and `db update` move it when the connection comes from `prisma.config.ts`; with an explicit `--db` they move it only if `--advance-ref db` is also passed. `db migrate --advance-ref db` moves it. `db sign` does not today; the design in `brief-db-ref-on-adoption.md` makes it do so, so that adopting a database is one step. +The `db` **ref** is a named pointer to a contract hash, kept in the repo, meaning "the state I consider the database to be at". `db init` and `db update` move it when the connection comes from `prisma.config.ts`; with an explicit `--db` they move it only if `--advance-ref db` is also passed. `db migrate --advance-ref db` moves it. `db sign` moves it too, with or without `--db`, and stores the snapshot the ref points at, so adopting a database is one step; `--no-advance-ref` skips that. This is the change `brief-db-ref-on-adoption.md` asked for; it shipped in rc.10. -Why this matters more than it seems: a project with no `db` ref and no migrations on disk plans its first migration from empty, which proposes recreating every table. This is the trap for anyone who adopts an existing database with `db sign` and then runs `migration plan`. The fix today is a baseline migration plus `migration ref set db ` once, then `--advance-ref db` on each migrate. When the graph is empty and the `db` ref names a stored snapshot, `migration plan` writes the baseline for you. +Why this matters more than it seems: a project with no `db` ref and no migrations on disk plans its first migration from empty, which proposes recreating every table. Before rc.10 this was the trap for anyone who adopted an existing database with `db sign` and then ran `migration plan`; the fix was a baseline migration plus `migration ref set db ` once. Now `db sign` sets the ref, and when the graph is empty and the `db` ref names a stored snapshot, `migration plan` writes the baseline for you. What remains on the reader is `--advance-ref db` on each `db migrate`. Why a graph and not a list: two branches can each add a migration, and the graph resolves the merge by hashes instead of by timestamp order. Partial failures are safe to retry because each edge has a verifiable precondition. @@ -75,7 +75,7 @@ Why a graph and not a list: two branches can each add a migration, and the graph | --- | --- | --- | --- | | `contract emit` | contract source | `contract.json`, `contract.d.ts` | after every contract change, before anything else | | `db init` | emitted contract | tables, signature, `db` ref | empty database, first time | -| `db sign` | emitted contract, live schema | signature | adopting a database that already matches | +| `db sign` | emitted contract, live schema | signature, `db` ref | adopting a database that already matches | | `db verify` | emitted contract, live schema | nothing | check for drift | | `db update` | emitted contract, live schema | schema diff, signature, `db` ref | development iteration | | `migration plan` | origin contract, emitted contract | a migration package | change you want checked in | @@ -100,7 +100,7 @@ Why a graph and not a list: two branches can each add a migration, and the graph | `createMany` | `createAll` (rows back) or `createAndCount` (count back) | the return shape is in the name | | `$transaction([...])` | `db.transaction(async tx => ...)` | callback form only | | `@db.Text`, `@db.VarChar(n)` | `Text`, `VarChar(n)` in type position | native types are types, not attributes | -| `Prisma.UserGetPayload<...>` | `Shape<...>`, with the `Models` namespace | in `prisma/orm` `main`; ships with the next tagged release | +| `Prisma.UserGetPayload<...>` | `Shape`; `Scalars<...>` for the plain row | one type per model, derived from `contract.d.ts`; since rc.10 | | `skipDuplicates`, `increment`, `findUniqueOrThrow`, `mode: "insensitive"`, JSON path filters | no equivalent yet (`.all().firstOrThrow()` covers the throw case) | say so plainly | ## The eight words diff --git a/docs/orm-docs-audit/slice-corrections.md b/docs/orm-docs-audit/slice-corrections.md index b283c636cbf..b06a0ea3a17 100644 --- a/docs/orm-docs-audit/slice-corrections.md +++ b/docs/orm-docs-audit/slice-corrections.md @@ -6,7 +6,7 @@ Before any restructure, every factual error on the published Prisma ORM 8 pages |---|---|---| | #8236 | Names, flags, paths, codes, and printed output that no longer exist at rc.9, replaced by the form that does | 40 files, merged 2026-09-10 | | #8237 | Pages whose explanations were wrong (the `db` ref, middleware, raw SQL, relations, aggregates, the existing-project pages) | 31 files, merged 2026-09-11 | -| #8238 | Facts on the getting-started pages and guides (Node floor, MongoDB replica set, create-prisma flags and scripts, the skills page, the tutorial, streaming, `npm create prisma@latest`) | 32 files, open as of 2026-09-11 | +| #8238 | Facts on the getting-started pages and guides (Node floor, MongoDB replica set, create-prisma flags and scripts, the skills page, the tutorial, streaming, `npm create prisma@latest`) | 32 files, merged 2026-09-11 | Out of scope by design: the sixteen Prisma 7 guides under Prisma ORM 8 paths (A7, since landed as #8242), new content (C), the agent skill (D14), the monorepo docs (D17), and the "Prisma 8" to "Prisma ORM" rename. From 3b90c1c9d2cae66f888d6fd20cd739dd02049f27 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 17:05:45 +0200 Subject: [PATCH 32/68] docs(audit): record C13, C14, C16 in review and C15 closed Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 272d1bc0bab..fe91ead2830 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -14,15 +14,16 @@ Status as of 2026-09-21. **Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. -**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C6, C7, C8, C10, C13, C14, C15, C16, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. +**In review.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. + +**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C6, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. ## Recommended order for the open work -1. **Reference completeness, one PR with one commit per item: C13, C14, C15, C16.** These document what already ships, need no product decision, and are verifiable against the rc.11 source. Run every command block, as the migrations pass did. -2. **Re-scope C9, C11, C12** against the ported guides. Expect a short list of gaps rather than new pages. -3. **C7 and C18** as soon as the decisions below land. -4. **The restructure** (A1, A3, A5, A6, A8) as one piece of work, now that the pages it organises exist. -5. **Everything else in C** as its dependency in D clears. +1. **Re-scope C9, C11, C12** against the ported guides. Expect a short list of gaps rather than new pages. +2. **C7 and C18** as soon as the decisions below land. +3. **The restructure** (A1, A3, A5, A6, A8) as one piece of work, now that the pages it organises exist. +4. **Everything else in C** as its dependency in D clears. ## Decisions needed, and from whom @@ -96,10 +97,10 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. - **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` on prisma/orm `main` (#30231 and #30236 merged 2026-09-10); publish when the first tagged release after rc.9 ships them. #30158 (reusable where filter types) is already in rc.9. Also what `contract.d.ts` already exports today. Unblocks J9. -- **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. -- **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. -- **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. -- **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. +- **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. In review as #8306: `orm/reference/migration-api.mdx`. +- **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. In review as #8306, as additions to both pages rather than a rewrite. The PSL README is stale on scalar lists (supported on PostgreSQL) and the Mongo PSL README on collation and partial filters (`@@index` takes both). +- **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. Closed without page changes (see "In review" above); the flat accessor claim in `audit/orm-client.md` does not hold on rc.11. +- **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. In review as #8306: `cli/contract-emit.mdx` "Run it automatically", linked from the artifact page and the three Vite-based framework guides. - **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. - **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. Landed as #8278 (the environment variables reference) and #8280. - **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. Landed over every ORM section: #8251, #8260, #8267, #8271, #8279, #8281, #8292, #8294. The working files for the migrations pass are under `wip/c21/mig/` in the worktree, not in any PR. From 9f14bb85d9a9d30befb56528c4ca3b66aa8817b3 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 17:06:41 +0200 Subject: [PATCH 33/68] docs(audit): the not-started list no longer names C13 to C16 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 48b40637088..7fcf521bed3 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -16,7 +16,7 @@ Status as of 2026-09-21. **In review.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. -**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C13, C14, C15, C16, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. +**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. ## Recommended order for the open work From 3c63c989ac6b17ff01401741291287754064e8aa Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 07:55:44 +0200 Subject: [PATCH 34/68] docs(audit): C13, C14, C16 shipped as #8306 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 7fcf521bed3..c86db41ac8a 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -14,7 +14,7 @@ Status as of 2026-09-21. **Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. -**In review.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. +**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. **Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. @@ -97,10 +97,10 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. - **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` in prisma/orm (#30231 and #30236, shipped in rc.10). #8261 documents `Models`, `Scalars<>`, `Shape<>`, and `ResultType` as a section of `orm/reference/orm-client.mdx` and a row on Coming from Prisma 7; what is left is the page with the Prisma 7 name beside each type, and what `contract.d.ts` exports beyond them. #30158 (reusable where filter types) is in rc.9. Unblocks J9. -- **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. In review as #8306: `orm/reference/migration-api.mdx`. -- **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. In review as #8306, as additions to both pages rather than a rewrite. The PSL README is stale on scalar lists (supported on PostgreSQL) and the Mongo PSL README on collation and partial filters (`@@index` takes both). +- **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. Shipped as #8306: `orm/reference/migration-api.mdx`. +- **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. Shipped as #8306, as additions to both pages rather than a rewrite. The PSL README is stale on scalar lists (supported on PostgreSQL) and the Mongo PSL README on collation and partial filters (`@@index` takes both). - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. Closed without page changes (see "In review" above); the flat accessor claim in `audit/orm-client.md` does not hold on rc.11. -- **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. In review as #8306: `cli/contract-emit.mdx` "Run it automatically", linked from the artifact page and the three Vite-based framework guides. +- **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. Shipped as #8306: `cli/contract-emit.mdx` "Run it automatically", linked from the artifact page and the three Vite-based framework guides. - **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. - **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. Landed as #8278 (the environment variables reference) and #8280. - **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. Landed over every ORM section: #8251, #8260, #8267, #8271, #8279, #8281, #8292, #8294. The working files for the migrations pass are under `wip/c21/mig/` in the worktree, not in any PR. From c2e9053ee5c856fd63e02bbe13238e927e59767a Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 08:38:05 +0200 Subject: [PATCH 35/68] docs(audit): record the migrations decisions and file D9 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index c86db41ac8a..05d4d18bc7a 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -27,16 +27,13 @@ Status as of 2026-09-21. ## Decisions needed, and from whom +The five migrations questions from the C21 handover were decided on 2026-09-22: commit `refs/db.json`; an environment ref names the state the pipeline will migrate to; diverged branches plan one migration from `prod` (prisma/web #8307 applies all three); the `--advance-ref db` default is prisma/orm#30370; and the migrations section gets a cutting round after #8307 lands. + | Item | Decision | Who | |---|---|---| | D4 | For each missing client API: build it, or document the workaround and say it is not planned | ORM product | | C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | ORM product | | C18 | The Bun, Deno, PostgreSQL, and MongoDB floors to publish beside the Node floor already on `release-status` | ORM product | -| migrations | Whether `migrations/app/refs/db.json` (and a `prod` ref) should be committed | Will | -| migrations | Why `--advance-ref db` is not the default in development, so the pages can say so | ORM product | -| migrations | What the `prod` ref means: what is deployed, or what should be, and whether deploys move it | ORM product | -| migrations | Merge migrations (the graph page) or rebase and replan (`migration-review.md`) for diverged histories | ORM product | -| migrations | Whether the migrations section gets a cutting round: about 10,000 words before C21, about 13,800 after | Will | ## A. Restructure @@ -115,7 +112,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan`, `migration ref set db `. Either `db sign` sets the `db` ref when none exists, or a `db adopt` command does sign plus ref. Removes the recreate-everything trap in J2 and halves C3. Landed as prisma/orm#30251: `db sign` sets the `db` ref, with or without `--db`; `--advance-ref ` redirects and `--no-advance-ref` skips. Documented in #8291. Brief in `brief-db-ref-on-adoption.md`. - **D2. `migration plan` with no origin and no migrations on disk plans from empty silently.** With migrations on disk it refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). For a signed database with no ref the silent case is the wrong default; it should warn or refuse the same way. Landed with D1: the plan prints a notice and `--json` carries `fromDefaulted: true`. -- **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. +- **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. Decided 2026-09-22 and filed as prisma/orm#30370: `db migrate` should advance `db` when the connection comes from `prisma.config.ts` and `CI` is unset, never with `--db`, with `--no-advance-ref` to opt out and a failed ref write downgraded to a warning. - **D13. `migration ref set … @db` fails** with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the marker. Support it when a connection is available, or reject it with a message that says why. Source: `cli/src/control-api/operations/ref.ts:104-118`. - **D15. `db update` never plans data operations.** A change that needs a backfill fails and the user must switch to `migration plan`; nothing says so. Allow it, or print the hint. Source: `cli/src/control-api/operations/db-update.ts:17`. - **D16. `migration status` exits 0 on warnings.** CI has to parse `--json`. A `--strict` flag or a non-zero exit on warn-level findings makes C11 one line. Source: `cli/src/orm/migration/status-findings.ts`. From 986371c8a84e39e90032da626beadf73fa6cc204 Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 09:03:26 +0200 Subject: [PATCH 36/68] docs(audit): the migrations cutting round shipped as #8309 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 05d4d18bc7a..2ec6ea6215a 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -27,7 +27,7 @@ Status as of 2026-09-21. ## Decisions needed, and from whom -The five migrations questions from the C21 handover were decided on 2026-09-22: commit `refs/db.json`; an environment ref names the state the pipeline will migrate to; diverged branches plan one migration from `prod` (prisma/web #8307 applies all three); the `--advance-ref db` default is prisma/orm#30370; and the migrations section gets a cutting round after #8307 lands. +The five migrations questions from the C21 handover were decided on 2026-09-22: commit `refs/db.json`; an environment ref names the state the pipeline will migrate to; diverged branches plan one migration from `prod` (prisma/web #8307 applies all three); the `--advance-ref db` default is prisma/orm#30370; and the migrations section had its cutting round as #8309 (merged 2026-09-22): one home per rule, no word ceilings, about 550 words of restatement removed. The reader round after it listed six older gaps on The migration graph and How migrations work, recorded in a comment on #8309: the graph drawing's column symbols, `^`, the `--from` token lists, a `migrate reset` replacement command, `db verify --schema-only`, and the two hashes both called "the hash". | Item | Decision | Who | |---|---|---| From c90dd036cfe3839c5e480c0ec4fbc6364598eb60 Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 12:11:14 +0200 Subject: [PATCH 37/68] docs(audit): C11 and C12 shipped as #8310; C9 re-scope recorded Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 2ec6ea6215a..1ce15c4007f 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -12,9 +12,9 @@ Status as of 2026-09-21. **Shipped on the ORM side.** D1: `db sign` sets the `db` ref (prisma/orm#30251, shipped in rc.10, documented in #8291; the companion repo's `step-3` tag was refreshed). D2's empty-database notice shipped in the same change. D3: create-prisma#96 adds the prompt and `--skills` flag. D14: the skill was brought up to rc.9 in prisma/orm#30250 and #30264 and its upgrade references renamed in #30283. D6: the release candidate stays on `latest`; #8194 pins the Prisma ORM 6 pages to 6.19.3 and points the Prisma ORM 7 CLI commands at `prisma@prev` instead. -**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9, C11, C12: the guides exist since #8242; the re-scope against them has not been done. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. +**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9: the guides exist since #8242 and the re-scope is done; the Cloudflare page needs a serverless-client section and four Hyperdrive facts, and there is no Prisma ORM 8 Vercel page, all waiting on the three product answers noted under 2026-09-22. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. -**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. +**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. C11 and C12 as prisma/web #8310, after the re-scope against the ported guides: the GitHub Actions guide gains a "check a shared database before you migrate it" workflow (`migration status --to --db --json`, fail on any `envelope.diagnostics` entry because the command exits 0 on `MIGRATION.MARKER_NOT_IN_HISTORY`, then `db migrate --to `), the `migration status` reference documents the `--json` shape and the two-line check, Applying a migration carries the pipeline form of its three steps, and Schema changes says what `db verify` adds after `migration check`. The same PR corrects `db.runtime().close()` to `db.close()` on ten guides and the guide-writing page, which the C9 re-scope found and the source decides. C9 itself waits on three product answers from Will (serverless client with the ORM via `@prisma/orm-postgres/orm-client`, the Hyperdrive cursor caveat on `postgresServerless()` only, and whether a Prisma ORM 8 Vercel page is wanted). **Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. From 66fe9f8d71d299c5836be4b849ebed6441e2587b Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 23 Sep 2026 09:05:24 +0200 Subject: [PATCH 38/68] docs(audit): C11 is one db migrate line; skill and npx follow-ups Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 1ce15c4007f..7af0acb19e9 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -14,7 +14,7 @@ Status as of 2026-09-21. **Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9: the guides exist since #8242 and the re-scope is done; the Cloudflare page needs a serverless-client section and four Hyperdrive facts, and there is no Prisma ORM 8 Vercel page, all waiting on the three product answers noted under 2026-09-22. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. -**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. C11 and C12 as prisma/web #8310, after the re-scope against the ported guides: the GitHub Actions guide gains a "check a shared database before you migrate it" workflow (`migration status --to --db --json`, fail on any `envelope.diagnostics` entry because the command exits 0 on `MIGRATION.MARKER_NOT_IN_HISTORY`, then `db migrate --to `), the `migration status` reference documents the `--json` shape and the two-line check, Applying a migration carries the pipeline form of its three steps, and Schema changes says what `db verify` adds after `migration check`. The same PR corrects `db.runtime().close()` to `db.close()` on ten guides and the guide-writing page, which the C9 re-scope found and the source decides. C9 itself waits on three product answers from Will (serverless client with the ORM via `@prisma/orm-postgres/orm-client`, the Hyperdrive cursor caveat on `postgresServerless()` only, and whether a Prisma ORM 8 Vercel page is wanted). +**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. C11 and C12 as prisma/web #8310, after the re-scope against the ported guides: the GitHub Actions guide gains a "migrate a shared database from a workflow" section whose job is the single command `db migrate --to --db "$URL"`, because `db migrate` refuses a database whose marker is outside the history with `MIGRATION.MARKER_MISMATCH` before it runs anything; the `migration status` reference documents its `--json` fields; Applying a migration and Schema changes point at the job. The C11 spec's `migration status --json` parse, taken from the prisma-8 skill, was wrong and the skill is corrected in prisma/orm#30382; prisma/web#8312 replaces `npx prisma@latest` with `npx prisma` after installation across the docs. The same PR corrects `db.runtime().close()` to `db.close()` on ten guides and the guide-writing page, which the C9 re-scope found and the source decides. C9 itself waits on three product answers from Will (serverless client with the ORM via `@prisma/orm-postgres/orm-client`, the Hyperdrive cursor caveat on `postgresServerless()` only, and whether a Prisma ORM 8 Vercel page is wanted). **Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. From 3e5f29a8fbc9b802d5c78a19798dc4589fa1d8ac Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 12:16:13 +0200 Subject: [PATCH 39/68] docs(audit): status as of 2026-09-28, gaps found after the audit, proposed order Rechecks every open item against prisma/web main, prisma/orm main, and create-prisma 0.13.3. Records what shipped since 2026-09-21, marks D16 no longer needed and D4, D5, D11 partly fixed, corrects C22's premise (prisma dev runs a Composer app), adds section E for eleven small gaps the reader rounds found, and proposes an order for the open work. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/README.md | 2 +- docs/orm-docs-audit/changes.md | 115 ++++++++++++++++++++------------- 2 files changed, 70 insertions(+), 47 deletions(-) diff --git a/docs/orm-docs-audit/README.md b/docs/orm-docs-audit/README.md index 1315803bf9c..aaf6835ceb0 100644 --- a/docs/orm-docs-audit/README.md +++ b/docs/orm-docs-audit/README.md @@ -10,7 +10,7 @@ Read in this order: 2. `journeys.md` — twelve jobs those readers come to do, with an entry point, a done criterion, the path through today's pages, and a verdict. 3. `mental-model.md` — the standalone explanation of Prisma ORM 8 (contract, emit, signature, plans, migrations and refs) that pages get written from. 4. `ia.md` — the proposed sidebar trees and `/orm` page structure, then the current state and the reasons. -5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; all three PRs merged), new pages (C), ORM changes (D). Leads with the suggested order. +5. `changes.md` — every proposed change by kind: restructure (A), corrections to existing pages (B; all three PRs merged), new pages (C), ORM changes (D), and small gaps found after the audit (E). Leads with the status, the suggested order, and the decisions that need an owner. 6. `naming.md` — the "Prisma ORM" naming rule. `plain-language.md` — the rule every page must follow so it reads as written by a person for an ordinary user, with the banned-word list and the reader-review step. 7. `slice-corrections.md` — how the section B corrections were sliced, and the decisions taken. 8. `brief-db-ref-on-adoption.md`, `brief-skills-opt-out.md`, `brief-skill-staleness.md` — three ORM-side changes handed to other agents (adoption sets the `db` ref; a skills opt-out in create-prisma; bringing the `prisma-8` agent skill up to rc.9), all since landed; `brief-intermediate-contracts.md` — a docs page to write (C25), landed in #8281. `changes.md` carries the status of each. diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 7af0acb19e9..63564947777 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -1,51 +1,58 @@ # Prisma ORM 8 docs: what to change, and in what order -This is the working list of changes to the Prisma ORM 8 documentation, built from a page-by-page audit against `@prisma/orm-postgres@8.0.0-rc.9` (the audit files are under `audit/`, with a source citation for every finding). Four kinds of change: restructure the site, correct existing pages, write new pages, change the ORM or its tooling where the docs are hard because the tool is. +This is the working list of changes to the Prisma ORM 8 documentation, built from a page-by-page audit against `@prisma/orm-postgres@8.0.0-rc.9` (the audit files are under `audit/`, with a source citation for every finding). Four kinds of change: restructure the site (A), correct existing pages (B), write new pages (C), change the ORM or its tooling where the docs are hard because the tool is (D). Section E lists small gaps found after the audit. Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J12" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. -Status as of 2026-09-21. +Status as of 2026-09-28. ## Where things stand -**Shipped.** Section B, all 35 corrections: prisma/web #8236, #8237, #8238. The naming pass: #8246 and #8275. C1 and C4 as #8245, which also puts "Coming from Prisma 7" at the top of the ORM sidebar (A2). C5 and C20 as #8278 and #8280. C21 over every ORM section: fundamentals #8251, the client reference #8260, the rest of the reference #8267, contract authoring #8271, data modeling #8279, migrations #8281 (which also adds C25), middleware #8292, extensions #8294; backed by the reader-review skill (#8247) and a prose checker that runs in CI (#8290). A7 as #8242 and #8244. Two release syncs (rc.10: #8261, #8262; rc.11: #8277) and a linter that fails CI on a stale pinned version (#8305). +**Shipped.** Section B, all 35 corrections: prisma/web #8236, #8237, #8238. The naming pass: #8246 and #8275. C1 and C4 as #8245, which also puts "Coming from Prisma 7" at the top of the ORM sidebar (A2). C5 and C20 as #8278 and #8280. C21 over every ORM section: fundamentals #8251, the client reference #8260, the rest of the reference #8267, contract authoring #8271, data modeling #8279, migrations #8281 (which also adds C25), middleware #8292, extensions #8294; backed by the reader-review skill (#8247) and a prose checker that runs in CI (#8290). A7 as #8242 and #8244. C13, C14, and C16 as #8306 (every construct run against rc.11); C15 needed no page changes. C11 and C12 as #8310, where C11 took a different shape from its spec: the CI job is the one command `db migrate --to `, because `db migrate` refuses a database whose marker is outside the migration history before it runs anything. The migrations decisions as #8307 and the migrations cutting round as #8309. Every command after installation runs the installed CLI as `npx prisma` (#8312); `db.runtime().close()` became `db.close()` on ten guides (#8310). A linter fails CI on a stale pinned version (#8305). -**Shipped on the ORM side.** D1: `db sign` sets the `db` ref (prisma/orm#30251, shipped in rc.10, documented in #8291; the companion repo's `step-3` tag was refreshed). D2's empty-database notice shipped in the same change. D3: create-prisma#96 adds the prompt and `--skills` flag. D14: the skill was brought up to rc.9 in prisma/orm#30250 and #30264 and its upgrade references renamed in #30283. D6: the release candidate stays on `latest`; #8194 pins the Prisma ORM 6 pages to 6.19.3 and points the Prisma ORM 7 CLI commands at `prisma@prev` instead. +**Kept current with releases.** rc.10 (#8261, #8262), rc.11 (#8277), and rc.12 (#8317), with rc.12's follow-ups: the `module` settings the upgrade guide recommends (#8319), what a CommonJS project changes after `orm init` (#8329), the default table name change and every page re-run against the release (#8326), and a third reader round (#8328). Scaffold commands pass `--no-deploy` so `npm create prisma` does not deploy before the page says to (#8331). The error reference sync, broken from 2026-09-18 by codes without a dot, works again (#8327). The rc.13 sync is open as #8336 and merges when rc.13 is published. -**Partly done.** A1 and A5: `/prisma-orm` now has four doors (create-prisma, quickstart, from scratch as #8302, add to an existing project), but the root page still carries the one-line "Here for the ORM?" pointer. C2: #8302 covers the new-app case; the "project started, database empty" reader still lands on the existing-database page. A6: `orm/core-concepts.mdx` was rewritten as prose in #8234 and #8251 but not from `mental-model.md`; compare before closing it. C18: `orm/release-status.mdx` states the Node and TypeScript floors; nothing states Bun, Deno, PostgreSQL, or MongoDB. C9: the guides exist since #8242 and the re-scope is done; the Cloudflare page needs a serverless-client section and four Hyperdrive facts, and there is no Prisma ORM 8 Vercel page, all waiting on the three product answers noted under 2026-09-22. C17: the syncs added several of the listed flags; the rest is unchecked. C6: the types shipped in rc.10 and #8261 documents them as a section of the client reference and a row on Coming from Prisma 7; the page with the Prisma 7 name beside each type is what is left. +**Shipped on the ORM side.** D1, D2 (prisma/orm#30251, rc.10), D3 (create-prisma#96), D6, and D14 (prisma/orm#30250, #30264, #30283). D16 is no longer needed. D4, D5, and D11 are partly fixed; see each item. -**Shipped 2026-09-22.** C13, C14, and C16 as prisma/web #8306 (one commit each; every construct run against rc.11). C15 needs no page changes: its runtime items were covered by #8260 and #8267, `createInMemoryCacheStore` is not public, and the flat `db.orm.User` accessor is not in rc.11. C11 and C12 as prisma/web #8310, after the re-scope against the ported guides: the GitHub Actions guide gains a "migrate a shared database from a workflow" section whose job is the single command `db migrate --to --db "$URL"`, because `db migrate` refuses a database whose marker is outside the history with `MIGRATION.MARKER_MISMATCH` before it runs anything; the `migration status` reference documents its `--json` fields; Applying a migration and Schema changes point at the job. The C11 spec's `migration status --json` parse, taken from the prisma-8 skill, was wrong and the skill is corrected in prisma/orm#30382; prisma/web#8312 replaces `npx prisma@latest` with `npx prisma` after installation across the docs. The same PR corrects `db.runtime().close()` to `db.close()` on ten guides and the guide-writing page, which the C9 re-scope found and the source decides. C9 itself waits on three product answers from Will (serverless client with the ORM via `@prisma/orm-postgres/orm-client`, the Hyperdrive cursor caveat on `postgresServerless()` only, and whether a Prisma ORM 8 Vercel page is wanted). +**Partly done.** A1: `/prisma-orm` has pages for create-prisma, the quickstart, from scratch, and an existing project, but the sidebar groups them by tool, the empty-database and Prisma 7 starting states have no door, and `/orm` is unchanged. A6: `orm/core-concepts.mdx` is prose but not written from `mental-model.md`; the item lists what it lacks. C2, C3, C6, C7, C8, C10, C17, C18: the facts are on existing pages, but the page each item asks for does not exist; each item says what is left. -**Not started.** A3 (the agent prompt still precedes the framework and fundamentals sections on `/prisma-orm`), A8 (the two error references are both generated now, from prisma-cli and prisma/orm, and still do not name the split). Every remaining new page: C3, C7, C8, C10, C19, C22, C23. On the ORM side: D4, D5, D7, D8, D9, D10, D11, D12, D13, D15, D16, D17, D18. +**Not started.** A3, A5, A8. C9's Vercel page and shutdown example, C19, C22, C23. Every gap in section E. On the ORM side: D7, D8, D9 (prisma/orm#30370 is open), D10 (prisma/orm#30301 and #30308 are open), D12, D13, D15, D17, D18, and the Node 24.0 to 24.10 range. ## Recommended order for the open work -1. **Re-scope C9, C11, C12** against the ported guides. Expect a short list of gaps rather than new pages. -2. **C7 and C18** as soon as the decisions below land. -3. **The restructure** (A1, A3, A5, A6, A8) as one piece of work, now that the pages it organises exist. -4. **Everything else in C** as its dependency in D clears. +Proposed on 2026-09-28, for discussion. + +1. **Release syncs** as each release candidate ships: #8336 for rc.13. +2. **Section E** in one pull request: small, verified gaps on the migration pages and the CLI reference, plus the D17 lines in prisma/orm's `docs/reference/error-reference.md` that the site's error reference is generated from. +3. **The restructure** (A1, A5, A3, A6, A8) as one piece of work, with C2 and C3 as two of its four doors. +4. **C18 and C7** as soon as the decisions below land, and C1's "not in Prisma ORM 8 yet" list as D4's decisions land. +5. **The remaining new pages**: C22, C9, C8, C6, C10 (with draft #8131), C19, C17, and C23 once it has an owner. +6. **ORM side**, in order of how badly each hurts a reader: D10, D9, D15, D13, D12, D7, D18, D11, D5's `public`-only inference, D17, the Node range. ## Decisions needed, and from whom -The five migrations questions from the C21 handover were decided on 2026-09-22: commit `refs/db.json`; an environment ref names the state the pipeline will migrate to; diverged branches plan one migration from `prod` (prisma/web #8307 applies all three); the `--advance-ref db` default is prisma/orm#30370; and the migrations section had its cutting round as #8309 (merged 2026-09-22): one home per rule, no word ceilings, about 550 words of restatement removed. The reader round after it listed six older gaps on The migration graph and How migrations work, recorded in a comment on #8309: the graph drawing's column symbols, `^`, the `--from` token lists, a `migrate reset` replacement command, `db verify --schema-only`, and the two hashes both called "the hash". +The five migrations questions from the C21 handover were decided on 2026-09-22 and applied in #8307 and #8309; the one ORM change among them, `db migrate` advancing the `db` ref by default, is prisma/orm#30370 and still open. | Item | Decision | Who | |---|---|---| -| D4 | For each missing client API: build it, or document the workaround and say it is not planned | ORM product | -| C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | ORM product | -| C18 | The Bun, Deno, PostgreSQL, and MongoDB floors to publish beside the Node floor already on `release-status` | ORM product | +| D4 | For each missing client API (atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path and containment filters, soft delete, validations, callbacks, read replicas, MongoDB referential actions): build it, or document the workaround and say it is not planned | Will | +| C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | Will | +| C18 | The floors to publish: PostgreSQL (stated nowhere), Bun (the site says 1.1 in three guides), Deno (the site says 2.6), MongoDB (8.0, stated only on the MongoDB upgrade guide); and whether ES modules are a requirement, given `cli/orm-init.mdx` documents a working CommonJS setup | Will | +| C9 | Whether a Prisma ORM 8 page for deploying to Vercel is wanted | Will | +| C23 | Where the example repositories live and who keeps them current | Will | +| Node range | Why generated projects exclude Node.js 24.0 to 24.10 | create-prisma owner | ## A. Restructure The proposed sidebar trees and the `/orm` page structure are in `ia.md`. These are the moves that tree implies. -- **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Unblocks J1, J2, J5. Partly landed: `/prisma-orm` has the four doors since #8302; `/orm` and the root page do not. +- **A1. Give the ORM its own front door, organised by starting state.** Replace the quickstart-versus-existing-project split with four doors on `/prisma-orm` and `/orm`: new app from scratch; app already started with an empty database; existing database with data; existing Prisma 7 app. Each door is one page that carries the whole path. Unblocks J1, J2, J5. Partly landed: `/prisma-orm` has the four doors since #8302; `/orm` and the root page do not. Status on 2026-09-28: `(index)/prisma-orm/meta.json` lists release status, supported databases, create-prisma, the quickstart, from scratch, and add to an existing project, grouped by tool. No door exists for an app with an empty database or for a Prisma 7 app, and the `ia.md` links to Coming from Prisma 7, a database on your machine, and editor setup are not in the sidebar. `orm/index.mdx` still has the six old sections, including the three-step workflow and the blog list. - **A2. "Coming from Prisma 7" at the top level of the ORM sidebar**, linked from the root page, `/getting-started`, `/orm`, and reading-data. The fourteen inline diff blocks stay but point at it. Unblocks J3, J4. The page itself is C1. Landed as #8245. -- **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. Not started: on `/prisma-orm` the prompt sits under "Use with your agent" ahead of the framework and fundamentals sections. +- **A3. Human content first, agent prompts last.** `/prisma-orm`, `/getting-started`, and every framework guide open with a copyable agent prompt before any human instruction. Move the prompt to the end or into a collapsed block. This is the direct answer to the "written for AI" complaint. Not started: on `/prisma-orm` the prompt sits under "Use with your agent" ahead of the framework and fundamentals sections. Still true on 2026-09-28: "Use with your agent" comes before the framework and fundamentals sections on `/prisma-orm`, and every framework and runtime guide puts it straight after Prerequisites. The prompt block already renders collapsed (`AgentPrompt`, since #8106); only its position is left. - **A5. Root page: give the ORM a section**, not one line ("Here for the ORM? Jump to Prisma 7 or Prisma 8"). The four doors from A1 in one row. File: `(index)/index.mdx`. Not started. -- **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. #8234 and #8251 rewrote the page as prose; check it against `mental-model.md` before closing this. +- **A6. Rewrite `orm/core-concepts.mdx` as a narrative** from `mental-model.md`. The current page is a glossary; the mental model explains why, in the order a reader meets each piece. Keep the glossary as a closing section. #8234 and #8251 rewrote the page as prose; check it against `mental-model.md` before closing this. Status on 2026-09-28: compared with `mental-model.md`, the page lacks the Prisma 7 contrasts and a link to Coming from Prisma 7, why queries go through `db.orm.public.User`, the origin rules for `migration plan`, the `db` ref as a concept, adoption and the automatic baseline, `db init` as a signature writer, the adoption order (`db sign` first), that a partial failure is safe to retry, the command table, and the closing glossary. - **A7. Move the sixteen Prisma 7 guides out of the Latest tree.** Landed as #8242 (2026-09-11), in a different shape. `guides/frameworks/react-router-7`, `solid-start`, `guides/deployment/*` except Cloudflare D1, `guides/integrations/github-actions`, `ai-sdk`, all of `guides/switch-to-prisma-orm/*` and `guides/database/*` were rewritten for Prisma ORM 8 at the same slugs, each with its Prisma 7 page preserved under `guides/v7/`; Cloudflare D1 moved to `guides/v7/` only (there is no Prisma ORM 8 D1 driver). The Latest sidebar keeps those labels. Thirteen further pages stay in Latest with a "This guide uses Prisma 7" note; #8242 says which are blocked on third-party adapters and which are portable follow-ups. -- **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. Both pages are generated now (from prisma-cli and prisma/orm), so the fix is in the generators. +- **A8. One error reference, or two that link.** `cli/error-reference.mdx` claims to list every CLI code but carries only the platform namespaces; every `MIGRATION.*`, `CONTRACT.*`, `CONFIG.*` code is on `orm/reference/error-reference.mdx`, and the structured errors' `docsUrl` points there. Merge them, or state the split on both and cross-link. Both pages are generated now (from prisma-cli and prisma/orm), so the fix is in the generators. Still true on 2026-09-28: each page says it lists every code, neither names the other, and both have a `CLI` namespace with different codes (30 on the CLI page, 38 on the ORM page). #8327 fixed parsing only. - **A4.** The upgrade-guide sidebar labels landed in #8238; the guides index (the Upgrading section replacing "Coming as they land") landed in #8242. ## B. Corrections to existing pages (all three PRs merged) @@ -73,36 +80,52 @@ Grouped by where the page lives. Each says what the page is for, what it must co ### Entry pages -- **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. #8302 covers the new-app case as `from-scratch`; the empty-database case is still folded into the existing-database page. +- **C2. Add Prisma ORM to an app you already started.** Starts from "you have a project directory and an empty or absent database": `orm init`, edit the contract, `contract emit`, `db init`, one query, with `db.ts` shown. Bun as the worked example, since that is the case reported, with a note for Node. Unblocks J1. Source: `mental-model.md`; the scaffold in `create-prisma`. #8302 covers the new-app case as `from-scratch`; the empty-database case is still folded into the existing-database page. Status on 2026-09-28: still folded into the existing-project page, which covers only a database that already has tables; the empty-database path (`orm init`, then `db init`) appears only in agent prompts and on `cli/orm-init.mdx`. - **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. Landed as #8245. -- **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the `db` ref it now sets, the baseline the first `migration plan` writes, the second migration with `--advance-ref db`. Unblocks J2. D1 has landed, so the page can be short. +- **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the `db` ref it now sets, the baseline the first `migration plan` writes, the second migration with `--advance-ref db`. Unblocks J2. D1 has landed, so the page can be short. Status on 2026-09-28: `add-to-existing-project/postgresql.mdx` now covers the Temporal types after inference, the `db` ref that `db sign` sets, and the automatic baseline; exit code 4 is on `cli/db-sign.mdx`. Left: the page of its own, what `contract infer` captures and that it is SQL-only, and the second migration applied with `db migrate --advance-ref db`. - **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; D6 resolved; landed as #8245. -- **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. -- **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database: `prisma dev` first (a local Prisma Postgres, no install; the page under Local development already exists, link it), then the Composer local stack (`dev`), then a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. -- **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. +- **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. Status on 2026-09-28: `orm/release-status.mdx` states Node.js 22.18 (24.11 on the 24 line) and TypeScript 5.9; the other floors are scattered or missing, as the decision table says. +- **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database. Corrected 2026-09-28: `prisma dev` is not a standalone local Prisma Postgres; it runs a Prisma Composer app from a module entry file (`cli/dev.mdx`), and its local Prisma Postgres serves only that app. For a reader using Prisma ORM on its own, the options are `npx create-db` (hosted and temporary), the Composer local stack if the app is a Composer app, and a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. Not started on 2026-09-28. +- **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. Not started on 2026-09-28; needs an owner (see the decision table). - **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Landed as #8278 (`orm/contract-authoring/editor-support.mdx`). ### Guides -- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. -- **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. -- **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. -- **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. +- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. Status on 2026-09-28: no Prisma ORM 8 page covers deploying to Vercel (`guides/postgres/vercel.mdx` has two short notes), and no Prisma ORM 8 page shows closing the client on shutdown; six guides say to close it on shutdown without showing how. The Cloudflare Workers page is handled separately. +- **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. Landed as #8310 in a different shape: the job is `db migrate --to ` alone, with no `migration status` parse, because `db migrate` refuses a database whose marker is outside the history before it runs anything. +- **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. Landed as #8310: `guides/database/schema-changes.mdx` says what `db verify` adds after `migration check`. +- **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. Status on 2026-09-28: a note in `orm/extensions/using-extensions.mdx` covers the pack, `supabase(...)`, the role helpers, and `SUPABASE.JWT_INVALID`; RLS blocks and `supabase:auth.AuthUser` are on `psl-syntax.mdx`. Left: the page itself (draft #8131 would add one), the session-pooler requirement, the one-time `GRANT` on `auth.*`, and the other `SUPABASE.*` errors. ### Reference completeness -- **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. -- **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. -- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` in prisma/orm (#30231 and #30236, shipped in rc.10). #8261 documents `Models`, `Scalars<>`, `Shape<>`, and `ResultType` as a section of `orm/reference/orm-client.mdx` and a row on Coming from Prisma 7; what is left is the page with the Prisma 7 name beside each type, and what `contract.d.ts` exports beyond them. #30158 (reusable where filter types) is in rc.9. Unblocks J9. +- **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. Status on 2026-09-28: every construct is now in the reference (#8306: `psl-syntax.mdx`, `typescript-schema-builder.mdx`, `migration-api.mdx`). Left: one page for the reader who needs these together, and the supported-or-preview label. +- **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. Status on 2026-09-28: the facts are spread over `orm/data-modeling/index.mdx`, `psl-syntax.mdx`, `sql-query-builder.mdx`, and `orm-client.mdx`. Left: the one page, and the point that a decimal string avoids float loss while the declared scale still rounds, which no page makes. +- **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` in prisma/orm (#30231 and #30236, shipped in rc.10). #8261 documents `Models`, `Scalars<>`, `Shape<>`, and `ResultType` as a section of `orm/reference/orm-client.mdx` and a row on Coming from Prisma 7; what is left is the page with the Prisma 7 name beside each type, and what `contract.d.ts` exports beyond them. #30158 (reusable where filter types) is in rc.9. Unblocks J9. Status on 2026-09-28: the section on `orm/reference/orm-client.mdx` and the row on Coming from Prisma 7 are all there is. Left: the page with the Prisma 7 name beside each type, and the where and input types, which no page shows. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. Shipped as #8306: `orm/reference/migration-api.mdx`. - **C14. PSL and TypeScript builder completeness.** A rewrite of `psl-syntax.mdx` and `typescript-schema-builder.mdx` large enough to plan as one. The PSL page lacks native types in type position, the `@default` generator list, the `temporal.*` presets, scalar lists, `@@unique`, `@@index` options, `@@check`, `@noCheck`, `@@control`, `namespace` blocks, `native_enum`, `@relation("Name")`, `onDelete`/`onUpdate`, inline extension types, MongoDB index options, `.variant()`. The TypeScript page lacks most field helpers, composite keys (`.attributes()`), indexes and checks, `foreignKeyDefaults`, the `output` option, and the MongoDB builder's value objects, indexes, enums, vectors, and polymorphism. The full list is in `audit/contract.md` under Missing. Source: the two `contract-psl` and `contract-ts` READMEs. Shipped as #8306, as additions to both pages rather than a rewrite. The PSL README is stale on scalar lists (supported on PostgreSQL) and the Mongo PSL README on collation and partial filters (`@@index` takes both). - **C15. Runtime reference completeness.** Additions to `transactions-and-runtime.mdx` and `orm-client.mdx`: `query` vs `execute`; `verifyMarker`; `binding`; `db.raw`, `db.nativeEnums`, `db.context`, `db.contract`, `db.stack`; the flat `db.orm.User` accessor for single-namespace contracts; `AsyncIterableResult.first()` / `.firstOrThrow()`; the `configure(meta)` callback and `meta.annotate(...)` (how cache opt-in works); `distinctOn`'s capability; MongoDB `mode` and the extra filter classes; the SQLite facade; the static client; `db.prepare`; `ctx.signal` and `MongoMiddleware`; `createInMemoryCacheStore`. Full list in `audit/orm-client.md` and `audit/builders.md` under Missing. Closed without page changes (see "In review" above); the flat accessor claim in `audit/orm-client.md` does not hold on rc.11. - **C16. Build integration.** The Vite plugin `@prisma/orm-postgres/vite-plugin-contract-emit` (re-emits on save; dev server only) and the `"prebuild": "prisma contract emit"` pattern for every other bundler. Zero hits on the site; the Vite-based framework guides tell readers to run emit by hand. Source: `packages/1-framework/3-tooling/vite-plugin-contract-emit/README.md`. Shipped as #8306: `cli/contract-emit.mdx` "Run it automatically", linked from the artifact page and the three Vite-based framework guides. -- **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. +- **C19. Extension pages beyond pgvector.** PostGIS (`Geometry`, seven operations, the `pg/geometry@1` JSON round-trip exemption), ParadeDB (`key_field`-only), arktype-json (`arktypeJson(schema)`) each have one catalog row. Not started on 2026-09-28. - **C20. Telemetry page.** `cli/telemetry.mdx` omits `DO_NOT_TRACK=1`, `PRISMA_NEXT_DISABLE_TELEMETRY=1`, the per-user config file, that CI never sends, the first-run notice, and the event fields. The rc.9 first-run notice links to `prisma-next.dev/docs/cli/telemetry`, which is not this page. Source: `packages/1-framework/3-tooling/cli-telemetry/src/`. Landed as #8278 (the environment variables reference) and #8280. - **C21. Plain-language pass over the reference and fundamentals pages.** 66 Prisma ORM 8 pages use vocabulary from the source code that readers do not have ("terminal", "codec", "reducer", "refinement callback", "namespace-qualified", "facade", "lane", "surface"). This is the largest complaint about the docs. Every page gets the reader review in `plain-language.md`: an agent with only the Prisma ORM 7 user's knowledge marks every sentence it cannot restate, and each mark is rewritten. Start with `orm/fundamentals/*` and `orm/reference/orm-client.mdx`, which every reader hits. The check script `check-plain.sh` catches the banned words before push; the review catches the rest. Landed over every ORM section: #8251, #8260, #8267, #8271, #8279, #8281, #8292, #8294. The working files for the migrations pass are under `wip/c21/mig/` in the worktree, not in any PR. - **C25. Data transforms that need an intermediate contract.** A migration that both removes a column and has to read it in `dataTransform` cannot type the transform against either the start or the end contract; the planner rejects the query with `PN-MIG-2005`, and authors fall back to raw SQL. The technique that exists today: emit an `intermediate.prisma` inside the migration directory describing the in-between shape, and type the transform against it. Goes on `orm/migrations/editing-a-migration.mdx` next to `dataTransform`, with the `updatedAtString()` trap that makes `ops.json` non-deterministic. Brief: `brief-intermediate-contracts.md`. Landed as part of #8281. -- **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. +- **C17. CLI page additions.** `configuration.mdx`: `migrations.dir`, `formatter`, the `composer` section, the telemetry variables. `orm-init.mdx`: full flag list, exit codes 4 and 5, `prisma-next.md`. `db-update.mdx`: never plans `data`-class operations. `migration-ref.mdx`: the refusals. `migration-new.mdx`: default origin rules. `migration-status.mdx`: `--json` diagnostics. `db-migrate.mdx`: `MIGRATION.MARKER_MISMATCH`, `PATH_UNREACHABLE`. `contract-emit.mdx`: `--json` output, the `output` option. `cli/index.mdx`: `@prisma/orm-toolchain`, `@prisma/orm-framework`. Status on 2026-09-28: `migration-new.mdx` and the `migration-status.mdx` `--json` fields are done. Partly done: `configuration.mdx` (`migrations.dir` only in passing), `orm-init.mdx` (exit codes 4 and 5 only on the error reference), `migration-ref.mdx` (refusals in prose, no codes), `contract-emit.mdx` (`--json` success result). Not done: `db-update.mdx` (never plans `data` operations), `db-migrate.mdx` (`MARKER_MISMATCH`, `PATH_UNREACHABLE`), `cli/index.mdx` (`@prisma/orm-toolchain`, `@prisma/orm-framework`). Whether `formatter` and `composer` are still config keys was not checked. + +## E. Gaps found after the audit + +Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28; none is fixed yet. Each is small and verified. + +- **E1. The migration graph drawing's column symbols.** `orm/migrations/the-migration-graph.mdx` defines `○` and `↑↓⟲` but not `│ │` and `│─╯`, and defers to `--legend`. +- **E2. `^` on The migration graph.** Used twice with no explanation or link; it is explained on `rollbacks-and-recovery.mdx`, `cli/migration-plan.mdx`, and `cli/migration-ref.mdx`. +- **E3. The `--from` forms.** The migration graph page states the accepted forms partially in four places (`migration plan --from`, `ref set`, `migration plan --from @empty`, `migration new --from`). +- **E4. A replacement for `migrate reset`.** `how-migrations-work.mdx` says to drop and recreate the database with your own tools and shows no command. +- **E5. `db verify --schema-only`.** Used on the migration graph page and on How migrations work with no explanation or link. +- **E6. Two hashes.** How migrations work names the contract hash and `migrationHash` without saying what `migrationHash` is computed from, and later accepts a `migrationHash` prefix without contrasting it with a contract hash prefix. +- **E7. `cli/migration-status.mdx`.** No sample output; `--space `, `^`, and `./path` are listed without explanation, and `./path` is explained on no page. +- **E8. "Contract space".** Defined on three migration pages, but not where a reader first meets it: the output on the from-scratch and quickstart pages, `migration status --space`, `cli/index.mdx`, and `cli/db-migrate.mdx`. +- **E9. `orm init` and `init` on the GitHub Actions guide.** The page uses both and never says that `init` installs the agent skills and does not set up the ORM; only `cli/init.mdx` says so. +- **E10. One situation, two codes.** `MIGRATION.MARKER_NOT_IN_HISTORY` from `migration status` and `MIGRATION.MARKER_MISMATCH` from `db migrate` describe the same database; no page links them, and the two error reference entries give different fixes. +- **E11. The error reference names the wrong source repository.** The header `apps/docs/scripts/generate-error-reference.mjs` writes into `orm/reference/error-reference.mdx` points at `prisma/prisma`; the repository is `prisma/orm`. ## D. Change the ORM and its tooling @@ -112,27 +135,27 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D1. Make adoption one step.** Today: `contract infer`, edit, `contract emit`, `db sign`, `migration plan`, `migration ref set db `. Either `db sign` sets the `db` ref when none exists, or a `db adopt` command does sign plus ref. Removes the recreate-everything trap in J2 and halves C3. Landed as prisma/orm#30251: `db sign` sets the `db` ref, with or without `--db`; `--advance-ref ` redirects and `--no-advance-ref` skips. Documented in #8291. Brief in `brief-db-ref-on-adoption.md`. - **D2. `migration plan` with no origin and no migrations on disk plans from empty silently.** With migrations on disk it refuses (`MIGRATION.PLAN_ORIGIN_UNKNOWN`). For a signed database with no ref the silent case is the wrong default; it should warn or refuse the same way. Landed with D1: the plan prints a notice and `--json` carries `fromDefaulted: true`. -- **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. Decided 2026-09-22 and filed as prisma/orm#30370: `db migrate` should advance `db` when the connection comes from `prisma.config.ts` and `CI` is unset, never with `--db`, with `--no-advance-ref` to opt out and a failed ref write downgraded to a warning. -- **D13. `migration ref set … @db` fails** with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the marker. Support it when a connection is available, or reject it with a message that says why. Source: `cli/src/control-api/operations/ref.ts:104-118`. -- **D15. `db update` never plans data operations.** A change that needs a backfill fails and the user must switch to `migration plan`; nothing says so. Allow it, or print the hint. Source: `cli/src/control-api/operations/db-update.ts:17`. -- **D16. `migration status` exits 0 on warnings.** CI has to parse `--json`. A `--strict` flag or a non-zero exit on warn-level findings makes C11 one line. Source: `cli/src/orm/migration/status-findings.ts`. +- **D9. `--db` suppresses `db` ref advancement.** `db init` and `db update` advance the ref only when the URL comes from config; with `--db` they do not unless `--advance-ref` is also passed. Surprising, and every example passes `--db`. Advance regardless, or warn when `--db` is used without `--advance-ref` and no ref exists. Source: `cli/src/control-api/operations/ref-advancement.ts:19-28`. Decided 2026-09-22 and filed as prisma/orm#30370: `db migrate` should advance `db` when the connection comes from `prisma.config.ts` and `CI` is unset, never with `--db`, with `--no-advance-ref` to opt out and a failed ref write downgraded to a warning. Still open on 2026-09-28. +- **D13. `migration ref set … @db` fails** with `MIGRATION.HASH_NOT_IN_GRAPH` instead of reading the marker. Support it when a connection is available, or reject it with a message that says why. Source: `cli/src/control-api/operations/ref.ts:104-118`. Still open on 2026-09-28: `@db` resolves to an empty hash and fails as `errorRefSetHashNotInGraph('')` (`migration/src/refs/contract-ref.ts:50-56`, `cli/src/control-api/operations/ref.ts:98-112`). +- **D15. `db update` never plans data operations.** A change that needs a backfill fails and the user must switch to `migration plan`; nothing says so. Allow it, or print the hint. Source: `cli/src/control-api/operations/db-update.ts:17`. Still open on 2026-09-28: `db update` plans only the additive, widening, and destructive classes and prints no pointer to `migration plan`. +- **D16. `migration status` exits 0 on warnings.** CI has to parse `--json`. A `--strict` flag or a non-zero exit on warn-level findings makes C11 one line. Source: `cli/src/orm/migration/status-findings.ts`. No longer needed: the CI job is `db migrate --to `, which refuses a database whose marker is outside the history before it runs anything (prisma/web #8310; the skill says the same since prisma/orm#30382). `migration status` exiting 0 on its `warn` findings is deliberate. - **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. -- **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. -- **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. -- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. -- **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. +- **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. Still open on 2026-09-28: `postgres()` takes no `mode`, so the runtime is always strict; at `main` only budgets read `ctx.mode`, not lints. +- **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. Still open on 2026-09-28: on PostgreSQL `runtime()` returns a `Runtime` and `prepare` exists; on MongoDB `runtime()` returns a promise and there is no `prepare`; `prepare` followed by `connect()` still throws `DRIVER.ALREADY_CONNECTED`. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. Still open on 2026-09-28: `contract infer` still maps `timestamptz` to the Temporal-backed `Timestamptz` (the map moved to `psl-build/postgres-type-map.ts:32-33`), the Prisma 7 route in `orm init` maps `DateTime` to the Temporal-backed `Timestamp(3)`, and `orm init` neither installs nor imports `temporal-polyfill`. prisma/orm#30301 and #30308 (infer `timestamptz` as `TimestamptzString`) are open. +- **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. Partly fixed by 2026-09-28: `contract infer` writes native types in type position (`VarChar(32)`, `Numeric(10, 2)`), never `@db.*`, and a hand-written `@db.*` gets an error naming the replacement; `Decimal` defaults keep their digits (prisma/orm#30350, rc.12); `dbgenerated` became sql tagged literals (#30380). Still open: `contract infer` reads only the `public` schema. For Prisma 7 projects the route changed: since prisma/orm#30291 (rc.12) `orm init` reads `schema.prisma` through `prisma7Schema(...)`, which accepts `@db.*` and `@@schema`, instead of inferring from the database. Not verified end to end against a real Prisma 7 database. ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. Status on 2026-09-28: insert-and-skip-conflicts landed as `createAll(rows, { onConflict: 'skip', conflictOn? })` and `createAndCount` (prisma/orm#30365, rc.12); the field filters have `.ilike(pattern)` and, since rc.12, full-text search operations. Still absent on SQL: atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path or containment filters, soft delete, validations, lifecycle callbacks, read replicas. MongoDB has `inc` and `mul`; MongoDB referential actions are still unsupported, and the Prisma 6 schema reader now rejects `onDelete` and `onUpdate` explicitly (prisma/orm#30405). - **D6. The npm `latest` tag.** `prisma@latest` is the Prisma ORM 8 CLI (8.0.0-rc.15 on 2026-09-21) while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. Resolved: the tag stays; #8194 pins the Prisma ORM 6 pages to 6.19.3 and the Prisma ORM 7 CLI commands to `prisma@prev`. ### create-prisma - **D3. Opt out of agent files at scaffold time.** No flag exists; every scaffold writes all four agent directories plus a `postinstall` hook. Add a prompt and `--skills none`, and have `orm init` ask. Landed as create-prisma#96. Brief in `brief-skills-opt-out.md`. -- **D11. create-prisma pins an older release candidate.** `create-prisma@0.11.7` pinned the ORM packages to `8.0.0-rc.8` for a Composer peer dependency while the site documented rc.9, so fresh scaffolds lagged the site. `0.13.1` (2026-09-17) pins rc.11, which is current today; the lag returns on every release candidate unless the bump is part of the release. Source: `create-prisma/src/constants/dependencies.ts` (lines 8-10 at 0.11.7). -- **D18. The MongoDB scaffold writes a `.env` nothing reads.** It contains `DATABASE_URL`; the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file. Source: `create-prisma/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`. -- **Node 24.0 to 24.10.** The generated `package.json` declares `^22.18.0 || >=24.11.0` while create-prisma itself accepts `>=22.18.0`. Nobody could say why the 24 sub-range is excluded. Worth a question to the owner. +- **D11. create-prisma pins an older release candidate.** `create-prisma@0.11.7` pinned the ORM packages to `8.0.0-rc.8` for a Composer peer dependency while the site documented rc.9, so fresh scaffolds lagged the site. `0.13.1` (2026-09-17) pins rc.11, which is current today; the lag returns on every release candidate unless the bump is part of the release. Source: `create-prisma/src/constants/dependencies.ts` (lines 8-10 at 0.11.7). Partly fixed on 2026-09-28: create-prisma 0.13.3 pins `8.0.0-rc.12` and `prisma` `8.0.0-rc.17`, both npm `latest`, but the bump is still manual (create-prisma#113 came four days after rc.12), and its `check:pins` script checks the toolchain match, not npm `latest`, so the lag returns with rc.13. +- **D18. The MongoDB scaffold writes a `.env` nothing reads.** It contains `DATABASE_URL`; the generated `prisma.config.ts` reads `MONGODB_URL` and loads no dotenv file. Source: `create-prisma/templates/create/_shared/prisma.config.ts.hbs:13,31`, `src/tasks/prisma-setup/project-files.ts:22-26`. Still open on 2026-09-28. +- **Node 24.0 to 24.10.** The generated `package.json` declares `^22.18.0 || >=24.11.0` while create-prisma itself accepts `>=22.18.0`. Nobody could say why the 24 sub-range is excluded. Worth a question to the owner. Still open on 2026-09-28: generated projects declare `^22.18.0 || >=24.11.0` and a test asserts it, while create-prisma and `prisma@8.0.0-rc.17` accept `>=22.18.0`. ### The agent skill @@ -140,7 +163,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Monorepo docs hygiene -- **D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` disagrees with the site's capabilities page on key namespacing, pack key nesting, the error code spelling, and whether capabilities are fixed at emit or negotiated at connect. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`, which does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md`, from which the site's error reference is generated verbatim, still says `ref set` and `prisma ref set` in eight entries (the command is `migration ref set` since rc.5). `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Until reconciled, the audit treats `packages/` and `docs/releases/` as the only truth. +- **D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` disagrees with the site's capabilities page on key namespacing, pack key nesting, the error code spelling, and whether capabilities are fixed at emit or negotiated at connect. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`, which does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md`, from which the site's error reference is generated verbatim, still says `ref set` and `prisma ref set` in eight entries (the command is `migration ref set` since rc.5). `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Until reconciled, the audit treats `packages/` and `docs/releases/` as the only truth. Rechecked on 2026-09-28: all five claims still hold, and `error-reference.md` now has nine bare `ref set` lines, two of them `prisma ref set`. ## Naming From 0f60952f60f944544c50ca99daee1b429f039e6b Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 12:42:41 +0200 Subject: [PATCH 40/68] docs(audit): slice spec for the migration and CLI reference gaps Section E of changes.md as one prisma/web slice, with every fact run against prisma 8.0.0-rc.17 and @prisma/orm-postgres 8.0.0-rc.12 on PostgreSQL 15: the accepted contract reference forms per command, the migrate reset replacement and the public-schema trap, what migrationHash covers, and the ./path form no command accepts. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- .../slices/01-migration-and-cli-gaps/spec.md | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md diff --git a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md new file mode 100644 index 00000000000..ba1ade9934e --- /dev/null +++ b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md @@ -0,0 +1,161 @@ +# Slice: close the gaps on the migration pages and the CLI reference + +_(Parent project: the Prisma ORM 8 docs audit, `docs/orm-docs-audit/` on branch `docs/orm8-docs-audit-design`, open as prisma/web#8243. This slice closes section E of `changes.md` and removes a contract reference form that no command accepts.)_ + +## At a glance + +One prisma/web pull request that fixes eleven small, verified gaps on the Prisma ORM 8 migration pages and CLI reference pages. Each gap is a place where a reader meets a symbol, token, term, or hash the page never explains, or a command the page tells them to run without showing it. The same pull request corrects the contract reference forms listed on five CLI pages: they advertise a `./path` form that no command accepts, and two of them omit `^` where it works. Every fact below was checked on 2026-09-28 by running `prisma@8.0.0-rc.17` with `@prisma/orm-postgres@8.0.0-rc.12` against PostgreSQL 15. + +## Terms used in this spec + +- **Contract state**: one version of the contract, identified by its storage hash (64 hex characters). +- **Contract reference**: the text a command accepts to name a contract state, for example a hash prefix or a ref name. +- **Marker**: the row in the database that records which contract state it matches. On PostgreSQL it lives in the `prisma_contract.marker` table. +- **Contract space**: a separate migration history with its own directory under `migrations/`. The app's is `migrations/app/`; an extension package that ships migrations, such as pgvector, has its own. +- **`^`**: a migration directory name followed by `^`, naming the contract state before that migration (its `from` hash). A bare directory name names the state after it (its `to` hash). + +## Chosen design + +All paths are under `apps/docs/content/docs/`. Change only the Prisma ORM 8 tree; never touch `orm/v6/`, `orm/v7/`, or any other `v7/` folder. Line numbers are from `main` at `142c18b4d` and are for orientation only; find each passage by its text. + +### E1. Explain the lane lines in the migration graph drawing + +File: `orm/migrations/the-migration-graph.mdx`, the paragraph right after the drawing in "A worked example" (it starts "Read it from the bottom up"). + +The CLI's `--legend` output explains `○`, `↑`, `↓`, `⟲`, `✓`, `⧗`, `∅`, the `@` markers, and ref labels. It does not explain the lane lines, and the page currently tells readers `--legend` covers "the other symbols". Add, after the sentence about `↑` rows: each column is a lane, one per branch of the history; a `│` carries a lane up past rows that belong to another lane; `╯` with `─` joins a lane to the state it starts from, so `│─╯` above `4437973` shows that the right-hand lane (Bob's migration) starts from the same state as the left-hand one (Alice's). Change "and `--legend` prints a key to the other symbols" to say that `--legend` prints a key to the row symbols (`○`, the arrows, `✓` and `⧗`, `∅`, and the labels). + +### E2. Define `^` where The migration graph first uses it + +File: `orm/migrations/the-migration-graph.mdx`, the paragraph starting "To say which state a ref should point at". At its first mention, say that `^` is a migration directory name followed by `^`, and names the contract state before that migration, while the directory name alone names the state after it. The later use in the "Common tasks" table then needs no change. + +### E3. State the accepted contract reference forms once, in a table + +File: `orm/migrations/the-migration-graph.mdx`, section "Name important states with refs". Replace the paragraph that starts "Not every command takes every token" with one sentence introducing a table, the table below, and then the existing `db migrate --show --from @contract --to prod` example sentence. Shorten the `ref set` sentence in the paragraph above it to the command's purpose plus "the table below lists the forms it accepts". In section "Adding a migration you write yourself", keep the explanation of what `migration new --from` takes, and add a link to the table. + +| Command and option | Accepts | +| --- | --- | +| `migration plan --from`, `--to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty` | +| `migration new --from` | a hash, or a prefix of one, that an existing migration ends at | +| `migration ref set ` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | +| `migration status --from`, `--to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty` | +| `db migrate --to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, or `@empty` | +| `db migrate --show --from` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, `@db`, or `@empty` | +| `db update --to` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | +| `db sign [contract]`, `--contract` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | + +A hash prefix is the first 6 or more characters, matching exactly one contract state. No command accepts a file path. + +### E4. Show the commands that replace `migrate reset` + +File: `orm/migrations/how-migrations-work.mdx`, the bullet that starts "`migrate reset` has no equivalent" in the list of Prisma ORM 7 commands. Prisma ORM 7's `migrate reset` was PostgreSQL-only, so this bullet covers PostgreSQL only. Keep "has no equivalent", then show the sequence as a code block, with `mydb` as the database name: + +```bash +dropdb --if-exists mydb +createdb mydb +npx prisma db migrate --advance-ref db +``` + +Then state: `npx prisma db init` in place of the last line creates what the contract declares without running the migrations; `db migrate` does not run a seed script, so run yours afterwards; if you cannot drop the database, drop both the `public` schema and the `prisma_contract` schema, because dropping only `public` leaves the marker, and `db migrate` then reports `Already up to date` on an empty database while `db verify` fails. + +### E5. Say what `db verify --schema-only` checks where it is used + +Files: `orm/migrations/the-migration-graph.mdx` (section "History you can trust") and `orm/migrations/how-migrations-work.mdx` (the paragraph about a `phone` column of another type). At each use, say it compares the tables with the contract and skips the marker check, and link `/cli/db-verify`. + +### E6. Say what `migrationHash` is, and that it is not a contract hash + +File: `orm/migrations/how-migrations-work.mdx`. + +- In the `migration.json` list, the item "its own hash, `migrationHash`, which `npx prisma migration check` reads" becomes: its own hash, `migrationHash`, computed from the rest of `migration.json` and from `ops.json`, so it changes when either file changes; `npx prisma migration check` recomputes it to find edited files. +- After the sentence that says `` can be "the first 6 or more characters of its `migrationHash`", add that this is the migration's own hash, not a contract hash: `migration show` takes a `migrationHash` prefix, while `--from` and `--to` take contract hash prefixes. + +### E7. Complete `cli/migration-status.mdx` + +- Add a "Sample output" subsection at the start of "Reading the result", with output you capture yourself from `npx prisma migration status` against a database with one migration applied and one pending, in the same shape as this capture: + + ```text + │ migrations: migrations + │ database: postgresql://****@localhost:54329/gaps + + ○ 3008325 @contract + │↑ 20260928T1034_add_user_phone b5ae4e6 → 3008325 1 ops ⧗ pending + ○ b5ae4e6 @db (db) + │↑ 20260928T1033_baseline ∅ → b5ae4e6 3 ops + ○ ∅ + + ⚠ 1 pending — run `{bin} db migrate --to 300832575ace` + ``` + + Then say it is read from the bottom up and link the reading guide in `/orm/migrations/applying-a-migration#check-before-preview-then-apply`. Say that `{bin}` is the CLI's placeholder for however you ran it, as `guides/database/schema-changes.mdx` already does. +- `--space ` row: the id is the contract space's directory name under `migrations/`, `app` for your own migrations; link the contract space definition (see E8). +- `--to` row: "Sets the target contract state. Accepts a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty`", linking the E3 table. +- `--from` row: keep the offline sentence, and say it accepts the same forms as `--to`. + +### E8. Define "contract space" where readers first meet it + +Use this definition, with a link to the Terms table on `orm/migrations/the-migration-graph.mdx`: "A contract space is a separate migration history. Your own migrations are in the `app` space, in `migrations/app/`, and each extension package that ships migrations, such as pgvector, has its own." + +Add it, or a link to it, at: the first prose paragraph after the `db init` output on `(index)/prisma-orm/from-scratch.mdx`; the sentence about the summary line on `(index)/prisma-orm/quickstart/mongodb.mdx`, where the definition ends after "in `migrations/app/`" because pgvector is a PostgreSQL extension and that page is MongoDB-only; the `--space` row on `cli/migration-status.mdx`; the opening paragraph of `cli/db-migrate.mdx`, replacing "(app and extensions)"; and `cli/index.mdx`, wherever the page first uses the term. + +### E9. Say how `init` differs from `orm init` on the GitHub Actions guide + +File: `guides/integrations/github-actions.mdx`, in "Prompt your coding agent", where `npx prisma@latest init` is introduced. Add that `init` installs the Prisma agent skills and does not set up Prisma ORM, which `orm init` did in step 2.1, linking `/cli/init`. + +### E10. Say that two codes describe the same situation + +- `orm/migrations/rollbacks-and-recovery.mdx`, section "Drift", the paragraph about the first kind of drift: after the sentence naming `MIGRATION.MARKER_MISMATCH`, add that when `npx prisma migration status` warns with `MIGRATION.MARKER_NOT_IN_HISTORY`, it has found this same situation, and the next `db migrate` fails with `MIGRATION.MARKER_MISMATCH`. +- `cli/migration-status.mdx`, where `MIGRATION.MARKER_NOT_IN_HISTORY` is named: add the same link in the other direction, pointing at the Drift section. + +Word both so they hold whether or not `migration status` warns in every such case: a fix in prisma/orm that makes it warn whenever the marker is outside the history is in review, and the site must stay true before and after it ships. + +### E11. Point the ORM error reference at the right repository + +The repository `prisma/prisma` was renamed `prisma/orm`; the old name works only through GitHub's redirect. + +- `apps/docs/scripts/generate-error-reference.mjs`: the `orm` target's `sourceRepo` is `"prisma/prisma"`. Change it to `"prisma/orm"`, together with the comment at the top of the file and the intro sentence that names the repository. +- `.github/workflows/sync-error-reference-docs.yml` and `.github/workflows/error-reference-check.yml`: change `repository: prisma/prisma` to `repository: prisma/orm`, and `prisma/prisma` to `prisma/orm` in step names and comments. Keep `path: prisma-src`, so the scripts' `--source` paths do not change. Then regenerate `orm/reference/error-reference.mdx` with the script, the way `.github/workflows/sync-error-reference-docs.yml` runs it, and confirm the only change to that page is the repository name. The `cli` target (`prisma/prisma-cli`) is correct; leave it. + +### Contract reference forms on the CLI pages + +Match each option row to the E3 table: + +- `cli/db-migrate.mdx`: `--to` row, remove `./path`, add `@contract` and `@empty`; `--from` row, list the forms from the E3 table. +- `cli/db-update.mdx`: `--to` row, remove `./path`, add `^`. +- `cli/db-sign.mdx`: the `[contract]` row and the `--contract` row both list the forms from the E3 table. Delete "Also accepts the `^` and `./path` forms that the positional argument does not"; the positional argument accepts `^` too. +- `cli/migration-plan.mdx`: `--from` row, remove `./path`. +- `cli/migration-status.mdx`: covered by E7. + +## Coherence rationale + +Every change is a sentence, a table, or a table row on the migration pages and the CLI reference, found by the same reader rounds and verified against the same release. One reviewer can check each against the CLI in one sitting, and the E3 table is the single source the other form lists defer to, so splitting it from the CLI page rows would leave the site contradicting itself between merges. + +## Scope + +**In:** the eleven gaps above and the contract reference rows on five CLI pages; the generator script and the two error reference workflows for E11, and regenerating `orm/reference/error-reference.mdx`. + +**Out:** anything under `v6/` or `v7/`; the text of individual error entries on `orm/reference/error-reference.mdx`, which is generated from `docs/reference/error-reference.md` in prisma/orm and is fixed there (item D17 in `changes.md`); the CLI's help text and `migration status` behaviour, which prisma/orm is fixing in a separate pull request; the restructure (section A); new pages (section C); cross-linking the two error reference pages (item A8). + +## Pre-investigated edge cases + +| Edge case | Disposition | Notes | +| --- | --- | --- | +| `migration status` and `migration status --from` without a database | `--from` runs with no database; `--to` alone needs one | Verified with an unreachable `--db`: `--from --to ` returned the pending count. | +| `@contract` and `@db` on `migration status` | Do not list them for `migration status` | Rejected today (`MIGRATION.REF_NOT_FOUND`) or mishandled; the prisma/orm fix adds them, and the release sync that ships it updates the E3 table. | +| `db update --to @empty` | Do not list `@` tokens for `db update` | Crashes with `CLI.UNEXPECTED` today; the prisma/orm fix rejects them with a structured error. | +| Dropping only the `public` schema | The E4 text must warn against it | Verified: the marker survives in `prisma_contract`, `db migrate` reports `Already up to date` on an empty database, and `db verify` fails with `CONTRACT.SCHEMA_VERIFICATION_FAILED`. | +| Hashes in sample output | Capture your own run; do not copy hashes from other pages | Hashes differ per contract; the E7 capture above is a shape reference only. | + +## Slice-specific done conditions + +- [ ] Every command, flag, token, and form named in the diff was run by the implementer against the published CLI (`prisma` npm `latest`) and PostgreSQL, and the pull request description lists the versions and what was run. +- [ ] No page under `apps/docs/content/docs/`, outside `v6/` and `v7/`, lists `./path` as a contract reference form. +- [ ] The changed pages pass `.claude/skills/docs-reader-review` (its three scripts and at least two cold reader rounds with `references/reader-persona.md`), `pnpm lint:links` in `apps/docs` after `npx -y pnpm@11.22.0 exec fumadocs-mdx`, and the prose checker CI runs. + +## Open questions + +None. Wording is the implementer's within the docs-reader-review rules; the facts above are fixed. A fact that does not hold when the implementer runs it is a stop condition: report it instead of rewording around it. + +## References + +- Parent project status and section E: [`../../changes.md`](../../changes.md) +- Plain-language rules: [`../../plain-language.md`](../../plain-language.md) +- Reader review: `.claude/skills/docs-reader-review/` on prisma/web `main` From 81d6804d918fe9d935a5c8cc959ad1b6a958c014 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 13:03:37 +0200 Subject: [PATCH 41/68] docs(audit): slice spec lists what db migrate --to accepts without --show Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- .../slices/01-migration-and-cli-gaps/spec.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md index ba1ade9934e..631e50413b9 100644 --- a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md +++ b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md @@ -38,7 +38,8 @@ File: `orm/migrations/the-migration-graph.mdx`, section "Name important states w | `migration new --from` | a hash, or a prefix of one, that an existing migration ends at | | `migration ref set ` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | | `migration status --from`, `--to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty` | -| `db migrate --to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, or `@empty` | +| `db migrate --to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty` | +| `db migrate --show --to` | the same, and `@contract` | | `db migrate --show --from` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, `@db`, or `@empty` | | `db update --to` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | | `db sign [contract]`, `--contract` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | @@ -118,7 +119,7 @@ The repository `prisma/prisma` was renamed `prisma/orm`; the old name works only Match each option row to the E3 table: -- `cli/db-migrate.mdx`: `--to` row, remove `./path`, add `@contract` and `@empty`; `--from` row, list the forms from the E3 table. +- `cli/db-migrate.mdx`: `--to` row, remove `./path`, add `@empty`, and say that with `--show` it also accepts `@contract`; `--from` row, list the forms from the E3 table. - `cli/db-update.mdx`: `--to` row, remove `./path`, add `^`. - `cli/db-sign.mdx`: the `[contract]` row and the `--contract` row both list the forms from the E3 table. Delete "Also accepts the `^` and `./path` forms that the positional argument does not"; the positional argument accepts `^` too. - `cli/migration-plan.mdx`: `--from` row, remove `./path`. @@ -132,14 +133,14 @@ Every change is a sentence, a table, or a table row on the migration pages and t **In:** the eleven gaps above and the contract reference rows on five CLI pages; the generator script and the two error reference workflows for E11, and regenerating `orm/reference/error-reference.mdx`. -**Out:** anything under `v6/` or `v7/`; the text of individual error entries on `orm/reference/error-reference.mdx`, which is generated from `docs/reference/error-reference.md` in prisma/orm and is fixed there (item D17 in `changes.md`); the CLI's help text and `migration status` behaviour, which prisma/orm is fixing in a separate pull request; the restructure (section A); new pages (section C); cross-linking the two error reference pages (item A8). +**Out:** anything under `v6/` or `v7/`; the text of individual error entries on `orm/reference/error-reference.mdx`, which is generated from `docs/reference/error-reference.md` in prisma/orm and is fixed there (item D17 in `changes.md`); the CLI's help text and its handling of `@contract`, `@db`, and `@empty`, which prisma/orm#30475 fixes; the restructure (section A); new pages (section C); cross-linking the two error reference pages (item A8). ## Pre-investigated edge cases | Edge case | Disposition | Notes | | --- | --- | --- | | `migration status` and `migration status --from` without a database | `--from` runs with no database; `--to` alone needs one | Verified with an unreachable `--db`: `--from --to ` returned the pending count. | -| `@contract` and `@db` on `migration status` | Do not list them for `migration status` | Rejected today (`MIGRATION.REF_NOT_FOUND`) or mishandled; the prisma/orm fix adds them, and the release sync that ships it updates the E3 table. | +| `@contract` and `@db` on `migration status` and on `db migrate --to` without `--show` | Do not list them there | Rejected today (`MIGRATION.REF_NOT_FOUND`) or mishandled (`--to @db` fails with `MIGRATION.PATH_UNREACHABLE`); prisma/orm#30475 fixes both, and the release sync that ships it updates the E3 table and the CLI rows. | | `db update --to @empty` | Do not list `@` tokens for `db update` | Crashes with `CLI.UNEXPECTED` today; the prisma/orm fix rejects them with a structured error. | | Dropping only the `public` schema | The E4 text must warn against it | Verified: the marker survives in `prisma_contract`, `db migrate` reports `Already up to date` on an empty database, and `db verify` fails with `CONTRACT.SCHEMA_VERIFICATION_FAILED`. | | Hashes in sample output | Capture your own run; do not copy hashes from other pages | Hashes differ per contract; the E7 capture above is a shape reference only. | From 171627e46b032331fc78d150b48fbd11e892cc80 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 13:03:50 +0200 Subject: [PATCH 42/68] docs(audit): section E points at its slice spec and the CLI fix Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 63564947777..97431d7cdca 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -113,7 +113,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co ## E. Gaps found after the audit -Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28; none is fixed yet. Each is small and verified. +Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28; none is fixed yet. Each is small and verified. Specified as one slice in `slices/01-migration-and-cli-gaps/spec.md`, which also removes a `./path` contract reference form that five CLI pages list and no command accepts. Grounding the slice found CLI defects in the same area (`./path` in the CLI's help text, `@contract` and `@db` refused or mishandled by `migration status`, `db migrate`, and `db update`, and `migration status` reporting `Up to date` right after `db update`), fixed in prisma/orm#30475. - **E1. The migration graph drawing's column symbols.** `orm/migrations/the-migration-graph.mdx` defines `○` and `↑↓⟲` but not `│ │` and `│─╯`, and defers to `--legend`. - **E2. `^` on The migration graph.** Used twice with no explanation or link; it is explained on `rollbacks-and-recovery.mdx`, `cli/migration-plan.mdx`, and `cli/migration-ref.mdx`. From 8787a75255020d31b631f7e67f68a95c697749ed Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 16:42:09 +0200 Subject: [PATCH 43/68] docs(audit): record Will's decisions on C7, C18, C9, and C23; add E12 C7 supported with a Limitations section; the C18 floors; a Vercel guide; examples in prisma/prisma-examples and never in prisma/orm, which adds E12 (four pages link prisma/orm examples) to section E and to the slice spec. ORM-side choices move to section D as suggestions (D4, new D19), so no docs item waits on a decision. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 35 ++++++++++--------- .../slices/01-migration-and-cli-gaps/spec.md | 14 ++++++-- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 97431d7cdca..01c52318d4d 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -25,22 +25,22 @@ Proposed on 2026-09-28, for discussion. 1. **Release syncs** as each release candidate ships: #8336 for rc.13. 2. **Section E** in one pull request: small, verified gaps on the migration pages and the CLI reference, plus the D17 lines in prisma/orm's `docs/reference/error-reference.md` that the site's error reference is generated from. 3. **The restructure** (A1, A5, A3, A6, A8) as one piece of work, with C2 and C3 as two of its four doors. -4. **C18 and C7** as soon as the decisions below land, and C1's "not in Prisma ORM 8 yet" list as D4's decisions land. -5. **The remaining new pages**: C22, C9, C8, C6, C10 (with draft #8131), C19, C17, and C23 once it has an owner. +4. **C18 and C7**, now that both are decided; C1's "not in Prisma ORM 8 yet" list changes only when D4's APIs are built. +5. **The remaining new pages**: C22, C9, C8, C6, C10 (with draft #8131), C19, C17, and C23. 6. **ORM side**, in order of how badly each hurts a reader: D10, D9, D15, D13, D12, D7, D18, D11, D5's `public`-only inference, D17, the Node range. ## Decisions needed, and from whom The five migrations questions from the C21 handover were decided on 2026-09-22 and applied in #8307 and #8309; the one ORM change among them, `db migrate` advancing the `db` ref by default, is prisma/orm#30370 and still open. -| Item | Decision | Who | -|---|---|---| -| D4 | For each missing client API (atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path and containment filters, soft delete, validations, callbacks, read replicas, MongoDB referential actions): build it, or document the workaround and say it is not planned | Will | -| C7 | Whether RLS, expression indexes, and `@@control` are documented as supported or as preview | Will | -| C18 | The floors to publish: PostgreSQL (stated nowhere), Bun (the site says 1.1 in three guides), Deno (the site says 2.6), MongoDB (8.0, stated only on the MongoDB upgrade guide); and whether ES modules are a requirement, given `cli/orm-init.mdx` documents a working CommonJS setup | Will | -| C9 | Whether a Prisma ORM 8 page for deploying to Vercel is wanted | Will | -| C23 | Where the example repositories live and who keeps them current | Will | -| Node range | Why generated projects exclude Node.js 24.0 to 24.10 | create-prisma owner | +Decided by Will on 2026-09-28: + +- **C7:** row-level security, expression and partial indexes, and `@@control` are documented as supported, with a Limitations section naming the known gaps. +- **C18:** publish PostgreSQL 15, MongoDB 8.0, Node.js 22.18, TypeScript 5.9, Bun 1.3, and Deno 2.6 (experimental). The packages are ES modules only, and a CommonJS project works on the supported Node.js versions as `cli/orm-init.mdx` describes. Drop the "24.0 to 24.10 do not work" wording: 24.11 is where Node.js 24 became a long-term support release, not a known break. +- **C9:** write a Prisma ORM 8 guide for deploying to Vercel. Prisma wants to cooperate with Vercel. +- **C23:** example repositories live in `prisma/prisma-examples`, one folder per starting state, with their Prisma versions bumped as part of each release-candidate docs sync. Docs never link to `examples/` in prisma/orm: those exist for end-to-end tests, not for readers. + +No docs item waits on a decision now. The ORM-side suggestions in section D (which client APIs to build, which CI jobs to add) are for the ORM team to schedule and block no page. ## A. Restructure @@ -84,21 +84,21 @@ Grouped by where the page lives. Each says what the page is for, what it must co - **C1. Coming from Prisma 7.** The mapping table from `mental-model.md` in four sections: schema and types, CLI commands, client API, and "not in Prisma ORM 8 yet" with a status per item. The last section is the one readers ask for most and no page has: `skipDuplicates`, `increment`/`decrement`, `findUniqueOrThrow`, case-insensitive filters, `$transaction` arrays, model and payload types, `@updatedAt` (rejected; use `temporal.updatedAt()`), `cuid()` (rejected; use `cuid(2)`), JSON path filtering, soft delete, validations, callbacks, read replicas. Unblocks J3. Placement is A2; content of the "not yet" list depends on D4. Landed as #8245. - **C3. Adopt an existing database.** Split from the existing-project page so it has room: what `contract infer` produces (SQL-only; captures indexes, checks, RLS, 1:1 relations; emits Temporal-backed timestamp types that need the polyfill, D10), what `db sign` checks and what exit code 4 means, the `db` ref it now sets, the baseline the first `migration plan` writes, the second migration with `--advance-ref db`. Unblocks J2. D1 has landed, so the page can be short. Status on 2026-09-28: `add-to-existing-project/postgresql.mdx` now covers the Temporal types after inference, the `db` ref that `db sign` sets, and the automatic baseline; exit code 4 is on `cli/db-sign.mdx`. Left: the page of its own, what `contract infer` captures and that it is SQL-only, and the second migration applied with `db migrate --advance-ref db`. - **C4. Release status.** One short page: release candidate; GA window; Prisma ORM 7 gets bug fixes and security updates for 18 months from GA; `npx prisma` and `npm install prisma` resolve to Prisma ORM 8; to stay on 7, pin `prisma@7` and `@prisma/client@7`. Linked from the root page and every "Using Prisma 7?" note. Unblocks J4. GA is expected in October 2026 and Prisma ORM 7 is supported for 18 months from GA; D6 resolved; landed as #8245. -- **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. Status on 2026-09-28: `orm/release-status.mdx` states Node.js 22.18 (24.11 on the 24 line) and TypeScript 5.9; the other floors are scattered or missing, as the decision table says. +- **C18. Supported versions.** No page states the floors. Candidates: Node (see the decision above), Bun 1.2 (site says 1.1), Deno 2.0, PostgreSQL 15 (stated nowhere), MongoDB 8.0, TypeScript 5.9, `tsconfig` with `moduleResolution: "bundler"` and `strict: true`, ESM-only. The monorepo's `docs/Supported Versions.md` is the draft but is wrong about Node and documents a `--merge-tsconfig` flag that does not exist, so confirm each number. One page under getting started, linked from every quickstart. Status on 2026-09-28: `orm/release-status.mdx` states Node.js 22.18 (24.11 on the 24 line) and TypeScript 5.9; the other floors are scattered or missing, as the decision table says. Decided 2026-09-28: the floors in the decisions section. Sixteen guides that say "Node.js 24 or later" change to 22.18 with the page. - **C22. A database on your machine.** One page in the Getting Started > Prisma ORM subtree for the reader with no hosted database. Corrected 2026-09-28: `prisma dev` is not a standalone local Prisma Postgres; it runs a Prisma Composer app from a module entry file (`cli/dev.mdx`), and its local Prisma Postgres serves only that app. For a reader using Prisma ORM on its own, the options are `npx create-db` (hosted and temporary), the Composer local stack if the app is a Composer app, and a PostgreSQL you run yourself, with a Docker Compose file and the connection string for it. Ends with how to look at the rows: Studio against the local instance (check whether `prisma dev` serves Studio, and which command opens it in Prisma ORM 8), or a Postgres client such as pgAdmin. Linked from every quickstart at the point where `DATABASE_URL` first appears. Unblocks J11. Source: `local-development/postgres.mdx`, `composer/local-development.mdx`, the Docker deployment guide for the Compose file shape. Not started on 2026-09-28. -- **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. Not started on 2026-09-28; needs an owner (see the decision table). +- **C23. Example repositories.** One small runnable repository per starting state, each with a README that lists which files the reader writes, which files Prisma generates, and the command that produces each, and with comments in `db.ts`, `prisma.config.ts`, and the query file. Linked from the matching quickstart or starting-state page. Seed: `examples/prisma-8-demo` in the monorepo. Needs a home (a `prisma/examples`-style repository or a folder in `prisma/orm`) and an owner on the ORM side. Unblocks J12. Not started on 2026-09-28; needs an owner (see the decision table). Decided 2026-09-28: `prisma/prisma-examples`, one folder per starting state, versions bumped in each release-candidate docs sync. Never link `examples/` in prisma/orm. The three Prisma ORM 8 apps already in `prisma-examples/compute/` pin `@prisma/orm-postgres` 8.0.0-rc.8. - **C5. Editor setup.** Where the VS Code extension lives (open-vsx), that Prisma ORM 8 does not bundle a language server and uses the locally installed CLI, that `// use prisma-next` on line one is what the language server keys on, and `prisma contract format` as the fallback. Unblocks J7. Landed as #8278 (`orm/contract-authoring/editor-support.mdx`). ### Guides -- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. Status on 2026-09-28: no Prisma ORM 8 page covers deploying to Vercel (`guides/postgres/vercel.mdx` has two short notes), and no Prisma ORM 8 page shows closing the client on shutdown; six guides say to close it on shutdown without showing how. The Cloudflare Workers page is handled separately. +- **C9. Deploying Prisma ORM 8.** Partly overtaken by #8242, which added Prisma ORM 8 guides for Docker, Cloudflare Workers, Turborepo, pnpm workspaces, and Bun workspaces; re-scope against those pages before writing. What a deploy needs: `prisma contract emit` as a `prebuild` step, `db migrate` (or `db init`) from the pipeline before the app starts, `db.close()` on shutdown, and for edge runtimes the per-request facade `@prisma/orm-postgres/serverless` (`postgresServerless({ contractJson })` at module scope, `await using runtime = await db.connect({ url })` per request). Sections or pages for Docker, Vercel, Cloudflare Workers, monorepos. The monorepo's `docs/Serverless Deployment Guide.md` is the source for the Cloudflare path (Hyperdrive, `nodejs_compat`, migrations against the origin URL never through Hyperdrive, one runtime per `connect()`, the 128 MiB isolate limit) and carries a production caveat with no site presence: against real Hyperdrive the serverless facade's default cursor path hangs (SQLSTATE 58000, request killed at 30 s); the workaround is `cursor: { disabled: true }`. Source: `skills/prisma-8/references/build.md:421-435`, `packages/3-extensions/postgres/README.md:41-60`, `docs/Serverless Deployment Guide.md:97,274`. Status on 2026-09-28: no Prisma ORM 8 page covers deploying to Vercel (`guides/postgres/vercel.mdx` has two short notes), and no Prisma ORM 8 page shows closing the client on shutdown; six guides say to close it on shutdown without showing how. The Cloudflare Workers page is handled separately. Decided 2026-09-28: write the Vercel guide (contract emit in the build, `db migrate --to ` in CI rather than in the Vercel build, the connection string, one module-level client). - **C11. CI.** #8242 rewrote `guides/integrations/github-actions.mdx` for Prisma ORM 8; check it against this before writing. `prisma migration status --to --db "$URL" --json`, fail the job on any `diagnostics[]` entry (the process exits 0 on warnings, so exit codes alone miss `MIGRATION.DIVERGED` and friends), then `prisma db migrate --to --db "$URL"`. Source: `skills/prisma-8/references/migration-review.md:172-197`. D16 would make this one line. Landed as #8310 in a different shape: the job is `db migrate --to ` alone, with no `migration status` parse, because `db migrate` refuses a database whose marker is outside the history before it runs anything. - **C12. Switching from another ORM; team schema workflow.** #8242 rewrote the three `guides/switch-to-prisma-orm/*` and three `guides/database/*` pages for Prisma ORM 8; re-scope against them. The brownfield flow (`orm init`, `contract infer`, review, `contract emit`, `db sign`, `db verify`) and the team loop (`migration plan`, refs, `db update` for local iteration, `db verify`, `migration status` in CI). Reuses C3 and C11. Landed as #8310: `guides/database/schema-changes.mdx` says what `db verify` adds after `migration check`. - **C10. Supabase and row level security.** The Supabase extension is one table row on the site. What ships: `@@rls` on a model, the five `policy_*` block kinds with `target` / `roles` / `using` / `withCheck`, the cross-space foreign key `supabase:auth.AuthUser`, `supabase({ contractJson, url, jwksUrl | jwtSecret })`, `db.asUser(jwt)` / `db.asAnon()` / `db.asServiceRole()`, the session-pooler requirement, the one-time `GRANT` for `auth.*`, and the `SUPABASE.*` errors. Source: `packages/9-public/@prisma/orm-extension-supabase/`, `skills/prisma-8/references/supabase.md`. Status on 2026-09-28: a note in `orm/extensions/using-extensions.mdx` covers the pack, `supabase(...)`, the role helpers, and `SUPABASE.JWT_INVALID`; RLS blocks and `supabase:auth.AuthUser` are on `psl-syntax.mdx`. Left: the page itself (draft #8131 would add one), the session-pooler requirement, the one-time `GRANT` on `auth.*`, and the other `SUPABASE.*` errors. ### Reference completeness -- **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. Status on 2026-09-28: every construct is now in the reference (#8306: `psl-syntax.mdx`, `typescript-schema-builder.mdx`, `migration-api.mdx`). Left: one page for the reader who needs these together, and the supported-or-preview label. +- **C7. Advanced Postgres.** All of it ships and none of it is documented: RLS and policies in PSL and the TypeScript builder; expression and partial indexes (`@@index(expression:, where:, unique:, type:)`); `@@check`; `@noCheck`; `installExtension` / `createExtension` migration factories; `@@control` for how much of a table Prisma manages. Unblocks J8. Source: `skills/prisma-8/references/contract.md:101-108,265-367`, `packages/2-sql/2-authoring/contract-psl/README.md`. Waits on the product call about how to label these. Status on 2026-09-28: every construct is now in the reference (#8306: `psl-syntax.mdx`, `typescript-schema-builder.mdx`, `migration-api.mdx`). Left: one page for the reader who needs these together, and the supported-or-preview label. Decided 2026-09-28: documented as supported, with a Limitations section. Known gaps to list: the policy-before-DDL ordering fix ships after rc.12 (prisma/orm#30232); `contract infer` refuses policies that span several schemas; no `GRANT` authoring; `FORCE ROW LEVEL SECURITY` is not modelled; per-column sort order in `@@index` fails (prisma/orm#30270); indexes on single-table variants are dropped (prisma/orm#30445); an expression index adopted with `map:` reports drift against PostgreSQL's reprint; `@@control` on external tables with relations or enums is partial. - **C8. Money and Decimal.** Cents as integers (already there), `Numeric(p, s)` in type position, what `@default` accepts, `avgDecimal`, and that a decimal string avoids float loss while the declared scale still rounds. Answers an open Discord question. Status on 2026-09-28: the facts are spread over `orm/data-modeling/index.mdx`, `psl-syntax.mdx`, `sql-query-builder.mdx`, and `orm-client.mdx`. Left: the one page, and the point that a decimal string avoids float loss while the declared scale still rounds, which no page makes. - **C6. Types.** Model, result, where, and input types with the Prisma 7 names beside each. Written from `docs/reference/model-and-result-types.md` in prisma/orm (#30231 and #30236, shipped in rc.10). #8261 documents `Models`, `Scalars<>`, `Shape<>`, and `ResultType` as a section of `orm/reference/orm-client.mdx` and a row on Coming from Prisma 7; what is left is the page with the Prisma 7 name beside each type, and what `contract.d.ts` exports beyond them. #30158 (reusable where filter types) is in rc.9. Unblocks J9. Status on 2026-09-28: the section on `orm/reference/orm-client.mdx` and the row on Coming from Prisma 7 are all there is. Left: the page with the Prisma 7 name beside each type, and the where and input types, which no page shows. - **C13. Migration factory reference.** The site shows six factories; the `Migration` base class has about thirty (indexes, foreign keys, uniques, checks, column changes, native enums, `installExtension`, RLS and policies), plus free factories and the `node migration.ts --dry-run` / `--config` self-emit CLI. Source: `packages/3-targets/3-targets/postgres/src/core/migrations/postgres-migration.ts:159-506`. Shipped as #8306: `orm/reference/migration-api.mdx`. @@ -113,7 +113,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co ## E. Gaps found after the audit -Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28; none is fixed yet. Each is small and verified. Specified as one slice in `slices/01-migration-and-cli-gaps/spec.md`, which also removes a `./path` contract reference form that five CLI pages list and no command accepts. Grounding the slice found CLI defects in the same area (`./path` in the CLI's help text, `@contract` and `@db` refused or mishandled by `migration status`, `db migrate`, and `db update`, and `migration status` reporting `Up to date` right after `db update`), fixed in prisma/orm#30475. +Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28 (E12 was found on 2026-09-28 after the C23 decision); none is fixed yet. Each is small and verified. Specified as one slice in `slices/01-migration-and-cli-gaps/spec.md`, which also removes a `./path` contract reference form that five CLI pages list and no command accepts. Grounding the slice found CLI defects in the same area (`./path` in the CLI's help text, `@contract` and `@db` refused or mishandled by `migration status`, `db migrate`, and `db update`, and `migration status` reporting `Up to date` right after `db update`), fixed in prisma/orm#30475. - **E1. The migration graph drawing's column symbols.** `orm/migrations/the-migration-graph.mdx` defines `○` and `↑↓⟲` but not `│ │` and `│─╯`, and defers to `--legend`. - **E2. `^` on The migration graph.** Used twice with no explanation or link; it is explained on `rollbacks-and-recovery.mdx`, `cli/migration-plan.mdx`, and `cli/migration-ref.mdx`. @@ -126,6 +126,7 @@ Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28; none - **E9. `orm init` and `init` on the GitHub Actions guide.** The page uses both and never says that `init` installs the agent skills and does not set up the ORM; only `cli/init.mdx` says so. - **E10. One situation, two codes.** `MIGRATION.MARKER_NOT_IN_HISTORY` from `migration status` and `MIGRATION.MARKER_MISMATCH` from `db migrate` describe the same database; no page links them, and the two error reference entries give different fixes. - **E11. The error reference names the wrong source repository.** The header `apps/docs/scripts/generate-error-reference.mjs` writes into `orm/reference/error-reference.mdx` points at `prisma/prisma`; the repository is `prisma/orm`. +- **E12. Links to examples in prisma/orm.** Four pages send readers to `examples/` in prisma/orm, which exist for end-to-end tests: `orm/extensions/using-extensions.mdx` (the pgvector, PostGIS, ParadeDB, and Supabase demos), `orm/migrations/editing-a-migration.mdx` and `orm/reference/migration-api.mdx` (a `migration.ts` in the retail-store example), and `orm/migrations/the-migration-graph.mdx` (the "Try it on real fixtures" section). Remove each link; where the page needs the code, show it on the page. ## D. Change the ORM and its tooling @@ -145,9 +146,11 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. Still open on 2026-09-28: `contract infer` still maps `timestamptz` to the Temporal-backed `Timestamptz` (the map moved to `psl-build/postgres-type-map.ts:32-33`), the Prisma 7 route in `orm init` maps `DateTime` to the Temporal-backed `Timestamp(3)`, and `orm init` neither installs nor imports `temporal-polyfill`. prisma/orm#30301 and #30308 (infer `timestamptz` as `TimestamptzString`) are open. - **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. Partly fixed by 2026-09-28: `contract infer` writes native types in type position (`VarChar(32)`, `Numeric(10, 2)`), never `@db.*`, and a hand-written `@db.*` gets an error naming the replacement; `Decimal` defaults keep their digits (prisma/orm#30350, rc.12); `dbgenerated` became sql tagged literals (#30380). Still open: `contract infer` reads only the `public` schema. For Prisma 7 projects the route changed: since prisma/orm#30291 (rc.12) `orm init` reads `schema.prisma` through `prisma7Schema(...)`, which accepts `@db.*` and `@@schema`, instead of inferring from the database. Not verified end to end against a real Prisma 7 database. +- **D19. Test and declare the published floors.** Suggested by the C18 decision: a Node.js 22 job and a Bun job in ORM CI, a test for a CommonJS consumer, `engines` on the published `@prisma/orm-*` packages (none declares one), and `docs/Supported Versions.md` brought in line (it says Node.js 24, Bun 1.2, Deno 2.0, and CommonJS unsupported). + ### Product decisions -- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. Status on 2026-09-28: insert-and-skip-conflicts landed as `createAll(rows, { onConflict: 'skip', conflictOn? })` and `createAndCount` (prisma/orm#30365, rc.12); the field filters have `.ilike(pattern)` and, since rc.12, full-text search operations. Still absent on SQL: atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path or containment filters, soft delete, validations, lifecycle callbacks, read replicas. MongoDB has `inc` and `mul`; MongoDB referential actions are still unsupported, and the Prisma 6 schema reader now rejects `onDelete` and `onUpdate` explicitly (prisma/orm#30405). +- **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. Status on 2026-09-28: insert-and-skip-conflicts landed as `createAll(rows, { onConflict: 'skip', conflictOn? })` and `createAndCount` (prisma/orm#30365, rc.12); the field filters have `.ilike(pattern)` and, since rc.12, full-text search operations. Still absent on SQL: atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path or containment filters, soft delete, validations, lifecycle callbacks, read replicas. MongoDB has `inc` and `mul`; MongoDB referential actions are still unsupported, and the Prisma 6 schema reader now rejects `onDelete` and `onUpdate` explicitly (prisma/orm#30405). Suggested on 2026-09-28, for the ORM team to schedule: build atomic increment and decrement and a collection-level `firstOrThrow` before GA; JSON path and containment filters and list filters after GA; document case-insensitive matching with `.ilike` and its escaping, and nested writes through `db.transaction`; soft delete, validations, callbacks, and read replicas are not planned (Prisma ORM 7 had none built in); MongoDB referential actions not for GA, with `docs/reference/mongodb-user-promise.md` corrected. - **D6. The npm `latest` tag.** `prisma@latest` is the Prisma ORM 8 CLI (8.0.0-rc.15 on 2026-09-21) while `@prisma/client@latest` is 7.10.0, so a Prisma 7 project's routine `npx prisma` picks up the 8 CLI against a 7 client. Move the release candidate to `next` until GA, or state the policy on C4. Resolved: the tag stays; #8194 pins the Prisma ORM 6 pages to 6.19.3 and the Prisma ORM 7 CLI commands to `prisma@prev`. ### create-prisma diff --git a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md index 631e50413b9..77275215dda 100644 --- a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md +++ b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/spec.md @@ -4,7 +4,7 @@ _(Parent project: the Prisma ORM 8 docs audit, `docs/orm-docs-audit/` on branch ## At a glance -One prisma/web pull request that fixes eleven small, verified gaps on the Prisma ORM 8 migration pages and CLI reference pages. Each gap is a place where a reader meets a symbol, token, term, or hash the page never explains, or a command the page tells them to run without showing it. The same pull request corrects the contract reference forms listed on five CLI pages: they advertise a `./path` form that no command accepts, and two of them omit `^` where it works. Every fact below was checked on 2026-09-28 by running `prisma@8.0.0-rc.17` with `@prisma/orm-postgres@8.0.0-rc.12` against PostgreSQL 15. +One prisma/web pull request that fixes twelve small, verified gaps on the Prisma ORM 8 migration pages and CLI reference pages. Each gap is a place where a reader meets a symbol, token, term, or hash the page never explains, or a command the page tells them to run without showing it. The same pull request corrects the contract reference forms listed on five CLI pages: they advertise a `./path` form that no command accepts, and two of them omit `^` where it works. Every fact below was checked on 2026-09-28 by running `prisma@8.0.0-rc.17` with `@prisma/orm-postgres@8.0.0-rc.12` against PostgreSQL 15. ## Terms used in this spec @@ -115,6 +115,16 @@ The repository `prisma/prisma` was renamed `prisma/orm`; the old name works only - `apps/docs/scripts/generate-error-reference.mjs`: the `orm` target's `sourceRepo` is `"prisma/prisma"`. Change it to `"prisma/orm"`, together with the comment at the top of the file and the intro sentence that names the repository. - `.github/workflows/sync-error-reference-docs.yml` and `.github/workflows/error-reference-check.yml`: change `repository: prisma/prisma` to `repository: prisma/orm`, and `prisma/prisma` to `prisma/orm` in step names and comments. Keep `path: prisma-src`, so the scripts' `--source` paths do not change. Then regenerate `orm/reference/error-reference.mdx` with the script, the way `.github/workflows/sync-error-reference-docs.yml` runs it, and confirm the only change to that page is the repository name. The `cli` target (`prisma/prisma-cli`) is correct; leave it. +### E12. Remove links to examples in prisma/orm + +`examples/` in prisma/orm exists for end-to-end tests, not for readers. Docs never link to it. + +- `orm/extensions/using-extensions.mdx`: delete the "runnable example" link in the Supabase paragraph and the sentence that links a runnable example for pgvector, PostGIS, ParadeDB, and Supabase. +- `orm/migrations/editing-a-migration.mdx` and `orm/reference/migration-api.mdx`: delete the link to the retail-store `migration.ts`. If the surrounding text depends on seeing that file, show the relevant lines on the page instead, taken from the file at prisma/orm `main` and checked against the published `@prisma/orm-mongo`. +- `orm/migrations/the-migration-graph.mdx`: delete the section "Try it on real fixtures". + +After the change, `git grep -nE "github.com/prisma/(orm|prisma)/(tree|blob)/[^ )]*examples" -- apps/docs/content/docs` returns nothing outside `v6/` and `v7/`. + ### Contract reference forms on the CLI pages Match each option row to the E3 table: @@ -131,7 +141,7 @@ Every change is a sentence, a table, or a table row on the migration pages and t ## Scope -**In:** the eleven gaps above and the contract reference rows on five CLI pages; the generator script and the two error reference workflows for E11, and regenerating `orm/reference/error-reference.mdx`. +**In:** the twelve gaps above and the contract reference rows on five CLI pages; the generator script and the two error reference workflows for E11, and regenerating `orm/reference/error-reference.mdx`. **Out:** anything under `v6/` or `v7/`; the text of individual error entries on `orm/reference/error-reference.mdx`, which is generated from `docs/reference/error-reference.md` in prisma/orm and is fixed there (item D17 in `changes.md`); the CLI's help text and its handling of `@contract`, `@db`, and `@empty`, which prisma/orm#30475 fixes; the restructure (section A); new pages (section C); cross-linking the two error reference pages (item A8). From 543702474d7df671f10c41cb7ac460d04114cde7 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 28 Sep 2026 17:02:35 +0200 Subject: [PATCH 44/68] docs(audit): drop release syncs from the order; they already happen Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 01c52318d4d..971f9f93bbc 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -22,12 +22,11 @@ Status as of 2026-09-28. Proposed on 2026-09-28, for discussion. -1. **Release syncs** as each release candidate ships: #8336 for rc.13. -2. **Section E** in one pull request: small, verified gaps on the migration pages and the CLI reference, plus the D17 lines in prisma/orm's `docs/reference/error-reference.md` that the site's error reference is generated from. -3. **The restructure** (A1, A5, A3, A6, A8) as one piece of work, with C2 and C3 as two of its four doors. -4. **C18 and C7**, now that both are decided; C1's "not in Prisma ORM 8 yet" list changes only when D4's APIs are built. -5. **The remaining new pages**: C22, C9, C8, C6, C10 (with draft #8131), C19, C17, and C23. -6. **ORM side**, in order of how badly each hurts a reader: D10, D9, D15, D13, D12, D7, D18, D11, D5's `public`-only inference, D17, the Node range. +1. **Section E** in one pull request: small, verified gaps on the migration pages and the CLI reference, plus the D17 lines in prisma/orm's `docs/reference/error-reference.md` that the site's error reference is generated from. +2. **The restructure** (A1, A5, A3, A6, A8) as one piece of work, with C2 and C3 as two of its four doors. +3. **C18 and C7**, now that both are decided; C1's "not in Prisma ORM 8 yet" list changes only when D4's APIs are built. +4. **The remaining new pages**: C22, C9, C8, C6, C10 (with draft #8131), C19, C17, and C23. +5. **ORM side**, in order of how badly each hurts a reader: D10, D9, D15, D13, D12, D7, D18, D11, D5's `public`-only inference, D17, the Node range. ## Decisions needed, and from whom From c61a0cabe03cef6034824f5e60a7b93e3cc5244e Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 29 Sep 2026 23:03:52 +0200 Subject: [PATCH 45/68] docs(audit): restructure plan with the decided Quickstart labels, and the slice 02 spec Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/ia.md | 2 + docs/orm-docs-audit/restructure-plan.md | 38 ++++++ .../02-quickstart-by-starting-point/spec.md | 113 ++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 docs/orm-docs-audit/restructure-plan.md create mode 100644 docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md diff --git a/docs/orm-docs-audit/ia.md b/docs/orm-docs-audit/ia.md index 0637510798e..771e4a5b0dc 100644 --- a/docs/orm-docs-audit/ia.md +++ b/docs/orm-docs-audit/ia.md @@ -8,6 +8,8 @@ Scope: the Getting Started > Prisma ORM subtree, the ORM > Introduction group, a ### Getting Started > Prisma ORM +_The labels in this tree were replaced on 2026-09-29 by statements the reader makes about their starting point; `restructure-plan.md` has the decided tree._ + ``` Prisma ORM Introduction to Prisma ORM human content first, agent prompt last diff --git a/docs/orm-docs-audit/restructure-plan.md b/docs/orm-docs-audit/restructure-plan.md new file mode 100644 index 00000000000..6769ce4656f --- /dev/null +++ b/docs/orm-docs-audit/restructure-plan.md @@ -0,0 +1,38 @@ +# Restructure of the Prisma ORM entry pages: plan + +Design approved by Will on 2026-09-29. The design is `ia.md`, with the sidebar labels below replacing the ones in its first tree. Items A1, A3, A5, A6, A8, C2, and C3 of `changes.md`. + +## Sidebar labels (decided) + +The Getting Started > Prisma ORM group names each starting point as a statement the reader makes about themselves, under one "Quickstart" group: + +``` +Prisma ORM + Introduction to Prisma ORM + Release status + Quickstart + I'm creating a new app + I have an app, but no database yet + I have a database already + I have a Prisma 7 app + Editor setup + create-prisma +``` + +PostgreSQL and MongoDB are a choice at the top of each page, not extra sidebar levels. "I have a Prisma 7 app" opens the upgrade guide, which links Coming from Prisma ORM 7 as the reference for what changed. + +## Slices, in order + +| Slice | Covers | Spec | +| --- | --- | --- | +| 02 | The Quickstart group, the new no-database pages, the extended existing-database pages, and the four starting points on `/prisma-orm` (A1, C2, C3) | `slices/02-quickstart-by-starting-point/spec.md` | +| 03 | `/orm` rebuilt; the docs root page gets a row of the four starting points; "What changed for developers" and the blog list leave `/orm` (A1, A5) | written when 02 merges | +| 04 | "Use with your agent" moves below the human steps on the entry pages and the twelve framework and runtime guides (A3) | written when 03 merges | +| 05 | `orm/core-concepts.mdx` rewritten from `mental-model.md` (A6) | written when 04 merges | +| 06 | The two error references name each other and say which codes live where, in the generator (A8) | written when 05 merges | + +Slice 01 is the migration and CLI gaps, delegated separately. + +## Done when + +Every slice is merged, each passed `/drive-code-review` and the docs reader review, and the four starting points are reachable from the docs root page, `/prisma-orm`, and `/orm`. diff --git a/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md b/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md new file mode 100644 index 00000000000..8cc4a7491b3 --- /dev/null +++ b/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md @@ -0,0 +1,113 @@ +# Slice: the Quickstart group, by the reader's starting point + +_(Parent project: the Prisma ORM 8 docs audit, `docs/orm-docs-audit/`; plan in `restructure-plan.md`. Items A1, C2, and C3 of `changes.md`.)_ + +## At a glance + +The Getting Started > Prisma ORM sidebar in prisma/web is grouped by the tool that runs (`create-prisma`, `orm init`). After this slice it is grouped by where the reader starts, in the reader's own words: + +``` +Quickstart + I'm creating a new app + I have an app, but no database yet + I have a database already + I have a Prisma 7 app +``` + +One page pair is new (an app with no database yet), one is extended (a database that already has tables), and no existing URL changes. + +## Chosen design + +All paths are under `apps/docs/content/docs/`. Do not touch `v6/` or `v7/` folders. + +### Sidebar + +`(index)/prisma-orm/meta.json` `pages` becomes, in order: `index`, the Release status link, the Supported databases link, `quickstart`, `[Editor setup](/orm/contract-authoring/editor-support)`, `create-prisma`. + +`(index)/prisma-orm/quickstart/meta.json` keeps the title "Quickstart" and lists four link entries, so the PostgreSQL and MongoDB pages do not appear as sidebar levels: + +| Label | Opens | +| --- | --- | +| I'm creating a new app | `/prisma-orm/quickstart/postgresql` | +| I have an app, but no database yet | `/prisma-orm/quickstart/existing-app/postgresql` | +| I have a database already | `/prisma-orm/add-to-existing-project/postgresql` | +| I have a Prisma 7 app | `/guides/upgrade-prisma-orm/postgresql` | + +`from-scratch` and `add-to-existing-project` leave the `prisma-orm` sidebar list; their pages and URLs stay. Confirm in the running docs app that unlisted pages still render at their URLs, that the four entries show in this order, and that the entry for the current page is highlighted on the PostgreSQL page of each pair. If fumadocs cannot express this with link entries, stop and report what it can express. + +### Database choice at the top of each page + +Each page in a pair starts, directly under the frontmatter, with one line that names the database it covers and links its twin, for example "This page uses PostgreSQL. [Use MongoDB instead](/prisma-orm/quickstart/mongodb)." The Prisma 7 upgrade guide gets no such line: Prisma ORM 7 did not support MongoDB. + +### I'm creating a new app + +Pages: `(index)/prisma-orm/quickstart/postgresql.mdx` and `mongodb.mdx`, unchanged in content except the database line, a frontmatter `title` that says what the page does ("Create a new app with PostgreSQL", "Create a new app with MongoDB"), and one sentence linking `/prisma-orm/from-scratch` for readers who want no scaffold. `from-scratch.mdx` links back. + +### I have an app, but no database yet (new) + +New pages `(index)/prisma-orm/quickstart/existing-app/postgresql.mdx` and `mongodb.mdx`. The reader has a project directory with a `package.json` and an empty database, or a connection string for one. Steps, each with the command and the output you capture yourself: + +1. `npx prisma@latest orm init` with the flags for the target, and what it writes, including `src/prisma/db.ts`, shown in full. +2. Set the connection string. Link `npx create-db@latest` for a reader with no database at all. +3. Edit the starter contract: one model. +4. `npx prisma contract emit`. +5. `npx prisma db init`, and what the marker and the `db` ref in its output are, each in one sentence. +6. One write and one read through `db.orm`, in a script that ends with `await db.close()`. +7. Change the contract and apply it: `contract emit`, `migration plan --name `, `db migrate --advance-ref db`. +8. Next steps. + +Commands are for Node.js with npm. One note says what differs on Bun. The MongoDB page follows the same steps with the MongoDB commands and leaves out anything PostgreSQL-only. + +### I have a database already (extended) + +Pages: `(index)/prisma-orm/add-to-existing-project/postgresql.mdx` and `mongodb.mdx`. Titles become "Add Prisma ORM to an existing PostgreSQL database" and the MongoDB equivalent. The PostgreSQL page gains: + +- What `contract infer` reads from the database and what it does not: check what it captures (indexes, checks, row-level security, relations, defaults) by running it against a database that has each, and state that it reads only the `public` schema. +- What `db sign` checks before it writes the marker, and that exit code 4 means the tables do not match the contract. +- The second migration: after `migration plan`, apply with `npx prisma db migrate --advance-ref db`, with output. +- A link to the no-database page for a reader whose database is empty. + +The MongoDB page gains the link and the second migration. + +### The four starting points on `/prisma-orm` + +`(index)/prisma-orm/index.mdx`: directly after the opening paragraph, add the four starting points as cards with the sidebar labels and the same targets, replacing the two links to create-prisma and from-scratch. Leave "Use with your agent" where it is; slice 04 moves it. + +### Links + +Every page that links `/prisma-orm/from-scratch`, `/prisma-orm/quickstart/*`, or `/prisma-orm/add-to-existing-project/*` with link text naming the old sidebar labels ("Quickstart", "Add to Existing Project") gets link text that matches the new titles. + +## Coherence rationale + +The sidebar change, the page it needs that does not exist, and the page it renames are one reviewable unit: merging the sidebar without the no-database page would leave an entry with nothing behind it. + +## Scope + +**In:** the two `meta.json` files, the six entry pages, the two new pages, `/prisma-orm`, and link text elsewhere. + +**Out:** `/orm` and the docs root page (slice 03); moving agent prompts (slice 04); core concepts (slice 05); any URL change or redirect; the Prisma 7 upgrade guide's content; links to `examples/` in prisma/orm, which docs never use; the gaps in `slices/01-migration-and-cli-gaps/spec.md`, which another agent is changing on some of the same pages, so rebase before opening the pull request. + +## Pre-investigated edge cases + +| Edge case | Disposition | Notes | +| --- | --- | --- | +| No Docker on the operator's machine | Use the Homebrew PostgreSQL 15 at `/opt/homebrew/opt/postgresql@15/bin` | `LANG=C LC_ALL=C initdb --locale=C -E UTF8`, start with `-c unix_socket_directories=''` on a spare port | +| MongoDB for verification | Use `mongodb-memory-server` or a local `mongod` if installed; if neither can run, stop and report | Do not publish MongoDB output you did not capture | +| `orm init` in a CommonJS project | Link `cli/orm-init.mdx#in-a-commonjs-project`; do not restate it | #8329 | +| CLI prints JSON when not on a terminal | Pass `--format human` when capturing output | The published pages show human output | + +## Slice-specific done conditions + +- [ ] Every command on the new and extended pages was run by the implementer on the published `prisma` and `@prisma/orm-*` `latest`, and the output on the page is the captured output. +- [ ] The sidebar shows the four entries in order in the running docs app, checked at desktop and mobile widths. +- [ ] The changed pages pass `.claude/skills/docs-reader-review` with at least two cold reader rounds, `lint:links`, and `lint:versions`. + +## Open questions + +None. + +## References + +- Design: [`../../ia.md`](../../ia.md), labels in [`../../restructure-plan.md`](../../restructure-plan.md) +- Reader jobs J1 and J2: [`../../journeys.md`](../../journeys.md) +- Mental model: [`../../mental-model.md`](../../mental-model.md) From 473b1c6235dec209f03ea18271ad928c8e50b99a Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 29 Sep 2026 23:48:28 +0200 Subject: [PATCH 46/68] docs(audit): slice 02 spec follows what runs today; record D20, D21, D22 Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 4 ++++ .../slices/02-quickstart-by-starting-point/spec.md | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 971f9f93bbc..a2135c6fa64 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -147,6 +147,10 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D19. Test and declare the published floors.** Suggested by the C18 decision: a Node.js 22 job and a Bun job in ORM CI, a test for a CommonJS consumer, `engines` on the published `@prisma/orm-*` packages (none declares one), and `docs/Supported Versions.md` brought in line (it says Node.js 24, Bun 1.2, Deno 2.0, and CommonJS unsupported). +- **D20. An existing MongoDB collection cannot be adopted.** Found 2026-09-29 on `prisma` 8.0.0-rc.19 and `@prisma/orm-mongo` 8.0.0-rc.13, against a collection with data and a unique index: `db sign` exits 4 (`missing: users/validator`) and suggests `db update`; `db update` exits 2 with `CLI.CONSENT_TOKEN_UNRESOLVED` ("has no name to confirm") although the URL names the database, with or without `--confirm`, `--db`, or `--yes`; `db init` fails with `MIGRATION.PLANNING_FAILED` ("destructive operation disallowed: Add validator on users"); `migration plan` then `db migrate` fails on `collection.users.create`. The path that should work adds a strict validator (`additionalProperties: false`) to a collection that holds data. Until fixed, the MongoDB existing-database page shows queries only. +- **D21. `orm init` fails in a project installed with Bun.** Found 2026-09-29: `bunx prisma@latest orm init` exits 5 with `CLI.INIT_EMIT_FAILED` ("A Scope already named Array already exists"), because `prisma@8.0.0-rc.19` depends on `@prisma/cli-engine@0.6.2` while `@prisma/orm-toolchain@8.0.0-rc.13` declares a peer on `0.6.1`, and Bun installs both. npm works. Running a script with `bun script.ts` in an npm-installed project works. Affects the Bun floor decided for C18. +- **D22. `contract infer` skips other schemas silently.** Found 2026-09-29: a table in a second schema is not read and no message says so. Part of D5's `public`-only item. + ### Product decisions - **D4. Missing client API.** Verified absent: `firstOrThrow` on the collection (it exists on the result, so `.all().firstOrThrow()` works), atomic `increment`/`decrement`, case-insensitive string filters, insert with on-conflict-do-nothing (`skipDuplicates`), JSON path or containment filters (the `jsonb` codec has only the `equality` trait). Also not supported: soft delete, validations, lifecycle callbacks, custom `Collection` subclasses, read replicas, MongoDB referential actions. Each needs a decision: build it, or document the workaround and say it is not planned. The types work has shipped: the where filter types (#30158) in rc.9; `Models`, `Scalars<>`, and `Shape<>` (#30231, #30236) in rc.10. Status on 2026-09-28: insert-and-skip-conflicts landed as `createAll(rows, { onConflict: 'skip', conflictOn? })` and `createAndCount` (prisma/orm#30365, rc.12); the field filters have `.ilike(pattern)` and, since rc.12, full-text search operations. Still absent on SQL: atomic increment and decrement, `firstOrThrow` on a collection, case-insensitive equality, JSON path or containment filters, soft delete, validations, lifecycle callbacks, read replicas. MongoDB has `inc` and `mul`; MongoDB referential actions are still unsupported, and the Prisma 6 schema reader now rejects `onDelete` and `onUpdate` explicitly (prisma/orm#30405). Suggested on 2026-09-28, for the ORM team to schedule: build atomic increment and decrement and a collection-level `firstOrThrow` before GA; JSON path and containment filters and list filters after GA; document case-insensitive matching with `.ilike` and its escaping, and nested writes through `db.transaction`; soft delete, validations, callbacks, and read replicas are not planned (Prisma ORM 7 had none built in); MongoDB referential actions not for GA, with `docs/reference/mongodb-user-promise.md` corrected. diff --git a/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md b/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md index 8cc4a7491b3..cb3556ef33d 100644 --- a/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md +++ b/docs/orm-docs-audit/slices/02-quickstart-by-starting-point/spec.md @@ -47,7 +47,7 @@ Pages: `(index)/prisma-orm/quickstart/postgresql.mdx` and `mongodb.mdx`, unchang New pages `(index)/prisma-orm/quickstart/existing-app/postgresql.mdx` and `mongodb.mdx`. The reader has a project directory with a `package.json` and an empty database, or a connection string for one. Steps, each with the command and the output you capture yourself: -1. `npx prisma@latest orm init` with the flags for the target, and what it writes, including `src/prisma/db.ts`, shown in full. +1. `npx prisma@latest orm init --yes --target --authoring psl --write-env` (without `--yes` it still prompts), and what it writes, including `src/prisma/db.ts`, shown in full. 2. Set the connection string. Link `npx create-db@latest` for a reader with no database at all. 3. Edit the starter contract: one model. 4. `npx prisma contract emit`. @@ -56,7 +56,7 @@ New pages `(index)/prisma-orm/quickstart/existing-app/postgresql.mdx` and `mongo 7. Change the contract and apply it: `contract emit`, `migration plan --name `, `db migrate --advance-ref db`. 8. Next steps. -Commands are for Node.js with npm. One note says what differs on Bun. The MongoDB page follows the same steps with the MongoDB commands and leaves out anything PostgreSQL-only. +Commands are for Node.js with npm. The pages say nothing about Bun: installing with Bun fails on the current release (D21 in `changes.md`). The first time a command prints the "Prisma agent skills are out of date" notice, one sentence says what it is and that `npx prisma@latest init` installs the skills; output blocks leave the notice out. The MongoDB page follows the same steps with the MongoDB commands and leaves out anything PostgreSQL-only. ### I have a database already (extended) @@ -67,7 +67,9 @@ Pages: `(index)/prisma-orm/add-to-existing-project/postgresql.mdx` and `mongodb. - The second migration: after `migration plan`, apply with `npx prisma db migrate --advance-ref db`, with output. - A link to the no-database page for a reader whose database is empty. -The MongoDB page gains the link and the second migration. +The MongoDB page gains the link only. Adopting an existing MongoDB collection cannot reach a signed database on the current release (D20 in `changes.md`), so the page shows no signing and no second migration. + +The PostgreSQL page also says that `contract emit` on an inferred contract prints `PN_EXACT_NAME_BODY_COMPARISON` warnings for policies, checks, and indexes with SQL bodies, and that they are expected. ### The four starting points on `/prisma-orm` From 9586aa3ad622743c7eedc5c386f12a6deb94efe1 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 07:28:50 +0200 Subject: [PATCH 47/68] docs(audit): docs slices are validated by reader review Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/restructure-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/restructure-plan.md b/docs/orm-docs-audit/restructure-plan.md index 6769ce4656f..f95eb9b74df 100644 --- a/docs/orm-docs-audit/restructure-plan.md +++ b/docs/orm-docs-audit/restructure-plan.md @@ -35,4 +35,4 @@ Slice 01 is the migration and CLI gaps, delegated separately. ## Done when -Every slice is merged, each passed `/drive-code-review` and the docs reader review, and the four starting points are reachable from the docs root page, `/prisma-orm`, and `/orm`. +Every slice is merged, each passed the docs reader review (`.claude/skills/docs-reader-review`), and the four starting points are reachable from the docs root page, `/prisma-orm`, and `/orm`. From db3add6c8fe23c9f6bb32daf98e3d524052529e2 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 07:34:25 +0200 Subject: [PATCH 48/68] docs(audit): D10 notes prisma/orm#30520 fixes the CLI half of the Temporal failure Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index a2135c6fa64..571a94e8fab 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -142,7 +142,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D8. Streaming does not stream on `postgres()`.** The facade creates its driver with `cursor: { disabled: true }`, so `for await` iterates an already-fetched result; only the serverless facade exposes cursor batches. Measured: breaking after the first row of a 400,000-row table still grew the heap by 64 MB. Expose `cursor` on `postgres()` or keep the docs' new wording. Source: `packages/3-extensions/postgres/src/runtime/postgres.ts:245-247`. - **D12. Permissive mode is unreachable on Postgres.** `postgres()` never forwards `mode`, so every "warn in permissive mode" branch in lints and budgets is dead on Postgres; only `mongo()` accepts it. Expose it or remove the branches. Source: `postgres.ts:86-94,276-282`, `sql-runtime.ts:187`. Still open on 2026-09-28: `postgres()` takes no `mode`, so the runtime is always strict; at `main` only budgets read `ctx.mode`, not lints. - **D7. `db.connect()` vs `db.runtime()`, `db.close()` vs `db.runtime().close()`.** Two names for adjacent things, a Mongo-only `await`, and `db.prepare` then `db.connect()` throwing `DRIVER.ALREADY_CONNECTED`. One call on both targets would simplify every page that shows a script. Still open on 2026-09-28: on PostgreSQL `runtime()` returns a `Runtime` and `prepare` exists; on MongoDB `runtime()` returns a promise and there is no `prepare`; `prepare` followed by `connect()` still throws `DRIVER.ALREADY_CONNECTED`. -- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. Still open on 2026-09-28: `contract infer` still maps `timestamptz` to the Temporal-backed `Timestamptz` (the map moved to `psl-build/postgres-type-map.ts:32-33`), the Prisma 7 route in `orm init` maps `DateTime` to the Temporal-backed `Timestamp(3)`, and `orm init` neither installs nor imports `temporal-polyfill`. prisma/orm#30301 and #30308 (infer `timestamptz` as `TimestamptzString`) are open. +- **D10. Inferred contracts fail at read time without the Temporal polyfill.** `contract infer` maps timestamp columns to Temporal-backed types; on Node.js 25 and earlier every read throws (official Node.js 26 ships `globalThis.Temporal`; Homebrew's Node.js 26 build omits it) `RUNTIME.TEMPORAL_UNAVAILABLE` unless `temporal-polyfill/full/global` is imported. `create-prisma` installs the polyfill; `orm init` does not. Options: infer to `TimestamptzString` by default, have `orm init` install and import the polyfill, or fail at emit with a clear message. Source: `packages/3-targets/3-targets/postgres/src/core/psl-infer/postgres-type-map.ts:30-33`. Still open on 2026-09-28: `contract infer` still maps `timestamptz` to the Temporal-backed `Timestamptz` (the map moved to `psl-build/postgres-type-map.ts:32-33`), the Prisma 7 route in `orm init` maps `DateTime` to the Temporal-backed `Timestamp(3)`, and `orm init` neither installs nor imports `temporal-polyfill`. prisma/orm#30301 and #30308 (infer `timestamptz` as `TimestamptzString`) are open. Update 2026-09-30: prisma/orm#30520 (open) fixes the control-plane half: `contract emit`, `db init`, `db update`, `contract infer`, and `node migration.ts` stop needing a global `Temporal` for date and time defaults. The application runtime is deliberately unchanged, so an app on Node.js 24 still needs `temporal-polyfill` for its first date read, and the docs keep telling readers to import it in `db.ts`. - **D5. `contract infer` on Prisma 7 databases.** Users report inferred contracts that fail to emit: `@db.*` attributes, `Decimal` defaults, non-`public` schemas. Check whether rc.9 still emits removed syntax and whether `Decimal @default(0.00)` is a bug. See D10. Partly fixed by 2026-09-28: `contract infer` writes native types in type position (`VarChar(32)`, `Numeric(10, 2)`), never `@db.*`, and a hand-written `@db.*` gets an error naming the replacement; `Decimal` defaults keep their digits (prisma/orm#30350, rc.12); `dbgenerated` became sql tagged literals (#30380). Still open: `contract infer` reads only the `public` schema. For Prisma 7 projects the route changed: since prisma/orm#30291 (rc.12) `orm init` reads `schema.prisma` through `prisma7Schema(...)`, which accepts `@db.*` and `@@schema`, instead of inferring from the database. Not verified end to end against a real Prisma 7 database. - **D19. Test and declare the published floors.** Suggested by the C18 decision: a Node.js 22 job and a Bun job in ORM CI, a test for a CommonJS consumer, `engines` on the published `@prisma/orm-*` packages (none declares one), and `docs/Supported Versions.md` brought in line (it says Node.js 24, Bun 1.2, Deno 2.0, and CommonJS unsupported). From c1533ed544f8227e52fd2732f482e64af7826b02 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 07:54:53 +0200 Subject: [PATCH 49/68] docs(audit): section E in review; record E13 to E20 and D23 to D29 Section E is in review as prisma/web#8348, the error reference command names as prisma/orm#30527, and the docs change prisma/orm#30475 needs as draft prisma/web#8349. The slice's plan, the facts run on rc.19, and the four reviews are kept beside its spec. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/orm-docs-audit/changes.md | 28 +- .../01-migration-and-cli-gaps/facts-rc19.md | 1316 +++++++++++++++++ .../slices/01-migration-and-cli-gaps/plan.md | 56 + .../reviews/code-review.md | 106 ++ .../reviews/reader-round1-cli.md | 101 ++ .../reviews/reader-round1-migrations.md | 53 + .../reviews/reader-round1-other.md | 110 ++ .../reviews/reader-round2-cli.md | 72 + .../reviews/reader-round2-orm.md | 79 + .../reviews/system-design-review.md | 89 ++ 10 files changed, 2006 insertions(+), 4 deletions(-) create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/facts-rc19.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/plan.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/code-review.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/reader-round1-cli.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/reader-round1-migrations.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/reader-round1-other.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/reader-round2-cli.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/reader-round2-orm.md create mode 100644 docs/orm-docs-audit/slices/01-migration-and-cli-gaps/reviews/system-design-review.md diff --git a/docs/orm-docs-audit/changes.md b/docs/orm-docs-audit/changes.md index 571a94e8fab..a85ea0701d8 100644 --- a/docs/orm-docs-audit/changes.md +++ b/docs/orm-docs-audit/changes.md @@ -4,7 +4,7 @@ This is the working list of changes to the Prisma ORM 8 documentation, built fro Item numbers (A1, B11, C9, D4) are stable identifiers used in the audit files and the PRs; some are out of sequence because items were added as they were found. "J1" to "J12" are the reader jobs defined in `journeys.md`. Source paths are in `prisma/orm` at rc.9 unless they start with `create-prisma`. -Status as of 2026-09-28. +Status as of 2026-09-30. ## Where things stand @@ -12,11 +12,13 @@ Status as of 2026-09-28. **Kept current with releases.** rc.10 (#8261, #8262), rc.11 (#8277), and rc.12 (#8317), with rc.12's follow-ups: the `module` settings the upgrade guide recommends (#8319), what a CommonJS project changes after `orm init` (#8329), the default table name change and every page re-run against the release (#8326), and a third reader round (#8328). Scaffold commands pass `--no-deploy` so `npm create prisma` does not deploy before the page says to (#8331). The error reference sync, broken from 2026-09-18 by codes without a dot, works again (#8327). The rc.13 sync is open as #8336 and merges when rc.13 is published. +**In review.** Section E as prisma/web#8348 (2026-09-29). The command names in prisma/orm's `error-reference.md` (part of D17) as prisma/orm#30527. The docs change that prisma/orm#30475 needs, as draft prisma/web#8349: it merges after a published release contains #30475 and its re-check list passes. + **Shipped on the ORM side.** D1, D2 (prisma/orm#30251, rc.10), D3 (create-prisma#96), D6, and D14 (prisma/orm#30250, #30264, #30283). D16 is no longer needed. D4, D5, and D11 are partly fixed; see each item. **Partly done.** A1: `/prisma-orm` has pages for create-prisma, the quickstart, from scratch, and an existing project, but the sidebar groups them by tool, the empty-database and Prisma 7 starting states have no door, and `/orm` is unchanged. A6: `orm/core-concepts.mdx` is prose but not written from `mental-model.md`; the item lists what it lacks. C2, C3, C6, C7, C8, C10, C17, C18: the facts are on existing pages, but the page each item asks for does not exist; each item says what is left. -**Not started.** A3, A5, A8. C9's Vercel page and shutdown example, C19, C22, C23. Every gap in section E. On the ORM side: D7, D8, D9 (prisma/orm#30370 is open), D10 (prisma/orm#30301 and #30308 are open), D12, D13, D15, D17, D18, and the Node 24.0 to 24.10 range. +**Not started.** A3, A5, A8. C9's Vercel page and shutdown example, C19, C22, C23. On the ORM side: D7, D8, D9 (prisma/orm#30370 is open), D10 (prisma/orm#30301 and #30308 are open), D12, D13, D15, D17, D18, and the Node 24.0 to 24.10 range. ## Recommended order for the open work @@ -112,7 +114,7 @@ Grouped by where the page lives. Each says what the page is for, what it must co ## E. Gaps found after the audit -Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28 (E12 was found on 2026-09-28 after the C23 decision); none is fixed yet. Each is small and verified. Specified as one slice in `slices/01-migration-and-cli-gaps/spec.md`, which also removes a `./path` contract reference form that five CLI pages list and no command accepts. Grounding the slice found CLI defects in the same area (`./path` in the CLI's help text, `@contract` and `@db` refused or mishandled by `migration status`, `db migrate`, and `db update`, and `migration status` reporting `Up to date` right after `db update`), fixed in prisma/orm#30475. +Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28 (E12 was found on 2026-09-28 after the C23 decision). Each is small and verified. E1 to E12 are in review as prisma/web#8348, with every command run on `prisma` 8.0.0-rc.19; the evidence is in `slices/01-migration-and-cli-gaps/`. Two cells of the spec's table did not hold on rc.17 or rc.19: `migration plan --to` and `db migrate --to` reject `@empty`, while `db migrate --show --to` accepts it. The pull request follows the CLI. When a release contains prisma/orm#30475, draft prisma/web#8349 updates the same table and rows; its description lists the commands to re-run first. Specified as one slice in `slices/01-migration-and-cli-gaps/spec.md`, which also removes a `./path` contract reference form that five CLI pages list and no command accepts. Grounding the slice found CLI defects in the same area (`./path` in the CLI's help text, `@contract` and `@db` refused or mishandled by `migration status`, `db migrate`, and `db update`, and `migration status` reporting `Up to date` right after `db update`), fixed in prisma/orm#30475. - **E1. The migration graph drawing's column symbols.** `orm/migrations/the-migration-graph.mdx` defines `○` and `↑↓⟲` but not `│ │` and `│─╯`, and defers to `--legend`. - **E2. `^` on The migration graph.** Used twice with no explanation or link; it is explained on `rollbacks-and-recovery.mdx`, `cli/migration-plan.mdx`, and `cli/migration-ref.mdx`. @@ -127,6 +129,17 @@ Found by the reader rounds on #8309 and #8310 and rechecked on 2026-09-28 (E12 w - **E11. The error reference names the wrong source repository.** The header `apps/docs/scripts/generate-error-reference.mjs` writes into `orm/reference/error-reference.mdx` points at `prisma/prisma`; the repository is `prisma/orm`. - **E12. Links to examples in prisma/orm.** Four pages send readers to `examples/` in prisma/orm, which exist for end-to-end tests: `orm/extensions/using-extensions.mdx` (the pgvector, PostGIS, ParadeDB, and Supabase demos), `orm/migrations/editing-a-migration.mdx` and `orm/reference/migration-api.mdx` (a `migration.ts` in the retail-store example), and `orm/migrations/the-migration-graph.mdx` (the "Try it on real fixtures" section). Remove each link; where the page needs the code, show it on the page. +Found while delivering E1 to E12, and not fixed by #8348: + +- **E13. The contract reference table is on a concept page.** #8348 puts the single table of accepted forms on `orm/migrations/the-migration-graph.mdx`, and five CLI pages link into it. `apps/docs/CLAUDE.md` says reference material belongs under `cli/`. Move it during the restructure. +- **E14. `cli/init.mdx` does not say that `init` adds `prisma` to `devDependencies`.** The rc.19 help text says it does. +- **E15. One hand-edited migration file, two codes.** `migration check` reports `MIGRATION.CHECK_HASH_MISMATCH` (exit 4); `db migrate` and `migration status` report `MIGRATION.CONTRACT_SPACE_VIOLATION` (exit 2). No page links them. See D26. +- **E16. Rollback in production is described three ways.** `rollbacks-and-recovery.mdx` step 4 runs plain `db migrate`; `how-migrations-work.mdx` says CI and production use `db migrate --to `; the Common tasks table on the graph page says `--to `. None says whether to move the `prod` ref back first. +- **E17. The Baselines paragraph on the graph page.** After `db sign`, the `db` ref and `contract.json` name the same state, so a reader cannot see what the next `migration plan` writes. +- **E18. "Newest migration" on `rollbacks-and-recovery.mdx`.** `--from ` is unclear once the history has branches. +- **E19. Reader marks on text #8348 did not write.** Two reader rounds left about 50 marks on unchanged text of the pages #8348 touched: `slices/01-migration-and-cli-gaps/reviews/reader-round*.md`, the ones labelled EXISTING. +- **E20. `prisma/prisma` names that rely on GitHub's redirect.** The repository is `prisma/orm`. Still named the old way in `npx skills add prisma/prisma/skills` on `ai/tools/skills.mdx`, `apps/docs/src/lib/agent-skill.ts`, and `apps/site/src/lib/agent-skills.ts` (whether `npx skills add` accepts `prisma/orm/skills` is an open question below); in the GitHub API URL in `packages/ui/src/hooks/use-star-count.ts` and the star link label in `apps/site/src/components/ecosystem/grid.tsx`; and in a comment in `apps/docs/next.config.mjs`. + ## D. Change the ORM and its tooling Places where the docs are hard because the tool is. Grouped by who owns the fix. @@ -150,6 +163,13 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. - **D20. An existing MongoDB collection cannot be adopted.** Found 2026-09-29 on `prisma` 8.0.0-rc.19 and `@prisma/orm-mongo` 8.0.0-rc.13, against a collection with data and a unique index: `db sign` exits 4 (`missing: users/validator`) and suggests `db update`; `db update` exits 2 with `CLI.CONSENT_TOKEN_UNRESOLVED` ("has no name to confirm") although the URL names the database, with or without `--confirm`, `--db`, or `--yes`; `db init` fails with `MIGRATION.PLANNING_FAILED` ("destructive operation disallowed: Add validator on users"); `migration plan` then `db migrate` fails on `collection.users.create`. The path that should work adds a strict validator (`additionalProperties: false`) to a collection that holds data. Until fixed, the MongoDB existing-database page shows queries only. - **D21. `orm init` fails in a project installed with Bun.** Found 2026-09-29: `bunx prisma@latest orm init` exits 5 with `CLI.INIT_EMIT_FAILED` ("A Scope already named Array already exists"), because `prisma@8.0.0-rc.19` depends on `@prisma/cli-engine@0.6.2` while `@prisma/orm-toolchain@8.0.0-rc.13` declares a peer on `0.6.1`, and Bun installs both. npm works. Running a script with `bun script.ts` in an npm-installed project works. Affects the Bun floor decided for C18. - **D22. `contract infer` skips other schemas silently.** Found 2026-09-29: a table in a second schema is not read and no message says so. Part of D5's `public`-only item. +- **D23. `migration status --json` prints `{bin}`.** Found 2026-09-29 on rc.19: `result.summary` and the hints in `result.diagnostics[]` contain the literal `{bin}`. The human output prints `prisma` since `@prisma/cli-engine` 0.6.2. +- **D24. `migration new --from` accepts a hash prefix shorter than 6 characters.** Found 2026-09-29 on rc.17 and rc.19: `--from 9` works; every other command rejects a 5-character prefix with `MIGRATION.REF_NOT_FOUND`. The docs give 6 as the minimum for every command. +- **D25. `migration status` with `@db`.** Found 2026-09-29 on rc.17 and rc.19: `--from @db` exits 0 and prints `Up to date` with a migration pending; `--to @db` warns about a target named `()`. prisma/orm#30475 changes how `migration status` resolves `@db`; recheck when it ships. +- **D26. A hand-edited migration file.** Found 2026-09-29 on rc.19: `db migrate --show` prints a route through a migration whose `ops.json` was edited, while `db migrate` refuses it. The same edit gets `MIGRATION.CHECK_HASH_MISMATCH` from `migration check` and `MIGRATION.CONTRACT_SPACE_VIOLATION` from `db migrate` and `migration status`. See E15. +- **D27. `db migrate --show` errors name `prisma migrate --show`.** Found 2026-09-30: in `control-api/operations/migrate-show.ts`, `commandName: 'migrate --show'` has no `retryCommand`, so the fix text reads "Run `prisma migrate --show --db `", a command that does not exist. prisma/orm#30475 rewrites those lines; reported there on 2026-09-30. +- **D28. prisma/orm#30475 leaves three defects.** Found 2026-09-30 by running its branch (`20615a96f0`): `db migrate --to @db` on a database with no marker fails with `MIGRATION.RUNNER_FAILED`; `db migrate --to @empty` never succeeds (the same `RUNNER_FAILED` on an empty database, `PATH_UNREACHABLE` otherwise) although the new help text lists it; and the help for `migration status --from` ("switches to offline path computation") and `db migrate --from` (leaves out the prefix, `^`, and `@empty`) is out of date. Reported on #30475. The evidence is in the description of prisma/web#8349. +- **D29. Offline `migration status` reports a backward target as up to date.** Found 2026-09-30 on #30475's branch, and not caused by it: `migration status --from --to ` with no database prints `Up to date`, although no migration leads back. ### Product decisions @@ -169,7 +189,7 @@ Places where the docs are hard because the tool is. Grouped by who owns the fix. ### Monorepo docs hygiene -- **D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` disagrees with the site's capabilities page on key namespacing, pack key nesting, the error code spelling, and whether capabilities are fixed at emit or negotiated at connect. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`, which does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md`, from which the site's error reference is generated verbatim, still says `ref set` and `prisma ref set` in eight entries (the command is `migration ref set` since rc.5). `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Until reconciled, the audit treats `packages/` and `docs/releases/` as the only truth. Rechecked on 2026-09-28: all five claims still hold, and `error-reference.md` now has nine bare `ref set` lines, two of them `prisma ref set`. +- **D17. `docs/reference/` and `docs/Supported Versions.md` disagree with the site and partly with the source.** `reference/capabilities.md` disagrees with the site's capabilities page on key namespacing, pack key nesting, the error code spelling, and whether capabilities are fixed at emit or negotiated at connect. `Supported Versions.md` says Node 24 and documents `--merge-tsconfig`, which does not exist. `Telemetry.md` says no exit code is sent; rc.9 sends one. `docs/reference/error-reference.md`, from which the site's error reference is generated verbatim, still says `ref set` and `prisma ref set` in eight entries (the command is `migration ref set` since rc.5). `mongodb-user-promise.md` promises MongoDB referential actions that are not implemented. Until reconciled, the audit treats `packages/` and `docs/releases/` as the only truth. Rechecked on 2026-09-28: all five claims still hold, and `error-reference.md` now has nine bare `ref set` lines, two of them `prisma ref set`. The command names in `error-reference.md` are in review as prisma/orm#30527 (2026-09-30): 29 entries named `ref`, `migrate`, `format`, `init`, `inspect-live-schema`, or `db run` without the group or by an old name. No production message names a bare `ref` command. The other four claims are still open. ## Naming diff --git a/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/facts-rc19.md b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/facts-rc19.md new file mode 100644 index 00000000000..e029ef8708f --- /dev/null +++ b/docs/orm-docs-audit/slices/01-migration-and-cli-gaps/facts-rc19.md @@ -0,0 +1,1316 @@ +# Facts verified on prisma@8.0.0-rc.19 + +Run on 2026-09-29. Every command ran in a scratch project under `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps`. Full logs are beside this file; each section names its log. + +## Versions + +| Component | Version | +| --- | --- | +| `prisma` | 8.0.0-rc.19 (npm `latest`, confirmed with `npm view prisma dist-tags`) | +| `@prisma/orm-postgres` | 8.0.0-rc.13 (npm `latest`) | +| `@prisma/cli-engine` | 0.6.2 (`orm init` added it as a dev dependency; `@prisma/orm-toolchain@8.0.0-rc.13` declares a peer dependency on 0.6.1, so npm prints a peer warning) | +| Node.js | v24.13.0 | +| PostgreSQL | 15.16 (Homebrew), port 54329, stopped at the end of the run | + +`npx prisma --version` prints `8.0.0-rc.19` (exit 0). + +Setup: `npx prisma orm init --yes --target postgres --authoring psl`. It wrote the contract to `src/prisma/contract.prisma` and emits `src/prisma/contract.json`, not `prisma/contract.json`. The starter contract has `User` and `Post`, so the baseline has 6 operations. I set `"type": "module"` in `package.json` because `npm init` wrote `commonjs` and `orm init` warned about it. + +Output mode: in this shell the CLI prints JSON by default, so every command ran with `--format human --no-color`. The logs omit those two flags from the printed command line. I removed one line from every output: `Prisma agent skills are out of date (...)`. + +Hashes in this run: baseline ends at `91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e` (called H1 below). `add_user_phone` ends at `a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d` (H2). The ref `prod` names H1. + +## Items that differ from the spec + +1. **E3, `migration plan --to @empty`: rejected.** The spec table says `migration plan --from`, `--to` accept `@empty`. Only `--from` does. `--to @empty` exits 2 with `MIGRATION.REF_WRONG_GRAMMAR`. rc.17 does the same, so the spec table was wrong for this cell on both versions. +2. **E3, `db migrate --to @empty` (without `--show`): I found no run that succeeds.** On an empty database it exits 2 with `MIGRATION.RUNNER_FAILED`. On a database at H1 it exits 2 with `MIGRATION.PATH_UNREACHABLE`. rc.17 gives the same `RUNNER_FAILED`. `db migrate --show --to @empty` does work (exit 0 on an empty database). +3. **E3, `migration new --from` accepts prefixes shorter than 6 characters.** The spec says a hash prefix is the first 6 or more characters. `migration new --from 91e7f`, `91e7`, `91e`, and `9` all exit 0 and scaffold from H1. Every other command rejects the 5-character prefix with `MIGRATION.REF_NOT_FOUND`. rc.17 also accepts `91e7f` here. +4. **E7, `{bin}` is still in `--json` output.** Human output prints `prisma`, as amendment 2 in `plan.md` expects. The `--json` output still has `{bin}` in `result.summary` and in `result.diagnostics[].hints`. This matters only if a page shows JSON output. + +Everything else matches. Three observations that do not contradict the spec, but that a page author should know: + +- `migration status --from @db` and `--to @db` exit 0 on rc.19 but give wrong answers (`--from @db` prints `Up to date` with one migration pending; `--to @db` warns about a target named `()`). The spec already says not to list `@db` there. rc.17 behaves the same. +- E9: `init --help` on rc.19 says `init` also adds `prisma` to `devDependencies` when no dependency field declares it. `apps/docs/content/docs/cli/init.mdx` lists three actions and does not mention this one. +- E6: `db migrate --show` does not refuse a hand-edited `ops.json`; it printed the route. I did not test whether `db migrate` without `--show` refuses it. + +## Could not verify + +- "A hash prefix matches exactly one contract state": I could not produce two contract hashes that share a 6-character prefix, so I did not test an ambiguous prefix. +- `npx prisma@latest` failed in the shared npm cache (`npm error ENOTEMPTY` in `~/.npm/_npx`). I ran E9 with a private npm cache inside `wip/gaps` and deleted that cache afterwards. I did not touch `~/.npm`. + +## 1. E3: contract reference forms + +Script: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/e3.sh`. Full output: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/e3.log`. One line per run: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/e3-summary.tsv`. Follow-up probes: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/e3-followup.log`. rc.17 comparison: `/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/rc17.log`. + +Method: before every run the script restored `migrations/` from a clean copy. Commands that change a database ran against a throwaway database cloned from a template (empty, at H1, or at H2). Read-only commands ran against the database `gaps`, which is at H1. + +Forms tested, all naming H1 where the form can name a state: full hash; prefixes of 12, 7, 6, and 5 characters; `prod`; `20260929T1558_baseline`; `20260929T1558_add_user_phone^`; `@empty`; `@contract`; `@db`; `./migrations/app/20260929T1558_baseline`; `./src/prisma/contract.json`; `./migrations/snapshots/

/contract.json`. + +Cell values: `ok` means exit 0. Anything else is the error code, and the exit code was 2. Codes without a namespace are in `MIGRATION.`. `migration plan --to` ran with `--from

`. + +| Command | full-hash | prefix-12 | prefix-7 | prefix-6 | prefix-5 | ref-name | dir-name | dir^ | @empty | @contract | @db | path-migration-dir | path-contract-json | path-snapshot-json | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| `migration plan --from` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | ok | REF_NOT_FOUND | HASH_NOT_IN_GRAPH | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `migration plan --to` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | REF_WRONG_GRAMMAR | REF_NOT_FOUND | HASH_NOT_IN_GRAPH | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `migration new --from` | ok | ok | ok | ok | ok | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | HASH_NOT_IN_GRAPH | +| `migration ref set` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | REF_SET_EMPTY_SENTINEL | REF_NOT_FOUND | HASH_NOT_IN_GRAPH | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `migration status --from` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | ok | REF_NOT_FOUND | ok | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `migration status --to` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | ok | REF_NOT_FOUND | ok | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db migrate --to (empty db)` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | RUNNER_FAILED | REF_NOT_FOUND | PATH_UNREACHABLE | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db migrate --to (db at H1)` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | PATH_UNREACHABLE | REF_NOT_FOUND | PATH_UNREACHABLE | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db migrate --show --to` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | PATH_UNREACHABLE | ok | CONFIG.DB_CONNECTION_REQUIRED | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db migrate --show --from` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | ok | ok | ok | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db update --dry-run --to` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | CLI.UNEXPECTED | REF_NOT_FOUND | CLI.UNEXPECTED | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db update --to (db at H2)` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | CLI.UNEXPECTED | REF_NOT_FOUND | CLI.UNEXPECTED | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db sign [contract] (db at H1)` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | SNAPSHOT_MISSING | REF_NOT_FOUND | SNAPSHOT_MISSING | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | +| `db sign --contract (db at H1)` | ok | ok | ok | ok | REF_NOT_FOUND | ok | ok | ok | SNAPSHOT_MISSING | REF_NOT_FOUND | SNAPSHOT_MISSING | REF_NOT_FOUND | REF_NOT_FOUND | REF_NOT_FOUND | + +Verdict per row of the spec table: + +| Spec row | Verdict | Notes | +| --- | --- | --- | +| `migration plan --from`, `--to` | **DIFFERS** | `--from` matches. `--to @empty` is rejected with `MIGRATION.REF_WRONG_GRAMMAR`. | +| `migration new --from` | **DIFFERS** | Accepts a hash and a prefix, rejects every other form with `MIGRATION.HASH_NOT_IN_GRAPH`. It also accepts prefixes of 5, 4, 3, and 1 characters. | +| `migration ref set ` | MATCH | `@empty` is rejected with `MIGRATION.REF_SET_EMPTY_SENTINEL`. | +| `migration status --from`, `--to` | MATCH | `@contract` is rejected. `@db` exits 0 but is mishandled; the spec does not list it. | +| `db migrate --to` | **DIFFERS** for `@empty` | The five basic forms match. `@empty` never succeeded. `@contract` is rejected with `MIGRATION.REF_NOT_FOUND` and `@db` fails with `MIGRATION.PATH_UNREACHABLE`, as the spec says. | +| `db migrate --show --to` | MATCH | `@empty` exits 0 on an empty database; on the database at H1 it fails with `MIGRATION.PATH_UNREACHABLE` because no migration leads back to empty. `@contract` works. `@db` is rejected with `CONFIG.DB_CONNECTION_REQUIRED` and the reason "@db is not valid as a --to target". | +| `db migrate --show --from` | MATCH | All eight forms exit 0. | +| `db update --to` | MATCH | `@empty` and `@db` crash with `CLI.UNEXPECTED`, `@contract` gives `MIGRATION.REF_NOT_FOUND`. Same with and without `--dry-run`. | +| `db sign [contract]`, `--contract` | MATCH | Both accept `^`. Both reject `@empty` and `@db` with `MIGRATION.SNAPSHOT_MISSING`. | +| "A hash prefix is the first 6 or more characters" | MATCH, except `migration new --from` | 6 accepted and 5 rejected on every other command. | +| "No command accepts a file path" | MATCH | Rejected in every cell. `migrations/app/` without `./`, an absolute path, and `src/prisma/contract.json` are rejected too. | + +The help text on rc.19 still advertises `./path` for `migration plan --from`, `migration status --to`, `db migrate --to`, `db update --to`, and `db sign --contract` (see `help.txt`). No command accepts it. + +Outputs for the cells that differ: + +```text +$ npx prisma migration plan --from a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d --to @empty --name t +✘ [MIGRATION.REF_WRONG_GRAMMAR] `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut + why: `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut +→ Pass `--to` a contract hash, ref name, or migration directory name. To plan starting from an empty database, use `--from @empty`. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_WRONG_GRAMMAR +[exit 2] + +$ npx prisma db migrate --to @empty --db postgresql://postgres@localhost:54329/t_e +▸ Running migration plan across spaces +✘ Running migration plan across spaces +✘ [MIGRATION.RUNNER_FAILED] Plan destination storage hash (empty) does not match provided contract storage hash (a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d). + why: Migration runner failed +→ Fix the issue and re-run `prisma db migrate --to ` — previously applied migrations are preserved. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.RUNNER_FAILED +[exit 2] + +$ npx prisma db migrate --to @empty --db postgresql://postgres@localhost:54329/t_h1 +✘ [MIGRATION.PATH_UNREACHABLE] Current contract has no planned migration path + why: No migration edge connects the current state "91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e" to the target "empty" in contract space "app". The on-disk migration graph does not join the two, and migrate replays existing edges — it never invents one. +→ Plan the missing edge: prisma migration plan --from 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e --to empty --name +→ Apply it: prisma db migrate --to empty + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.PATH_UNREACHABLE +[exit 2] + +$ npx prisma migration new --from 91e7f --name t +│ contract: src/prisma/contract.json +│ migrations: migrations/app + +✔ Scaffolded migration at migrations/app/20260929T1600_t + +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d + +→ Write the migration body in migrations/app/20260929T1600_t/migration.ts +→ Run it to self-emit ops.json and attest the package: node "migrations/app/20260929T1600_t/migration.ts" +[exit 0] + +$ npx prisma migration status --from @db +│ migrations: migrations +│ from: @db + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops +○ 91e7f9f (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops +○ ∅ + +✔ Up to date +[exit 0] + +$ npx prisma migration status --to @db +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops +○ 91e7f9f @db (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ No migration path from the database state (91e7f9f03580) to the target (). Run `prisma migration plan --name ` to author one, or pass `--to ` to pick a reachable target. +[exit 0] + +``` + +Follow-up probes (output trimmed to status lines): + +```text +$ npx prisma migration new --from 91e7 --name t +✔ Scaffolded migration at migrations/app/20260929T1605_t +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +[exit 0] +$ npx prisma migration new --from 91e --name t +✔ Scaffolded migration at migrations/app/20260929T1605_t +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +[exit 0] +$ npx prisma migration new --from 9 --name t +✔ Scaffolded migration at migrations/app/20260929T1606_t +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +[exit 0] +$ npx prisma migration new --from 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784f --name t +✘ [MIGRATION.HASH_NOT_IN_GRAPH] Starting contract not found + why: No migration with to hash matching "91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784f" exists in migrations/app +[exit 2] +$ npx prisma migration plan --to @empty --name t +✘ [MIGRATION.REF_WRONG_GRAMMAR] `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut + why: `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut +[exit 2] +$ npx prisma migration plan --from prod --to @empty --name t +✘ [MIGRATION.REF_WRONG_GRAMMAR] `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut + why: `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut +[exit 2] +$ npx prisma db migrate --show --to @empty --db postgresql://postgres@localhost:54329/t_e +ℹ Already up to date — nothing to run +[exit 0] +$ npx prisma db migrate --show --from @empty --to @empty --db postgresql://postgres@localhost:54329/t_e +ℹ Already up to date — nothing to run +[exit 0] +$ npx prisma db migrate --show --from @empty --db postgresql://postgres@localhost:54329/t_e +ℹ The following 2 migrations will run: +[exit 0] +$ npx prisma db migrate --show --to @contract --db postgresql://postgres@localhost:54329/t_e +ℹ The following 2 migrations will run: +[exit 0] +$ npx prisma db migrate --show --from @db --db postgresql://postgres@localhost:54329/t_e +ℹ The following 2 migrations will run: +[exit 0] +--- other path spellings +$ npx prisma migration plan --from migrations/app/20260929T1558_baseline --name t +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "migrations/app/20260929T1558_baseline" + why: No contract matching "migrations/app/20260929T1558_baseline" exists in the migration graph or refs index. +[exit 2] +$ npx prisma migration plan --from /Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/work/migrations/app/20260929T1558_baseline --name t +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/work/migrations/app/20260929T1558_baseline" + why: No contract matching "/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/work/migrations/app/20260929T1558_baseline" exists in the migration graph or refs index. +[exit 2] +$ npx prisma db migrate --show --to migrations/app/20260929T1558_baseline +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "migrations/app/20260929T1558_baseline" + why: No contract matching "migrations/app/20260929T1558_baseline" exists in the migration graph or refs index. +[exit 2] +$ npx prisma db sign --contract src/prisma/contract.json --db postgresql://postgres@localhost:54329/t_e +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "src/prisma/contract.json" + why: No contract matching "src/prisma/contract.json" exists in the migration graph or refs index. +[exit 2] +--- status with @ tokens and no database configured +$ npx prisma migration status --from @db +✔ Up to date +[exit 0] +$ npx prisma migration status --from @contract +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "@contract" + why: No contract matching "@contract" exists in the migration graph or refs index. +[exit 2] +$ npx prisma migration status --from @empty --to @empty +✔ Up to date +[exit 0] +``` + +The same cells on rc.17 (`prisma@8.0.0-rc.17`, `@prisma/orm-postgres@8.0.0-rc.12`, `@prisma/cli-engine@0.6.1`). The first `migration plan --to @empty` run failed for another reason, because rc.17 cannot read snapshots that rc.19 wrote, so I rebuilt the history with rc.17 and ran it again: + +```text +8.0.0-rc.17 +| `-- @prisma/cli-engine@0.6.1 deduped + +-- @prisma/cli-engine@0.6.1 + `-- @prisma/cli-engine@0.6.1 deduped +storageHash: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +$ npx prisma migration new --from 91e7f --name t +✔ Scaffolded migration at migrations/app/20260929T1612_t +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +[exit 0] +$ npx prisma migration plan --from a4c3fa7fc3b2 --to @empty --name t +✘ [CONTRACT.VALIDATION_FAILED] Contract validation failed + why: Predecessor contract at /Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/rc17/migrations/snapshots/a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d/contract.json failed to deserialize: Contract structural validation failed: execution.mutations.defaults +[exit 2] +$ npx prisma db migrate --to @empty --db postgresql://postgres@localhost:54329/t_e +✘ Running migration plan across spaces +✘ [MIGRATION.RUNNER_FAILED] Plan destination storage hash (empty) does not match provided contract storage hash (a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d). + why: Migration runner failed +[exit 2] +$ npx prisma db migrate --show --to @empty --db postgresql://postgres@localhost:54329/t_e +ℹ Already up to date — nothing to run +[exit 0] +$ npx prisma migration status --from @db +✔ Up to date +[exit 0] +$ npx prisma migration status --to @db +⚠ No migration path from the database state (91e7f9f03580) to the target (). Run `{bin} migration plan --name ` to author one, or pass `--to ` to pick a reachable target. +[exit 0] + +⚠ 1 pending — run `{bin} db migrate --to a4c3fa7fc3b2` +[exit 0] + +--- history rebuilt with rc.17 +storageHash: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +$ npx prisma migration plan --name baseline +✔ Planned 6 operation(s) +ℹ No db ref set — planning from an empty database. Run db init, db update, or db sign if a database already exists. +from: (baseline) +to: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +ℹ DDL preview +[exit 0] +storageHash: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +$ npx prisma migration plan --name add_user_phone --from @empty +✔ Planned 6 operation(s) +from: (baseline) +20260929T1612_add_user_phone +20260929T1612_baseline +$ npx prisma migration plan --from 20260929T1612_baseline --name add_user_phone +✘ [MIGRATION.DIR_EXISTS] Migration directory already exists + why: The directory "/Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/rc17/migrations/app/20260929T1612_add_user_phone" already exists. Each migration must have a unique directory. +[exit 2] +$ npx prisma migration plan --from 20260929T1612_add_user_phone --to @empty --name t +✘ [MIGRATION.REF_WRONG_GRAMMAR] `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut + why: `@empty` is only valid as an origin (`--from`); planning a migration to the empty contract is not supported through this shortcut +[exit 2] +$ npx prisma migration plan --to @empty --name t +✘ [MIGRATION.PLAN_ORIGIN_UNKNOWN] Cannot determine the plan origin: migrations exist but no origin is named + why: Migrations exist on disk, but there is no `db` ref and no --from was given, so the plan origin would silently fall back to an empty database and the resulting migration would recreate everything the existing migrations already create. +[exit 2] +``` + +## 2. E1: migration graph and --legend + +Verdict: MATCH. Log: `e1.log`. Project: `graph/`. History: `init`, then `alice_add_phone` and `bob_add_avatar` both planned with `--from `, `prod` set to Bob's migration, then `alice_merge` planned with `--from prod`. + +`--legend` explains `○`, `↑`, `↓`, `⟲`, `✓`, `⧗`, `∅`, `@contract` and `@db`, ref labels, and the `aaaaaa → bbbbbb` notation. It prints the key after the drawing. It does not explain `│`, `─`, or `╯`. + +```text +$ npx prisma migration graph +│ migrations: migrations + + ○ b68f9a4 @contract + │↑ 20260929T1601_alice_merge 59b927f → b68f9a4 1 ops +○ │ a4c3fa7 +│↑│ 20260929T1601_alice_add_phone 91e7f9f → a4c3fa7 1 ops +│ ○ 59b927f (prod) +│ │↑ 20260929T1601_bob_add_avatar 91e7f9f → 59b927f 1 ops +│─╯ +○ 91e7f9f +│↑ 20260929T1601_init ∅ → 91e7f9f 6 ops +○ ∅ + +1 space(s), 5 contract(s), 4 migration(s) +[exit 0] + +$ npx prisma migration graph --legend +│ migrations: migrations + + ○ b68f9a4 @contract + │↑ 20260929T1601_alice_merge 59b927f → b68f9a4 1 ops +○ │ a4c3fa7 +│↑│ 20260929T1601_alice_add_phone 91e7f9f → a4c3fa7 1 ops +│ ○ 59b927f (prod) +│ │↑ 20260929T1601_bob_add_avatar 91e7f9f → 59b927f 1 ops +│─╯ +○ 91e7f9f +│↑ 20260929T1601_init ∅ → 91e7f9f 6 ops +○ ∅ + +1 space(s), 5 contract(s), 4 migration(s) + +Legend: + ○ contract ↑ forward ↓ rollback + ⟲ migration without schema change + ✓ applied ⧗ pending + ∅ empty database (baseline) + @contract @db reserved markers — also typeable as --from/--to tokens + (prod, staging) user-defined refs + aaaaaa → bbbbbb migration from contract aaaaaa to bbbbbb +[exit 0] + +$ npx prisma migration graph --ascii +│ migrations: migrations + + * b68f9a4 @contract + |^ 20260929T1601_alice_merge 59b927f -> b68f9a4 1 ops +* | a4c3fa7 +|^| 20260929T1601_alice_add_phone 91e7f9f -> a4c3fa7 1 ops +| * 59b927f (prod) +| |^ 20260929T1601_bob_add_avatar 91e7f9f -> 59b927f 1 ops +|-/ +* 91e7f9f +|^ 20260929T1601_init - -> 91e7f9f 6 ops +* - + +1 space(s), 5 contract(s), 4 migration(s) +[exit 0] + +``` + +## 3. E4: replacing migrate reset + +Verdict: MATCH on every point. Logs: `e4a.log`, `e4b.log`. Project: `work/`, database `mydb`. `dropdb` and `createdb` ran with `PGHOST=localhost PGPORT=54329 PGUSER=postgres`. + +| Fact | Result | +| --- | --- | +| `dropdb --if-exists mydb`, `createdb mydb`, `npx prisma db migrate --advance-ref db` rebuilds | exit 0 each; `Applied 2 migration(s) (7 operation(s))`; `db verify` then passes | +| `npx prisma db init` as the last line instead | exit 0; `Applied 5 operation(s) across 1 contract space`; creates the tables and the marker without running the migrations (the ledger has one row with an empty `migration_name`); `db verify` passes; `migration status` prints `Up to date` | +| `db migrate` runs no seed script | With `prisma.seed` and `scripts.seed` set in `package.json` to write `seed-ran.txt`, `db migrate` exited 0 and the file was not created. The CLI has no seed option in any help text. | +| Drop only `public` | The marker row survives in `prisma_contract.marker`; `db migrate --advance-ref db` prints `Already up to date` (exit 0) with no tables; `db verify` exits 4 with `CONTRACT.SCHEMA_VERIFICATION_FAILED` (24 failures); `migration status` prints `Up to date` | +| Drop `public` and `prisma_contract` | `db migrate --advance-ref db` applies both migrations (exit 0); `db verify` passes | + +```text +--- drop only public +$ psql -d mydb -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;' +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table "Post" +drop cascades to table "User" +DROP SCHEMA +CREATE SCHEMA + space | core_hash +-------+------------------------------------------------------------------ + app | a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +(1 row) + +Did not find any relation named "public.*". +$ npx prisma db migrate --advance-ref db +│ migrations: migrations +│ database: postgresql://****@localhost:54329/mydb + +✔ Already up to date + +App space +├─ (no operations) +└─ marker a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d + +✔ Advanced ref "db" → a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +→ Check every space against the database: prisma migration status +[exit 0] + +``` + +`db verify` after dropping only `public` (issue list trimmed): + +```text +$ npx prisma db verify +▸ Connecting to database... +✔ Connecting to database... +▸ Verifying database marker... +✔ Verifying database marker... +▸ Introspecting database schema +✔ Introspecting database schema +▸ Verifying contract spaces +✔ Verifying contract spaces +│ contract: src/prisma/contract.json +│ mode: full (marker + schema, tolerant) +│ database: postgresql://****@localhost:54329/mydb + +✘ Schema issues + +✘ Database schema does not satisfy contract (24 failures) + +✘ [CONTRACT.SCHEMA_VERIFICATION_FAILED] Database schema does not satisfy contract (24 failures) + why: The live schema differs: missing: database/public/Post; missing: database/public/Post/column:authorId; missing: database/public/Post/column:content; missing: database/public/Post/column:created +→ Push the contract to the database: prisma db update +→ Or reconcile the differences by hand and verify again + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/CONTRACT.SCHEMA_VERIFICATION_FAILED +[exit 4] + +``` + +After dropping both schemas: + +```text +--- drop both schemas +$ psql -d mydb -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public; DROP SCHEMA prisma_contract CASCADE;' +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table prisma_contract.marker +drop cascades to table prisma_contract.ledger +drop cascades to table prisma_contract.contract +DROP SCHEMA +CREATE SCHEMA +DROP SCHEMA +$ npx prisma db migrate --advance-ref db +▸ Running migration plan across spaces +✔ Running migration plan across spaces +│ migrations: migrations +│ database: postgresql://****@localhost:54329/mydb + +✔ Applied 2 migration(s) (7 operation(s)) across 1 contract space(s) + +App space +├─ Create schema "public" +├─ Create table "Post" +├─ Create table "User" +├─ Add unique constraint on "User" (email) +├─ Create index "Post_authorId_idx_e47547ed" on "Post" +├─ Add foreign key "Post_authorId_fkey" on "Post" +├─ Add column "phone" to "User" +└─ marker a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d + +✔ Advanced ref "db" → a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +→ Check every space against the database: prisma migration status +[exit 0] + +$ npx prisma db verify +▸ Connecting to database... +✔ Connecting to database... +▸ Verifying database marker... +✔ Verifying database marker... +▸ Introspecting database schema +✔ Introspecting database schema +▸ Verifying contract spaces +✔ Verifying contract spaces +│ contract: src/prisma/contract.json +│ mode: full (marker + schema, tolerant) +│ database: postgresql://****@localhost:54329/mydb + +✔ Database marker and schema match contract + +storageHash: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +profileHash: 3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2 +[exit 0] + + List of relations + Schema | Name | Type | Owner +--------+------+-------+---------- + public | Post | table | postgres + public | User | table | postgres +(2 rows) + +``` + +## 4. E5: db verify --schema-only + +Verdict: MATCH. Log: `e5.log`. The tables in `mydb` matched the contract (H2) throughout the first three cases. + +| Database state | `db verify` | `db verify --schema-only` | +| --- | --- | --- | +| Marker changed to H1 | exit 4, `CONTRACT.MARKER_MISMATCH` | exit 0, `Database schema satisfies contract` | +| Marker row deleted | exit 4, `CONTRACT.MARKER_MISSING` | exit 0 | +| `prisma_contract` schema dropped | exit 4, `CONTRACT.MARKER_MISSING` | exit 0 | +| `phone` column changed to `integer` | not run | exit 4, `CONTRACT.SCHEMA_VERIFICATION_FAILED`, `mismatch: database/public/User/column:phone` | +| Extra table `extra` | not run | exit 0; with `--strict`, exit 4 with `CONTRACT.MARKER_REQUIRED` (the marker schema was still dropped in this run) | + +The mode line reads `mode: schema only (tolerant)`, and the marker step (`Verifying database marker...`) does not run. + +```text +--- marker set to the baseline hash (tables match the contract a4c3fa7) +UPDATE 1 +✔ Connecting to database... +✘ Verifying database marker... +│ mode: full (marker + schema, tolerant) +✘ Hash mismatch +✘ [CONTRACT.MARKER_MISMATCH] Hash mismatch + why: Contract storageHash does not match database marker +[exit 4] +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (tolerant) +✔ Database schema satisfies contract +[exit 0] +--- marker row deleted +DELETE 1 +✔ Connecting to database... +✘ Verifying database marker... +│ mode: full (marker + schema, tolerant) +✘ Marker missing +✘ [CONTRACT.MARKER_MISSING] Database not signed + why: No database signature (marker) found +[exit 4] +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (tolerant) +✔ Database schema satisfies contract +[exit 0] +--- prisma_contract schema dropped +DETAIL: drop cascades to table prisma_contract.marker +drop cascades to table prisma_contract.ledger +drop cascades to table prisma_contract.contract +DROP SCHEMA +✔ Connecting to database... +✘ Verifying database marker... +│ mode: full (marker + schema, tolerant) +✘ Marker missing +✘ [CONTRACT.MARKER_MISSING] Database not signed + why: No database signature (marker) found +[exit 4] +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (tolerant) +✔ Database schema satisfies contract +[exit 0] +--- column type differs: phone is integer +ALTER TABLE +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (tolerant) +✘ Schema issues +✘ Database schema does not satisfy contract (1 failure) +✘ [CONTRACT.SCHEMA_VERIFICATION_FAILED] Database schema does not satisfy contract (1 failure) + why: The live schema differs: mismatch: database/public/User/column:phone. +[exit 4] +--- extra table, tolerant and strict +ALTER TABLE +CREATE TABLE +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (tolerant) +✔ Database schema satisfies contract +[exit 0] +✔ Introspecting database schema +✔ Verifying contract spaces +│ mode: schema only (strict) +✘ Unclaimed elements (declared by no contract) +✘ Database schema has 1 unclaimed element (not in any contract) +✘ [CONTRACT.MARKER_REQUIRED] Database schema has 1 unclaimed element (not in any contract) +[exit 4] +``` + +## 5. E6: migrationHash + +Verdict: MATCH. Logs: `e6a.log`, `e6b.log`. + +| Fact | Result | +| --- | --- | +| `migrationHash` changes when `ops.json` changes | Editing a label in `ops.json` by hand: `migration check` exits 4 with `MIGRATION.CHECK_HASH_MISMATCH`, stored `e8a4473f...`, recomputed `ee7fa1f0...` | +| It changes when the rest of `migration.json` changes | Editing `createdAt` by hand: exit 4, same code, recomputed `7cb600a3...` | +| Recompiling writes a new hash | After changing `migration.ts` and running `node migrations/app//migration.ts`, `migrationHash` became `d9739ea1...` and `migration check` passed. Recompiling with no change kept `e8a4473f...` and kept `createdAt`. | +| `migration show` takes a `migrationHash` prefix | Full hash, 12 characters, and 6 characters: exit 0. 5 characters: exit 2, `MIGRATION.REF_NOT_FOUND` | +| `migration show` with a contract hash prefix | exit 2, `MIGRATION.REF_WRONG_GRAMMAR`, "Hash matched a contract but not a migration" | +| `migration show` with a ref name | exit 2, `MIGRATION.REF_WRONG_GRAMMAR` | +| `migration show` with a directory name or a directory path | exit 0 (`migration show` does accept a path to the migration directory; this is a migration reference, not a contract reference) | +| `--from` and `--to` with a `migrationHash` prefix | exit 2, `MIGRATION.REF_NOT_FOUND` on `migration status --from`, `migration status --to`, `migration plan --from`, `db migrate --show --to`, `db migrate --show --from` | + +`migration.json` has five fields: `from`, `to`, `providedInvariants`, `createdAt`, `migrationHash`. + +```text +$ npx prisma migration check +│ migrations: migrations/app + +✔ All checks passed +[exit 0] + +--- A: hand edit ops.json (label text) +$ npx prisma migration check +│ migrations: migrations/app + +✘ 1 integrity failure(s) + +✘ [MIGRATION.CHECK_HASH_MISMATCH] migrations/app/20260929T1558_add_user_phone/migration.json: Stored hash e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd does not match recomputed hash ee7fa1f0bc645d70eb56c16b8c258ef08920587bc23a0438b4ec73ebee91f09a +→ Re-emit the migration package, or restore it from version control + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.CHECK_HASH_MISMATCH +[exit 4] + +$ npx prisma migration check 20260929T1558_add_user_phone +│ migrations: migrations/app +│ target: 20260929T1558_add_user_phone + +✘ 1 integrity failure(s) + +✘ [MIGRATION.CHECK_HASH_MISMATCH] migrations/app/20260929T1558_add_user_phone/migration.json: Stored hash e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd does not match recomputed hash ee7fa1f0bc645d70eb56c16b8c258ef08920587bc23a0438b4ec73ebee91f09a +→ Re-emit the migration package, or restore it from version control + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.CHECK_HASH_MISMATCH +[exit 4] + +$ npx prisma db migrate --show --db postgresql://postgres@localhost:54329/gaps +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 ↑ will run +○ 91e7f9f @db (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f +○ ∅ + +ℹ The following 1 migration will run: + + 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 +[exit 0] + +--- B: hand edit migration.json (createdAt) +5: "createdAt": "2026-09-29T15:58:04.319Z", +5: "createdAt": "2026-09-28T15:58:04.319Z", +$ npx prisma migration check +│ migrations: migrations/app + +✘ 1 integrity failure(s) + +✘ [MIGRATION.CHECK_HASH_MISMATCH] migrations/app/20260929T1558_add_user_phone/migration.json: Stored hash e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd does not match recomputed hash 7cb600a382b12cf734cdee243fdde56158b7bc120665848cab6be5532d5d8a41 +→ Re-emit the migration package, or restore it from version control + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.CHECK_HASH_MISMATCH +[exit 4] + +--- C: edit migration.ts and recompile +``` + + +```text +--- C: edit migration.ts (phone column becomes varchar) and recompile +$ node migrations/app/20260929T1558_add_user_phone/migration.ts +Wrote ops.json + migration.json to /Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/work/migrations/app/20260929T1558_add_user_phone +[exit 0] +5: "createdAt": "2026-09-29T15:58:04.319Z", +6: "migrationHash": "d9739ea14ce921b6bc042fba10b0cf9f641b5bcfe0f7ff1e9adf76b9e44be13d" +29: "sql": "ALTER TABLE \"public\".\"User\" ADD COLUMN \"phone\" varchar" +$ npx prisma migration check +│ migrations: migrations/app + +✔ All checks passed +[exit 0] + +--- recompile with no change +$ node migrations/app/20260929T1558_add_user_phone/migration.ts +Wrote ops.json + migration.json to /Users/wmadden/Projects/prisma/web/.claude/worktrees/typescript-module-nodenext-upgrade-36b97c/wip/gaps/work/migrations/app/20260929T1558_add_user_phone +5: "createdAt": "2026-09-29T15:58:04.319Z", +6: "migrationHash": "e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd" +--- migration show forms +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: e8a4473fb1ef +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: e8a447 +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +✘ [MIGRATION.REF_NOT_FOUND] Not a known migration reference: "e8a44" + why: No migration matching "e8a44" exists in the migration graph or refs index. +→ Provide a valid migration directory name or migration hash. +[exit 2] +✘ [MIGRATION.REF_WRONG_GRAMMAR] Hash matched a contract but not a migration + why: Hash matched a contract but not a migration +→ Use a contract-accepting flag like `--to` or `--from` to reference contracts by hash. Pass `migration show ` for a specific migration. +[exit 2] +✘ [MIGRATION.REF_WRONG_GRAMMAR] Hash matched a contract but not a migration + why: Hash matched a contract but not a migration +→ Use a contract-accepting flag like `--to` or `--from` to reference contracts by hash. Pass `migration show ` for a specific migration. +[exit 2] +✘ [MIGRATION.REF_WRONG_GRAMMAR] Hash matched a contract but not a migration + why: Hash matched a contract but not a migration +→ Use a contract-accepting flag like `--to` or `--from` to reference contracts by hash. Pass `migration show ` for a specific migration. +[exit 2] +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: 20260929T1558_add_user_phone +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: migrations/app/20260929T1558_add_user_phone +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +│ contract: src/prisma/contract.json +│ migrations: migrations/app +│ target: ./migrations/app/20260929T1558_add_user_phone +✔ 20260929T1558_add_user_phone +from: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +to: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +hash: e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd +[exit 0] +✘ [MIGRATION.REF_WRONG_GRAMMAR] "prod" is a ref name, not a migration + why: "prod" is a ref name, not a migration +→ Refs point at contracts, not migrations. Use a migration directory name or migration hash. +[exit 2] +--- --from/--to with a migrationHash prefix +$ npx prisma migration status --from e8a4473fb1ef +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "e8a4473fb1ef" + why: No contract matching "e8a4473fb1ef" exists in the migration graph or refs index. +→ Provide a valid contract hash, ref name, or migration directory name. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_NOT_FOUND +[exit 2] + +$ npx prisma migration status --to e8a4473fb1ef --db postgresql://postgres@localhost:54329/gaps +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "e8a4473fb1ef" + why: No contract matching "e8a4473fb1ef" exists in the migration graph or refs index. +→ Provide a valid contract hash, ref name, or migration directory name. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_NOT_FOUND +[exit 2] + +$ npx prisma migration plan --from e8a4473fb1ef --name t +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "e8a4473fb1ef" + why: No contract matching "e8a4473fb1ef" exists in the migration graph or refs index. +→ Provide a valid contract hash, ref name, or migration directory name. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_NOT_FOUND +[exit 2] + +$ npx prisma db migrate --show --to e8a4473fb1ef --db postgresql://postgres@localhost:54329/gaps +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "e8a4473fb1ef" + why: No contract matching "e8a4473fb1ef" exists in the migration graph or refs index. +→ Provide a valid contract hash, ref name, or migration directory name. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_NOT_FOUND +[exit 2] + +$ npx prisma db migrate --show --from e8a4473fb1ef --db postgresql://postgres@localhost:54329/gaps +✘ [MIGRATION.REF_NOT_FOUND] Not a known contract reference: "e8a4473fb1ef" + why: No contract matching "e8a4473fb1ef" exists in the migration graph or refs index. +→ Provide a valid contract hash, ref name, or migration directory name. + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.REF_NOT_FOUND +[exit 2] + +``` + +## 6. E7: migration status + +Verdict: MATCH with amendment 2, and one DIFFERS note for `--json`. Log: `e7.log`. + +Sample output, exactly as printed, with one migration applied and one pending, before the `prod` ref existed: + +```text +$ npx prisma migration status +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f @db (db) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +``` + +The CLI does not indent the drawing. The spec's shape reference differs in two ways: the hint prints `prisma`, not `{bin}`, and the applied row ends with `✓ applied`. + +| Fact | Result | +| --- | --- | +| Hints print `prisma` or `{bin}` | Human output: `prisma`. `--json`: `{bin}` in `result.summary` and `result.diagnostics[].hints`; the envelope's `nextActions[].command` prints `prisma`. | +| `--space app` | exit 0; adds the header line `space: app`; same drawing | +| `--space nosuch` | exit 2, `MIGRATION.SPACE_NOT_FOUND`, "No directory named "nosuch" exists under the migrations root", "Pick one of: app" | +| `--from --to ` with an unreachable `--db` | exit 0, prints `1 pending`; header shows `from: 91e7f9f` and no `database:` line | +| `--from --to ` with no database configured | exit 0, same output | +| `--from ` alone with no database | exit 0 | +| `--to ` alone with no database configured | exit 2, `CONFIG.DB_CONNECTION_REQUIRED` | +| `--to ` alone with an unreachable `--db` | exit 2, `DRIVER.CONNECTION_FAILED` | +| No options, no database configured | exit 2, `CONFIG.DB_CONNECTION_REQUIRED` | + +```text +$ npx prisma migration ref set prod 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +✔ Set ref "prod" → 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e +[exit 0] + +{ + "hash": "91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e", + "invariants": [] +} +$ npx prisma migration status +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f @db (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --space app +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps +│ space: app + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f @db (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --space nosuch +✘ [MIGRATION.SPACE_NOT_FOUND] Unknown contract space: nosuch + why: No directory named "nosuch" exists under the migrations root. +→ Pick one of: app +→ See every space's migrations: prisma migration list + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.SPACE_NOT_FOUND +[exit 2] + +$ npx prisma migration status --legend +│ migrations: migrations +│ database: postgresql://****@localhost:54329/gaps + +Legend: + ○ contract ↑ forward ↓ rollback + ⟲ migration without schema change + ✓ applied ⧗ pending + ∅ empty database (baseline) + @contract @db reserved markers — also typeable as --from/--to tokens + (prod, staging) user-defined refs + aaaaaa → bbbbbb migration from contract aaaaaa to bbbbbb + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f @db (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --json +{"kind":"result","envelope":{"ok":true,"commandId":"migration.status","result":{"ok":true,"spaces":[{"space":"app","currentContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","targetContract":"a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d","migrations":[{"name":"20260929T1558_baseline","hash":"20baf4b21cbbaf9e51fcec754bfb9146733993cb4f2a05c0021a51bbb2156caf","fromContract":null,"toContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","operationCount":6,"createdAt":"2026-09-29T15:58:01.936Z","refs":["db","prod"],"providedInvariants":[],"status":"applied"},{"name":"20260929T1558_add_user_phone","hash":"e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd","fromContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","toContract":"a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d","operationCount":1,"createdAt":"2026-09-29T15:58:04.319Z","refs":[],"providedInvariants":[],"status":"pending"}]}],"summary":"1 pending — run `{bin} db migrate --to a4c3fa7fc3b2`","diagnostics":[]},"exitCode":0,"diagnostics":[],"nextActions":[]},"commandId":"migration.status","timestamp":"2026-09-29T15:58:26.947Z"} +[exit 0] + +$ npx prisma migration status --from 91e7f9f --to 20260929T1558_add_user_phone --db postgresql://postgres@localhost:1/nope +│ migrations: migrations +│ from: 91e7f9f + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --from 91e7f9f --to 20260929T1558_add_user_phone +│ migrations: migrations +│ from: 91e7f9f + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --to 20260929T1558_add_user_phone +✘ [CONFIG.DB_CONNECTION_REQUIRED] Database connection is required + why: migration status needs a database connection to read the marker and ledger (or pass --from for an offline path preview) +→ Run `prisma migration status --from `, or set `db: { connection: "postgres://…" }` in prisma.config.ts + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/CONFIG.DB_CONNECTION_REQUIRED +[exit 2] + +$ npx prisma migration status +✘ [CONFIG.DB_CONNECTION_REQUIRED] Database connection is required + why: migration status needs a database connection to read the marker and ledger (or pass --from for an offline path preview) +→ Run `prisma migration status --from `, or set `db: { connection: "postgres://…" }` in prisma.config.ts + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/CONFIG.DB_CONNECTION_REQUIRED +[exit 2] + +$ npx prisma migration status --from 91e7f9f +│ migrations: migrations +│ from: 91e7f9f + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ⧗ pending +○ 91e7f9f (db, prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops +○ ∅ + +⚠ 1 pending — run `prisma db migrate --to a4c3fa7fc3b2` +[exit 0] + +$ npx prisma migration status --to 20260929T1558_add_user_phone --db postgresql://postgres@localhost:1/nope +✘ [DRIVER.CONNECTION_FAILED] Database connection failed + why: +→ Verify the database URL, ensure the database is reachable, and confirm credentials/permissions + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/DRIVER.CONNECTION_FAILED +[exit 2] + +``` + +## 7. E10: marker outside the history + +Verdict: MATCH. Log: `e10.log`. Steps: database migrated to H2, then a `bio` field added to the contract, `contract emit` (new hash `3a5ec3f...`), `db update`, and no migration planned. + +| Case | `migration status` | `migration status --json` diagnostics | `db migrate` | `db migrate --show` | +| --- | --- | --- | --- | --- | +| 1. `contract.json` is the new state, same as the marker | exit 0, `Up to date`, no warning; draws `3a5ec3f @contract @db (db)` detached above the history | empty | exit 2, `MIGRATION.MARKER_MISMATCH` | exit 0, `Already up to date` | +| 2. `contract.json` back at H2, marker still `3a5ec3f` | exit 0, warns with `MIGRATION.MARKER_NOT_IN_HISTORY` | one entry, code `MIGRATION.MARKER_NOT_IN_HISTORY`, severity `warn` | exit 2, `MIGRATION.MARKER_MISMATCH` | exit 2, `MIGRATION.PATH_UNREACHABLE` | + +So `migration status` does not warn in every such case, and the next `db migrate` fails with `MIGRATION.MARKER_MISMATCH` in both. The spec's instruction to word the text so it holds either way still applies on rc.19. + +```text +--- case 1: contract.json is the new state (same as the marker) +$ npx prisma migration status +│ migrations: migrations +│ database: postgresql://****@localhost:54329/mydb + +○ 3a5ec3f @contract @db (db) + +○ a4c3fa7 +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ✓ applied +○ 91e7f9f (prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +✔ Up to date +[exit 0] + +$ npx prisma migration status --json +{"kind":"result","envelope":{"ok":true,"commandId":"migration.status","result":{"ok":true,"spaces":[{"space":"app","currentContract":"3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5","targetContract":"3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5","migrations":[{"name":"20260929T1558_baseline","hash":"20baf4b21cbbaf9e51fcec754bfb9146733993cb4f2a05c0021a51bbb2156caf","fromContract":null,"toContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","operationCount":6,"createdAt":"2026-09-29T15:58:01.936Z","refs":["prod"],"providedInvariants":[],"status":"applied"},{"name":"20260929T1558_add_user_phone","hash":"e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd","fromContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","toContract":"a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d","operationCount":1,"createdAt":"2026-09-29T15:58:04.319Z","refs":[],"providedInvariants":[],"status":"applied"}]}],"summary":"Up to date","diagnostics":[]},"exitCode":0,"diagnostics":[],"nextActions":[]},"commandId":"migration.status","timestamp":"2026-09-29T16:08:12.294Z"} +[exit 0] + +$ npx prisma db migrate +✘ [MIGRATION.MARKER_MISMATCH] Database marker is not reachable in the on-disk migration graph + why: DB marker is 3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5, but the on-disk migration graph reaches: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e, a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d, empty. +→ Catch the on-disk graph up to the live marker: prisma migration plan --from +→ Point the local db ref at the live marker: prisma migration ref set db 3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5 +→ Investigate whether the database was migrated by an out-of-band process + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.MARKER_MISMATCH +[exit 2] + +$ npx prisma db migrate --show +│ migrations: migrations +│ database: postgresql://****@localhost:54329/mydb + +○ 3a5ec3f @contract @db (db) + +○ a4c3fa7 +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 +○ 91e7f9f (prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f +○ ∅ + +ℹ Already up to date — nothing to run +[exit 0] + +--- case 2: contract.json back at a4c3fa7 (in the history), marker still outside +storageHash: a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d +[exit 0] +$ npx prisma migration status +│ migrations: migrations +│ database: postgresql://****@localhost:54329/mydb + +○ a4c3fa7 @contract +│↑ 20260929T1558_add_user_phone 91e7f9f → a4c3fa7 1 ops ✓ applied +○ 91e7f9f (prod) +│↑ 20260929T1558_baseline ∅ → 91e7f9f 6 ops ✓ applied +○ ∅ + +⚠ Database marker 3a5ec3f2e077 is not in the on-disk migration graph + +⚠ [MIGRATION.MARKER_NOT_IN_HISTORY] Database was updated outside the migration system (marker for space "app" does not match any migration) + why: The marker the database carries names no contract in the on-disk migration graph. +→ Overwrite the marker if the database already matches the contract: prisma db sign +→ Or push the current contract to the database: prisma db update + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.MARKER_NOT_IN_HISTORY +[exit 0] + +$ npx prisma migration status --json +{"kind":"result","envelope":{"ok":true,"commandId":"migration.status","result":{"ok":true,"spaces":[{"space":"app","currentContract":"3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5","targetContract":"a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d","migrations":[{"name":"20260929T1558_baseline","hash":"20baf4b21cbbaf9e51fcec754bfb9146733993cb4f2a05c0021a51bbb2156caf","fromContract":null,"toContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","operationCount":6,"createdAt":"2026-09-29T15:58:01.936Z","refs":["prod"],"providedInvariants":[],"status":"applied"},{"name":"20260929T1558_add_user_phone","hash":"e8a4473fb1ef2d26610f7ea0bcfc2823a716b347280796b0321f8289c74867bd","fromContract":"91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e","toContract":"a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d","operationCount":1,"createdAt":"2026-09-29T15:58:04.319Z","refs":[],"providedInvariants":[],"status":"applied"}]}],"summary":"Database marker 3a5ec3f2e077 is not in the on-disk migration graph","diagnostics":[{"code":"MIGRATION.MARKER_NOT_IN_HISTORY","severity":"warn","message":"Database was updated outside the migration system (marker for space \"app\" does not match any migration)","hints":["Run '{bin} db sign' to overwrite the marker if the database already matches the contract","Run '{bin} db update' to push the current contract to the database"]}]},"exitCode":0,"diagnostics":[{"code":"MIGRATION.MARKER_NOT_IN_HISTORY","severity":"warn","summary":"Database was updated outside the migration system (marker for space \"app\" does not match any migration)","why":"The marker the database carries names no contract in the on-disk migration graph.","meta":{"space":"app"},"nextActions":[{"kind":"run-command","label":"Overwrite the marker if the database already matches the contract","command":"prisma db sign"},{"kind":"run-command","label":"Or push the current contract to the database","command":"prisma db update"}],"docsUrl":"https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.MARKER_NOT_IN_HISTORY"}],"nextActions":[]},"commandId":"migration.status","timestamp":"2026-09-29T16:09:03.399Z"} +[exit 0] + +$ npx prisma db migrate +✘ [MIGRATION.MARKER_MISMATCH] Database marker is not reachable in the on-disk migration graph + why: DB marker is 3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5, but the on-disk migration graph reaches: 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e, a4c3fa7fc3b224675893305ff2fdd24588acbe11ab44cfd67d7d0e14e61d0a2d, empty. +→ Catch the on-disk graph up to the live marker: prisma migration plan --from +→ Point the local db ref at the live marker: prisma migration ref set db 3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5 +→ Investigate whether the database was migrated by an out-of-band process + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.MARKER_MISMATCH +[exit 2] + +$ npx prisma db migrate --show +✘ [MIGRATION.PATH_UNREACHABLE] No migration path from 3a5ec3f2e077f8 to a4c3fa7fc3b224 in space "app". + why: The migration graph has no path from the from-state to the target in space "app". +→ Plan the missing edge: prisma migration plan +→ Apply it: prisma db migrate + docs: https://docs.prisma.io/docs/orm/v8/reference/error-reference/MIGRATION.PATH_UNREACHABLE +[exit 2] + +✔ Connecting to database... +✘ Verifying database marker... +✘ Hash mismatch +✘ [CONTRACT.MARKER_MISMATCH] Hash mismatch + why: Contract storageHash does not match database marker +[exit 4] +{ + "hash": "3a5ec3f2e077f8d0e90354a7279440b35e97f41fa3d4edb8e6e1d64b89afaaf5", + "invariants": [] +} +``` + +## 8. E9: init and orm init + +Verdict: MATCH. Log: `e9.log`. Both ran in the empty directory `e9/`; neither wrote a file. I did not run `init` itself. + +- `npx prisma@latest init --help`: "Prepare this repository for Prisma: config file, dev dependency, AI-agent skills". It adds a `postinstall` script that keeps the agent skills in sync, adds `prisma` to `devDependencies` when no dependency field declares it, scaffolds a `prisma.config.ts` that records which agents get skills, and syncs the skills once. It "runs locally and calls no platform API". It does not set up Prisma ORM. +- `npx prisma@latest orm init --help`: "Initialize a new Prisma ORM project". It "scaffolds config, schema, and runtime files, installs dependencies, and emits the contract". +- `apps/docs/content/docs/cli/init.mdx` says the same about `init`, except that it does not mention the `prisma` dev dependency. +- The `orm init` result on rc.19 itself points at `init`: "Working with a coding agent? Run `prisma init` in this project to set up the Prisma agent skills." + +```text +$ npx prisma@latest --version +8.0.0-rc.19 +[exit 0] +$ npx prisma@latest init --help +prisma init → Prepare this repository for Prisma: config file, dev dependency, AI-agent skills + +│ Usage +│ $ prisma init [options] +│ +│ Runs locally and calls no platform API. Adds a postinstall script to +│ package.json that keeps the Prisma agent skills in sync on every install, +│ adds prisma to devDependencies at this CLI's exact version when no +│ dependency field declares it, scaffolds a prisma.config.ts recording which +│ agents to install skills for, then syncs the skills once now. Everything +│ lands in the current directory; a prisma.config.ts or postinstall script +│ that already exists is never edited. Rerunning is safe: each step reports +│ what is already done. In a directory another prisma.config.ts already +│ governs, init writes only the prisma.config.ts scaffold — the postinstall +│ hook, the prisma dev dependency, and the skills sync belong at the +│ repository root and are skipped unless --postinstall or --skills asks for +│ them here. +│ +│ Options +│ --postinstall/--no-postinstall Add the skills-sync postinstall hook (--no-postinstall skips) +│ --skills Agents to install skills for (comma-separated: claude, cursor, agents, devin); 'none' records that no agent skills are wanted +│ +│ Global options also apply: --format, --json, --log-level, --verbose, +│ --quiet, --yes, --confirm, --interactive, --color, --config. Run 'prisma +│ --help' for details. +│ +│ Examples +│ $ prisma init +│ $ prisma init --skills=claude,cursor +│ $ prisma init --skills=none +│ $ prisma init --no-postinstall + +[exit 0] +$ npx prisma@latest orm init --help +prisma orm init → Initialize a new Prisma ORM project + +│ Usage +│ $ prisma orm init [options] +│ +│ Scaffolds config, schema, and runtime files, installs dependencies, +│ and emits the contract. Gets you from zero to typed queries in one step. +│ +│ Run it interactively for a guided setup, or supply --target and --authoring +│ for a fully scriptable run (CI, AI coding agents, automation). +│ +│ In a Prisma 7 project, pass --from-prisma7-schema (or answer yes when asked) +│ to use the existing schema.prisma as the contract source. +│ +│ Options +│ --target Database target: postgres or mongodb +│ --authoring