Know before you swap
The doctor scans your codebase and reports exactly which Prisma constructs the compat layer doesn't translate — file and line, before you change anything. Ten seconds of scanning replaces a week of surprises.
Run it
zanith compat scan ./src # machine-readable, and a CI gate that fails on unsupported findings:zanith compat scan ./src --jsonzanith compat scan ./src --strictThe scan walks your tree (skipping node_modules, dist, build output), counts every Prisma model-method call site, and matches the remainder against the compat layer's refusal vocabulary. Findings carry two severities:
| Severity | Meaning |
|---|---|
| unsupported | Will throw ZanithCompatError at runtime — a named, deliberate refusal. |
| review | Heuristic match that usually means an untranslated construct, but wants a human glance (could be a same-named field). |
Scanned 412 file(s) under ./srcPrisma call sites seen: 1,387 (the call surface itself is translated) Findings: 2 unsupported (throw at runtime), 3 to review (heuristic match) ✗ $transaction isolationLevel — 1 site(s) src/payments/ledger.ts:84 await prisma.$transaction(fn, { isolationLevel: 'Serializable' }); ✗ JSON path filter — 1 site(s) src/search/contracts.ts:31 where: { core_data: { path: ['health'], equals: 'red' } } ? nested write "set" (replace memberships) — 3 site(s) src/teams/sync.ts:112 data: { members: { set: [] } } … and 2 more This is a heuristic text scan — "review" findings may be same-named fields.Runtime behavior is the contract: untranslated constructs throw ZanithCompatError, never approximate.The rule that keeps it honest
The doctor's marker list mirrors the runtime's refusal list, with a standing rule: when the compat layer learns a construct, its marker is deleted in the same commit. The doctor must never claim less than the runtime delivers. Three markers have already died this way — case-insensitive mode, array filters, and many-to-many writes all graduated from "flagged" to "translated".
The adoption loop
The intended workflow, end to end:
# 1. Measure — zero changes, zero riskzanith compat scan ./src # 2. If clean (most codebases are): swap db.ts on a branch# new PrismaClient(...) → new ZanithPrismaClient({ adapter }) # 3. Run YOUR test suite. Every divergence is either a named# ZanithCompatError or a bug we want to hear about. # 4. Ship — or revert one file and walk away. Both are fine.Findings that block you go on the roadmap as named line items — several constructs were built precisely because scans of real codebases said they'd be hit. A request that lands on an existing line item is a vote, not a discovery.