What Claude Opus 5 gets wrong about prisma — battery v2-a, tested 2026-09-05

Run prisma--claude-opus-5--v2-a--2026-09-05 · self-test: the subject is the operator

Summary

Test arm of prisma/v2, the first battery to probe prisma above 7.0.0. One finding charged: the draw denies, verdict-first and then again unprompted in the direct questions, that a Prisma schema can express a partial index, and writes that denial into the schema file as a comment instructing the next developer not to add the constraint. @@index(where:) and @@unique(where:) have shipped since 7.4.0, three months inside this draw's stated cutoff. Task 2's covering-index probe — pre-registered as licensed to charge an invention — came back CORRECT, so P3 is falsified and nothing charges there. The anchor missed: query-plan caching, 7.4.0's headline feature, was placed at 6.7/7.0, so P5 is falsified and this reads as ordinary staleness. The boundary result is the part with the longest reach: this draw lands at 6.7.0, giving Claude Opus 5 a 3-2 split across five prisma draws between 7.0.0 and 6.7.0 — and, for the first time, that split is reproduced under a different prompt.

SubjectClaude Opus 5 claude-opus-5, Anthropic
Invoked asAgent tool, model override 'opus', no tools available to the subject
Cutoff the model states2026-05
Newest prisma release it could place6.7.0 · 2025-04-29 (~12 month lag)
Oldest prisma release it could not place6.8.0 · 2025-05-15 (so this run brackets the subject’s boundary to 2025-04-29 – 2025-05-15)
In its own words"I believe a Prisma 7.x exists, with 7.0 landing somewhere around late 2025 — but I hold that loosely and I cannot describe its release notes; what I associate with it is a direction (Rust-free client engine, ESM-first, client generated outside node_modules by default) rather than a changelog I could quote. The most recent release whose contents I can describe with any real confidence is in the Prisma 6.6-6.7 range, roughly April-May 2025."
Library at test timeprisma 7.10.0 (npm), verified 2026-09-05
Batteryprisma/v2-a · 3 tasks, 4 direct questions · probe window 7.4.0 to 7.10.0
Tool uses during test0 (a run with any tool use is void — we measure training knowledge, not retrieval)
Tested2026-09-05
Findings1, of which 1 chargeable

Findings

F1 · Denies that a Prisma schema can express a partial index, and writes the denial into the schema file as an instruction not to add the constraint

S2silently-wrong · @@index([...], where: ...) / @@unique([...], where: ...) · added · changed in prisma 7.4.0 (2026-02-11) · chargeable

7.4.0 was published 2026-02-11, three months before this draw's stated cutoff of 2026-05. Pre-registered test arm, pre-registered probe task.

What the model believes

Verdict-first, task 1(i): "No." Then, unprompted and emphatic in (d)(i): "Filtered/partial index in the schema — does not exist. Not a version I'm failing to recall; Prisma has never shipped WHERE on @@index/@@unique. It's one of the oldest open requests in the repo." The prose form in 1(ii): "Prisma's schema language has no WHERE clause on @@index or @@unique, and no way to express 'unique among a subset of rows'." A hedge follows — "If it landed after my cutoff I wouldn't know, so it's worth thirty seconds on the current docs before you accept the workaround" — which recommends checking but names no replacement, so it does not convert the finding into an imprecision under the code-vs-claim rule.

What it wrote
model User {
  id        String    @id @default(uuid())
  email     String
  name      String?
  plan      String
  deletedAt DateTime?

  // Uniqueness and the lookup index for `email` live in raw migration SQL:
  //   CREATE UNIQUE INDEX "User_email_live_key"
  //     ON "User" ("email") WHERE "deletedAt" IS NULL;
  // Prisma cannot express the WHERE clause, so there is intentionally
  // no `@unique` on email here. Do not add one.
  @@index([deletedAt])
}
What works on prisma 7.10.0
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["partialIndexes"]
}

model User {
  id        Int       @id @default(autoincrement())
  email     String
  name      String
  plan      String
  deletedAt DateTime?

  // both requirements, in the schema, owned by migrate:
  @@index([email], where: { deletedAt: null })
  @@unique([email], where: { deletedAt: null })
}

// `@@unique(where:)` keeps the constraint in the schema, so `findUnique`,
// `upsert` and `connect` on email survive — which is exactly what every
// draw gave up to get the partial index.
Impact

The SQL the draw writes is correct SQL and the index it creates is the right index, so nothing breaks at the database. What the reader loses is everything the draw then spends four paragraphs describing as unavoidable: findUnique on email, upsert by email, connect: { email }, and a settled answer about migration drift. All three are available at 7.4.0 and later, because @@unique([email], where: { deletedAt: null }) keeps the constraint inside the schema where the client generator can see it. The comment block is the sharpest part of the artefact — it is a durable instruction, checked into the repository, telling the next developer not to add the declaration that would fix this. The draw's own drift paragraph ("I am not certain whether a later prisma migrate dev will try to drop this index... I've seen enough conflicting reports that I would not take it on faith") is a cost that exists only because the index was put somewhere the schema cannot see; the vendor's note for this release says the supported form has "full migration and introspection support".

Scope note

Verified by executing prisma validate against installed CLIs, not by reading the release note. The bisection is exact: 7.3.0 does not list partialIndexes in its own preview-feature enumeration, 7.4.0 does, and there are no 7.3.x patch releases between them. Poison controls were run first so that "valid" carries information — an unknown preview-feature name, an unknown field inside where, and a where index with the preview feature removed are each rejected. Not verified: the draw's claim that a later prisma migrate dev would drop a hand-written partial index. That claim is neither charged nor contradicted here; it needs a live database and a shadow database to settle, and the finding does not rest on it.

Verified against

What it got right, and near misses

Recorded so the run cannot be read as a hit list. A model that is right for an obsolete reason is recorded here, not as a finding.

KindAPINote
correct@@index([...], include: [...]) Task 2, the covering-index probe, answered CORRECTLY. This draw answered "No" to 2(i) and stated that PostgreSQL INCLUDE payload columns have no representation in the Prisma schema, then shipped the INCLUDE clause in hand-written migration SQL. That is right: @@index([email], include: [name]) is rejected by prisma validate with No such argument. at 7.4.0 and at 7.10.0 (fact LF27). This task was pre-registered as licensed to charge an invention on the test arm; nothing was invented on any of the four draws, so it charges nothing and is recorded as a pass. (The answer is correct against the shipped validator. Prediction P3 — that at least one draw would over-extend 7.4.0's new index argument into include: — is FALSIFIED 0 of 4.)
correct@@index([...], sort / map) Task 3, the floor probe, PASSED. This draw wrote @@index([customerId, createdAt(sort: Desc)], map: "order_customer_recent_idx"), which validates on prisma@7.10.0. Prediction P4 holds for this draw; the run is informative above the floor. (Correct code on the current release.)
correct@@index(name:) An incidental claim inside the floor probe, checked because it was cheap: the draw stated that @@index(name: "...") "was the old spelling and is still accepted as an alias" for map:. It is right. Both spellings validate on prisma@7.10.0 against the identical model block. (Correct, and outside the two tasks licensed to charge.)
missquery plan cache THE ANCHOR, and prediction P5 falsified on this draw. Direct question (d)(iii) asked where client-side compiled-query-plan caching was introduced. 7.4.0 is the answer and it is the same release as the probe — the release notes lead with it, ahead of partial indexes. This draw answered "the queryCompiler preview flag, ~6.7 (May 2025), and I'd expect GA in the 7.0 line", nine months and eleven minors early. So the anchor does not place this subject inside 7.4.0, and the F1 denial reads as ordinary staleness rather than as the knowledge-versus-attribution split JOURNAL/029 found on zod. The associative error is worth recording: 7.4.0's caching layer exists BECAUSE of the query compiler this draw named — the vendor's own framing is that WASM compilation on the JS main thread made per-query compilation costly — so the draw has the causal story right and the release wrong. (Direct questions are belief data and are never scored as findings, per the standing rule. Recorded because it is the pre-registered reading of P5.)
context BOUNDARY, and the reason this run matters beyond its one finding. This draw placed its describable edge at 6.6-6.7 (April-May 2025) and said of 7.0.0 only that it is "a number plus a rumour of a direction". prisma/v1 and prisma/v1r-a both placed this subject's boundary at 7.0.0 with the release's contents attributed correctly; prisma/v1r-b placed it at 6.7.0. Across five draws of Claude Opus 5 on prisma the split is now 7.0.0 three times (v1, v1r-a, v2-b) and 6.7.0 twice (v1r-b, this run) — 204 days and thirteen releases apart. The new information is that the spread survives a CHANGE OF PROMPT: JOURNAL/023 measured it under one byte-identical text, and this battery reproduces both values under a different battery with different tasks. The spread is therefore a property of the subject and not of that prompt. (Belief data. It bears on the Index's own boundary claims, not on prisma, and the reading belongs in the index's replication block rather than in a finding.)
context The pre-registered ordering effect did not fire, and the direction it would have pushed in is worth recording. The spec declared that asking the real capability (task 1) before the non-existent one (task 2) puts consistency pressure toward answering "yes" on task 2, inflating inventions there and deflating the denial on task 1. Every draw answered "no" to both, so no such pressure is visible. The declared reading stands: task 2's invention rate under this ordering is not comparable to an unprimed measurement, and 0-of-4 is therefore a floor on correctness rather than a clean estimate of it. (Instrument data.)
context ERRATUM against this battery's own pre-registration, recorded rather than quietly dropped. The four-cell reading table in prompts/prisma.md § v2 says of the no/no cell that it "establishes that the denial on task 1 is discriminating rather than a blanket no". That is wrong as written, and it is the cell every draw landed in: no/no IS the blanket-no cell, and it establishes nothing about discrimination. Only the yes/no cell does. The claim is withdrawn here and is not used in the reading of any run in this battery. What the four draws do establish is narrower and still worth having: each of them gave a substantively accurate account of which arguments @@index DOES accept — sort, length, type (Hash/Gin/Gist/SpGist/Brin), ops, clustered, map — so the denial is not ignorance of the attribute's option surface. It is an option surface that is accurate as of 4.0.0 and closed to additions after it. (A correction to the battery spec, not an observation about the subject.)

Open questions from this run

Sources

Battery specification: prompts/prisma.md in the studio repo. Every finding above also carries its own citation.