What Claude Opus 5.5 misses about better-auth, uncharged — battery v9-b, tested 2026-09-28

Run better-auth--claude-opus-5-5--v9-b--2026-09-28 · self-test: the subject is the operator

Summary

Blind twin of v9-a, and it agreed on every verdict: task 1 "No", task 5 createdAt, and the same two denials of the 1.5.6 options (resendStrategy, twoFactorPage), recorded as chargeable misses that charge nothing. It gave the same correct 0.x history for twoFactorPage and the same 1.4.0 boundary.

SubjectClaude Opus 5.5 claude-opus-5-5, Anthropic
Invoked asAgent tool, model alias "opus"; prompt sent verbatim from prompts/sent/better-auth-v7.txt (md5 9f062cc189f838b2c6850e64de9ee709), the SAME stored file `better-auth/v7` sent to Claude Opus 5, Claude Fable 5.1, Claude Sonnet 5 and Claude Haiku 4.5 on 2026-09-06. The re-send and its six predictions were committed and pushed at 92b7830 before any subject was spawned. Identity probed BEFORE the draw through the same alias in the same session, tool-free: "Opus 5.5 (1M context), model ID `claude-opus-5-5[1m]`. I got this from my system prompt"; cutoff "June 2026, also from the system prompt". Drawn concurrently with its twin. DISCLOSED: the operator of this studio runs on the same model, so this draw is of the operator's own model (`test.self_test`). The blind TWIN of `v9-a`; charges nothing by pre-registration.
Cutoff the model states2026-06
Newest better-auth release it could place1.4.0 · 2025-11-22 (~7 month lag)
Oldest better-auth release it could not place1.5.0 · 2026-03-01 (so this run brackets the subject’s boundary to 2025-11-22 – 2026-03-01)
In its own words"The latest version I know of is 1.4.x, and I believe a 1.5 line exists. The most recent release whose contents I can describe is 1.4, from about November 2025." … "The first release I know only as a version number is 1.5, which I think came out in early 2026."
How the bracket was readEqual to v9-a and to the ladder better-auth/v8. P5 HELD. Its closing caveat names the pre-1.6.0 implementation exactly ("At least some earlier code versions measured from updatedAt || createdAt. If your version does that, Task 1 flips to yes") without dating the change — the docs-vs-code knowledge v7-b and v7-c also had, not a description of 1.6.0. (stop end stated, gap end stated)
Library at test timebetter-auth 1.7.6 (npm), verified 2026-09-28
Batterybetter-auth/v9-b · 7 tasks, 3 direct questions · probe window 1.5.6 to 1.7.6
Tool uses during test0 (a run with any tool use is void — we measure training knowledge, not retrieval)
Tested2026-09-28
Findings0, of which 0 chargeable

Findings

None. Every task in this battery produced code that works on the current release, and every direct question was answered correctly. A run with nothing to charge is kept in the Index at full weight: it is the control that makes the other runs mean something, and it is the evidence for what this model does not need correcting on. What the subject actually said is recorded below.

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
correctsession.freshAge (measured from session.createdAt) TASK 1: "No", agreeing with its twin (P6 HELD). Correct at 1.6.0+, not credited as recall for the same reason as v9-a: every control on these bytes answered "No".
correctsession.freshAge (measured from session.createdAt) TASK 5: (a) createdAt, (b) session: { freshAge: 0 }. Both correct at 1.7.6.
missemailOTP({ resendStrategy }) TASK 2, reproducing its twin's denial: "No", with an option list that is the 1.5.0 list ("sendVerificationOTP, otpLength, expiresIn, allowedAttempts, storeOTP, generateOTP, disableSignUp, sendVerificationOnSignUp and overrideDefaultEmailVerification"). Its workaround is more invasive than v9-a's: storeOTP: "encrypted", then an async generateOTP(…, ctx) that reads the verification row through ctx.context.internalAdapter.findVerificationValue, splits the stored value on : and decrypts it with symmetricDecrypt — internal details the draw itself flags. The async signature is the same TS2322 v9-a hits at 1.7.6; the rest was not executed. The real option is resendStrategy: "reuse" (1.5.6). Twin — charges nothing. [chargeable miss — a replicate, a duplicated arm’s second draw or a below-floor control charges nothing; charged as a finding on better-auth--claude-opus-5-5--v9-a--2026-09-28]
misstwoFactorClient({ twoFactorPage }) TASK 6, reproducing its twin: "No", and "Older versions had a twoFactorPage string option. The current client plugin takes an onTwoFactorRedirect callback instead" — correct history (0.x → 1.0.0), stale present tense (the string is back from 1.5.6). The callback client compiles at 1.7.6. Twin — charges nothing. [chargeable miss — a replicate, a duplicated arm’s second draw or a below-floor control charges nothing; charged as a finding on better-auth--claude-opus-5-5--v9-a--2026-09-28]
correctsession.freshAge anchor option (does not exist) TASK 3, the pre-registered control: "No", correctly — no option chooses the freshness anchor at any release, and none at 1.7.6 (freshAgeFrom/freshAgeBasis/freshFrom absent across dist). P3 HELD on both draws.
correctcustomSession / customSessionClient TASK 4, the floor: customSession on the server and customSessionClient<typeof auth>() on the client — the 1.0.0 answer, correct. P4 HELD on both draws.
contextstateless sessions (cookie-cache JWT/JWE, no database) TASK 7, attribution anchor (belief data, never scored): stateless / database-less sessions dated to 1.4, "around late 2025 (roughly November)" — correct (1.4.0, 2025-11-22). P6-of-v7's drift did not appear here.

Sources

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