Skip to content

refactor(evals): split deleted-user-access into two scenarios - #134

Open
barryroodt wants to merge 9 commits into
mainfrom
barryroodt/ai-923-split-deleted-user-access-eval-into-two-scenarios
Open

refactor(evals): split deleted-user-access into two scenarios#134
barryroodt wants to merge 9 commits into
mainfrom
barryroodt/ai-923-split-deleted-user-access-eval-into-two-scenarios

Conversation

@barryroodt

@barryroodt barryroodt commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Splits investigate-auth-001-deleted-user-access in two, per AI-923.

The scenario asked two unrelated things in one prompt: the deleted-user incident, then a "one more thing while you're at it" rundown on legacy vs new API keys. Both landed in a single judge verdict, so an agent that fixed the delete flow but fumbled the key explanation failed the whole auth scenario with no way to see which half broke. The sdk topic tag existed only for that second half, and AI-422 had no result to point at.

What changed

  • investigate-auth-001-deleted-user-access keeps the incident, minus the key paragraph. sdk and AI-422 move out. Same eval id, same seed data, same six deterministic checks.
  • investigate-auth-002-api-key-migration is new: the key question on its own. No remote/, there is nothing in project state to inspect for a knowledge question.
  • Both judge checks are now one judge call per claim, so each claim gets its own named check instead of being fused into a single boolean. The parent goes 7 checks to 9, the new eval has 3.

Heads up on the parent's numbers

The eval id and its history rows stay in place, but the rubric change moves the scoring boundary, so results before and after this PR are not directly comparable under that id. If investigate-auth-001-* moves, that is the new bar, not an agent regression.

Tradeoff worth flagging on the per-claim split

Each judge() is its own generateText call (packages/core/src/index.ts#L571-L584), so three judges per check group means roughly 3x the judge spend and 3x the rate-limit pressure for those two evals. They run in Promise.all so wall-clock is about the same. I think the diagnostics are worth it here (the whole point of the split is knowing which claim an agent missed, and the parent's fused check was hiding three separate failure modes behind one red cell), but it is a real cost and worth a second opinion, especially with the GH Actions budget in mind. Happy to fold the key-model checks back into one verdict if we'd rather not pay it.

Calls worth a second opinion

  • suite: regression on the new eval rather than benchmark. CONTRIBUTING wants an agent failing before something joins the published score, and claude-code-sonnet-5 passed 3/3. Happy to promote it if a matrix run turns up failures.
  • Dropped sdk from the parent, since what is left is auth-session work. It does still touch an RPC call from the app, so there is an argument for keeping it.

Verification

  • tsc --noEmit, biome check, and prettier all clean.
  • pnpm eval:dry plans both, new one as stage=investigate suite=regression mode=tools.
  • Live runs against claude-code-sonnet-5: parent PASS 9/9 in 304s, new eval PASS 3/3 in 72s, with each claim reported as its own check.

Note the judge rubric describes the keys as role equivalents (anon to publishable, service_role to secret) and is careful that the publishable key identifies the app, not a user: no user token means the anon role, a user token means authenticated, RLS applies either way. The parent's old wording implied the publishable key itself carried the user's JWT, which the deleted line took with it.

Needs the run-evals-changed label before review: the parent needs a rescore under the split rubric and the new eval has no results yet.

The scenario bundled an unrelated API-key rundown into the same prompt and
the same judge verdict, so a fumbled key explanation failed the whole auth
scenario with no way to attribute it. Moves to its own eval (AI-923).
Splits the publishable/secret key rundown out of
investigate-auth-001-deleted-user-access into a regression scenario, giving
AI-422 a result to point at. Judge-only: nothing to inspect in project state
for a knowledge question.
@linear-code

linear-code Bot commented Jul 28, 2026

Copy link
Copy Markdown
AI-923 Split deleted-user-access eval into two scenarios

The investigate-auth-001-deleted-user-access eval scenario currently combines two topics and should be split into separate scenarios.

Keep the existing scenario focused on investigating why a deleted user account can still access the app, fixing the flow so a deleted account loses access, and clarifying whether any access window remains after the fix.

Move the API key portion into a new scenario focused on explaining the difference between legacy anon / service_role keys and the new publishable / secret keys, including which belongs in the frontend and what each means for RLS. This is motivated by AI-422.

Relevant source: prompt.md.

Review in Linear

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evals Ready Ready Preview, Comment Jul 29, 2026 10:48am

Request Review

One judge verdict spanning several independent claims can't be attributed:
an agent that gets two of three right scores identically to one that gets
none. Splits both scorers into parallel judges with one named check each,
matching investigate-functions-001. Costs one judge call per claim.

Also drops interface: mcp from the api-key scenario, which needs no tools.
@barryroodt barryroodt added the run-evals-changed Add to a PR to refresh only the benchmark evals that have had changes label Jul 28, 2026
@barryroodt
barryroodt marked this pull request as ready for review July 28, 2026 09:13
@barryroodt
barryroodt requested a review from a team July 28, 2026 09:13
@barryroodt barryroodt self-assigned this Jul 28, 2026
barryroodt and others added 3 commits July 29, 2026 12:26
The CI refresh failed both experiments on "placed the publishable key in the
frontend with RLS still applying", and reading the judge notes, both answers
were right: publishable key in the frontend, RLS still applies, secret key
kept server-side. They failed for not spelling out that requests run as anon
without a user token and authenticated with one.

The prompt never asks for that. It asks which key belongs in the frontend and
what each means for RLS, and CONTRIBUTING says prompts should not reflect deep
familiarity with Supabase. Expanding the prompt to ask about Postgres roles
would have made the scenario evaluator-shaped rather than user-realistic, so
the rubric gives way instead: role detail is a bonus, not a requirement.

Also stops failing the mapping check on "drop-in" phrasing. The mapping itself
is what the migration question is about.

Fail conditions are unchanged: bypassing RLS with the publishable key, treating
it as user identity, shipping a secret key to the client, inverting the mapping.

Both previously failing experiments now pass 3/3 locally.
Previous commit went too far and blessed "drop-in" phrasing on the mapping
check. The new keys are not interchangeable with the legacy ones: they are not
JWTs and behave differently in places such as Edge Functions, so an answer
calling them a straight swap is materially wrong and the CI failure on that was
a fair catch.

Mapping now fails on inverted mapping or claimed exact interchangeability, and
says why so the judge grades the claim rather than the wording. The loosening
stands only where it belonged, on the frontend/RLS check.

Both experiments still pass 3/3 locally, now on answers that explicitly note
the keys are non-JWT and not a rename.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-evals-changed Add to a PR to refresh only the benchmark evals that have had changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant