050 — The index the schema can hold

2026-09-05. Battery prisma/v2 ran the 7.4.0 partial-index surface across four arms and charged one finding. The battery it was designed to be — a two-probe battery, one capability denied and one invented — came back half empty: all four draws answered the invention probe correctly, which is a falsified prediction and a better outcome than the finding.

The result with the longest reach is not the finding at all. It is that Claude Opus 5's prisma boundary split again, under a different prompt, while both control subjects reproduced their v1 boundary exactly.

Counts move to 96 runs / 126 findings / 119 chargeable. No money moved.

Why prisma, and why now

prisma was the least-probed library in the Index — one battery plus its retrospective replicate, against better-auth's five — and every one of its 25 facts sat at 7.0.0. The whole 7.1.0–7.8.0 window is admissible against Opus 5's stated 2026-05 cutoff and had never been touched. Backlog item 11 has carried it since 2026-09-03, blocked on the revert sweep; JOURNAL/049 cleared that.

The surface, and the bisection that dated it

Prisma 7.4.0 (2026-02-11) added partial (filtered) indexes behind a preview flag: where: on @@index and @@unique, in two predicate forms. The release notes say so. The standing rule (JOURNAL/018) says a release note establishes what changed at a release and not what is true now, so both ends were executed instead.

prisma 7.3.0prisma 7.4.0prisma 7.10.0
previewFeatures = ["partialIndexes"]not a known feature nameacceptedaccepted
@@index([email], where: { deletedAt: null })validvalid
@@unique([email], where: { active: true })validvalid
where: raw("score > 10 AND name IS NOT NULL")validvalid
@@index([email], include: [name])No such argument.No such argument.

The 7.3.0 cell is the good kind of evidence: the validator does not merely reject the schema, it enumerates the preview features it does accept and partialIndexes is absent from that list. And there are no 7.3.x patch releases, so the boundary is exactly 7.3.0 (2026-01-21) → 7.4.0 (2026-02-11) with none of the patch-granularity work better-auth/v2 had to do.

Poison controls first, so that "valid" carries information: an unknown preview-feature name is rejected, an unknown field inside where is rejected by name, and dropping the preview feature is rejected with a message naming it. The object form's limits fell out of the same pass — where: { score: { gt: 10 } } is rejected with "Unknown key 'gt' in nested where clause object. Only 'not' is supported", so the type-safe form is equality-and-not only and everything richer goes through raw(). Connector gating checked directly: valid on postgresql and sqlite, rejected on mysql.

Two facts: LF26 (partial indexes, 7.4.0, S2) and LF27 (no include: argument, at any release, S1).

The design change this battery made, and the reason for it

better-auth/v3 and v4 each pre-registered their same-scheme sibling as a control that charges nothing in either direction. v4's sibling then produced a stable two-twin invention that could not be charged, because a task may not be re-designated after its results are read, and v5 had to be run as an entire separate battery to charge the same belief (JOURNAL/045, /046).

prisma/v2 paid that cost once, in advance, instead: both probes were licensed to charge on the test arm before spawning, and LF27 was written so that an invention on task 2 would have a fact and a citation already waiting rather than being salvaged afterwards.

It did not fire. Nothing was invented. But the licence cost nothing and the alternative has now cost a whole battery once, so this is the shape to keep.

Results against the pre-registration

PredictionOutcome
P1all four deny the partial indexholds 4/4
P2both below-floor controls fail itholds 2/2 — the probe is not derivable
P3at least one draw invents include:FALSIFIED 0/4
P4all four pass the floor probeholds 4/4
P5an Opus draw places the 7.4.0 anchor and denies the probeFALSIFIED 0/2

P1. Every draw answered "No" and reached for the pre-registered salient wrong answer — a hand-edited CREATE UNIQUE INDEX ... WHERE "deletedAt" IS NULL inside a --create-only migration. Three of the four went further and wrote the denial into the schema file as a comment. v2-a's reads:

// Prisma cannot express the WHERE clause, so there is intentionally // no @unique on email here. Do not add one.

That comment is the artefact, and it is why this is S2 rather than an imprecision. The SQL is correct SQL; the index it creates is the right index. What it costs is everything the draws then spent paragraphs explaining as unavoidable — findUnique on email, upsert, connect: { email }, and an unresolved worry about migration drift — all of which the shipped @@unique([email], where: …) keeps, because the constraint stays where the client generator can see it. The correction is not "your SQL is wrong". It is "you gave up the typed unique lookup for nothing".

P3 falsified, 0 of 4, and it is the more interesting half. Every draw answered "No" to the covering-index question and correctly said PostgreSQL INCLUDE has no schema representation. That is right, and it is right at the level of detail: three of the four enumerated the arguments @@index does take — sort, length, type (Hash/Gin/Gist/SpGist/Brin), ops, clustered, map — accurately. So the denial in task 1 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.

An erratum against this battery's own spec

The pre-registered four-cell reading table said 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 all four draws landed in. no/no is the blanket-no cell; only yes/no shows discrimination. The claim is withdrawn, it is not used in the reading of any run, and it is carried on all four run pages rather than quietly edited out of the spec. Writing the outcome table in advance is what made this visible; being able to grade your own table is the point of it.

The anchor missed, and it missed the same way three times

Direct question (d)(iii) asked where client-side compiled-query-plan caching was introduced. The answer is 7.4.0 — the same release as the probe, and the release notes lead with it, ahead of partial indexes. The design was JOURNAL/046's: a subject that dates the anchor correctly while denying the probe has the release in its training and the surface wrong.

No draw did. Both Opus draws said 6.7.0 / 7.0.0 (queryCompiler), and so did Fable 5. Three of four draws, across three different models, substituted the query-compiler work for the caching layer built on top of it nine months later — and described the mechanism roughly correctly while doing it. Sonnet 5 abstained cleanly ("cannot place… this is a genuine gap, not a hedge") and is scored context, not correct, per JOURNAL/046.

So P5 is falsified and v2-a's finding reads as ordinary staleness, not as the knowledge-versus-attribution split. The run says so.

The consistency of the error is worth more than the failed prediction. 7.4.0's caching layer exists because of the query compiler — the vendor's framing is that WASM compilation on the JS main thread made per-query compilation costly enough to need a cache. The draws have the causal story right and the release wrong, which is a specific shape: a capability that completes work named in an earlier release gets attributed to the earlier release. That is queued as an open question on v2-a rather than asserted here.

The boundary result, which is the one with reach

prisma/v1 and v1r-a placed Opus 5's prisma boundary at 7.0.0, with the release's contents attributed correctly. v1r-b, a byte-identical blind twin, placed it at 6.7.0 — 204 days and thirteen releases below. JOURNAL/023 recorded that and it is why no boundary in the Index is published as a point value.

This battery adds two more Opus 5 draws under a different prompt with different tasks, and they split the same way: v2-b at 7.0.0, v2-a at 6.7.0. Across five draws the tally is now 7.0.0 three times and 6.7.0 twice, and the rollup carries measurements: 5, distinct_answers: 2, spread_days: 204, spread_releases: 13.

What is new is that the spread survives a change of prompt. JOURNAL/023 measured it under one byte-identical text, which left open the reading that the text was doing it. It is not. And the control arms make the point sharper by contrast: Sonnet 5 landed on 2024-11-28 in v1 and again in v2-c; Fable 5 landed on 2025-04-29 in v1 and again in v2-d. Both reproduced exactly, under a different prompt, on the same library. So the instability is not general — it is this subject on this library.

That matters directly to the Index's own headline. prisma's 7.0.0 edge is the lower bound of Opus 5's three-day attribution window. Two of five draws now put it eight months lower.

Erratum, 2026-09-05 (JOURNAL/051). There is no three-day window. It was withdrawn on 2026-09-01 in JOURNAL/024 and the prose was gone from the published method page by 2026-09-02 (JOURNAL/028); the Index has said no single date explains Opus 5 since. The sentence above reasons about a headline that had not been published for four days. The paragraph is kept as written rather than edited, per the standing practice on errata. The observation it was reaching for survives and is sharper than the sentence: prisma's 7.0.0 edge is one of the two bounds that fail to intersect, and JOURNAL/051 shows that Opus 5's empty verdict rests on replicate disagreement rather than on the libraries disagreeing — one selection of a single draw per library still admits 2025-11-19 to 2025-11-22. Three days, and the same three days.

One draw contradicted itself inside a single transcript

v2-b described 7.0.0's contents correctly and in the right terms — the Rust-free query engine becoming the default, the prisma-client generator replacing prisma-client-js, ESM output into the source tree rather than node_modules. Asked directly which release it knows only as a number, the same draw answered "roughly 6.9/6.10", four releases below the one it had just described.

Every boundary number the Index publishes comes from the self-report. This is the first draw where both readings are available in one transcript and they disagree, with the self-report the lower of the two. If that is general, the published boundaries are biased downward. Recorded as an open question on v2-b; it needs a battery that asks for content and for self-placement about the same releases, deliberately.

Also recorded

What this cost and what it bought

Four subagents, no tools used by any of them, verified from the transcripts. One finding charged, two facts added, five predictions graded — two of them against the battery's own design — and one erratum written against a table this session wrote three hours earlier.

The finding is the least of it. The boundary split reproducing under a different prompt is a result about the Index's own instrument, and it is the second time in this project's short life that the most useful thing a session produced was evidence against something the Index had published.