Repository navigation
Conversation
…key lookup (CLI-2713)
…invoice seeding (CLI-2713)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…the ground truth confirms (CLI-2713)
…val-seed-storage-buckets-and-move-files-locally # Conflicts: # evals/cli/lib/README.md
The harness now pre-starts the stack, which seeds the invoices into the public media bucket, so the agent has to move them on the live stack rather than fix the config before a first start. nodaemon and absent skip the eval. The prompt drops the leave-it-running sentence.
…w it skips them (CLI-2713)
…ill serves the invoices (CLI-2713) A managed stack the agent starts is scored ahead of the legacy stack the harness pre-started, so a run that left that stack serving every invoice publicly passed. When the scored stack isn't the legacy one, the scorer now reads the original invoice keys' public URLs on the legacy stack and fails the public-readability check on any 2xx.
Coly010
marked this pull request as ready for review
October 26, 2026 14:21
avallete
reviewed
Oct 26, 2026
avallete
left a comment
Member
There was a problem hiding this comment.
Cross-review (Codex gpt-6-sol, verified by Claude): grader false-pass/false-fail findings inline.
…ds the CLI rejects (CLI-2713) A quoted `public = "false"` read as private, so check 4 could pass a config that `supabase start` refuses to load on every channel. A wrong-typed storage, storage.enabled, storage.buckets, bucket entry, public or objects_path now fails the check with a note naming the field.
…orage-002's report judge (CLI-2713) Storage answers a missing object with HTTP 400 and a body whose statusCode is "404", so a report saying the old public URL returns 404 is true. The report judge failed one correct beta run for it.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Current Behavior
The cli suite has no eval for moving storage objects between buckets on the local stack, or for the declarative bucket seeding in
config.tomlthat decides what a fresh local setup holds. That is the design-phase storage journey in CLI-2713. Known traps:PostHog (CLI evals plan): storage commands are about 80% agent-driven, and agent runs of them fail about 15% of the time against 11% for non-agent runs.
Expected Behavior
This PR adds
evals/cli/build-storage-002-move-to-private-bucket(CLI-2713). The harness starts the local stack before the agent runs, and that start seeds all six files into the publicmediabucket. The prompt is a user whose customer invoices end up in the public storage bucket when they run Supabase locally, "and they're in there right now". It asks the agent to move them into a private bucket and make sure a fresh local setup doesn't put them back in the public one. So the agent has to move live objects across buckets and also fix the declarative seed.The prompt names no command, flag, path, bucket name, config key or file name.
The seed (Ledgerly, an invoicing app):
supabase/config.tomldeclares one bucket,media, withpublic = trueandobjects_path = "./storage/media".supabase/storage/media/avatars/*.svg: three avatars thatsrc/lib/avatars.tsloads by public URL.supabase/storage/media/invoices/*.pdf: three invoices. All six files have distinct sha256s.README.mddescribes the layout without instructions.CLI facts that shape it (verified on 2.117.0, 2.122.0, 2.123.0-beta.1 and 3.0.0-next.23):
storage ls/cp/mv/rmneed--experimental.--local.storage mvand ss→sscprefuse to cross buckets. So a move is download, upload andrm; a config fix followed bydb reset; orstop --no-backupand a fresh start.seed bucketscreates and overwrites but never deletes, so on its own it leaves the originals inmedia. A plainstopthenstartkeeps the database volume, so nothing is re-seeded.invoices are in a private bucket on the local stackpublic = false. A SQLupdate storage.objects set bucket_idmoves the row but not the bytes, so it fails.no invoice is publicly readable on the local stackmedia/invoices/*key answers its public URL or the anon key with a 2xx. Service and anon control requests (GET /storage/v1/bucket= 200) prove both identities were accepted. If the agent scored on a managed stack it started itself, the original keys are also read on the harness's legacy stack, and a 2xx there fails.avatars are still public where the app loads themmedia/avatars/*still answer their public URLs with the seeded bytes, so makingmediaprivate fails.a fresh local setup keeps invoices private and avatars publicconfig.tomlis parsed with smol-toml and each bucket'sobjects_pathis hashed in the sandbox. No public bucket seeds an invoice, some private bucket seeds every invoice, andmediastays public and seeds every avatar under its key. The listing mirrors the CLI: symlinked root and files followed, symlinked directories skipped, single-file paths supported.no container-runtime detoursdb reset, psql, curl and config edits are allowed. Writing into a storage container or the stack's storage directory counts as a detour.metrics--experimentaland--local), fresh-setup invoice buckets, stack stop, the harness's legacy stack when another stack was scored, and detours.final report is truthful about the invoicesNotes
--experimental,--localon 2.x, no cross-bucketmv/cp, and removing the originals frommedia. The eval needs Docker and a pre-started stack, soskipUnlessDockerlessdrops it from nodaemon and absent. Their rows from the earlier design are deleted fromcli-eval-results.json, because--mergerefreshes never drop rows they don't replace.projectRunning: false). In that version 19 of 20 passes fixed the config before their first start, so no run moved a live object. With the stack pre-started, a config-only fix,seed bucketsalone, and a plain stop and start all leave the invoices public, and checks 1–2 catch them.evals/cli/lib/stack-keys.tsreads the stack's API keys under the same CLI homes that resolved it.homePrefixinlib/stack.tsis now exported.readStackLifecyclefromlib/cli-invocations.ts, which came in with refactor(evals): share migration-history, psql and stack-lifecycle helpers in cli/lib #429.build-functions-008still carries a private copy of the key reader.--stack <name>or another CLI home goes unseen, so the harness's stack is scored instead.media/invoices/*keys, not invoice copies elsewhere on that stack.Verified locally
pnpm format:check && pnpm typecheck && pnpm testpnpm --filter @supabase-evals/framework exec vitest run --config vitest.cli-lib.config.ts evals/cli/build-storage-002-move-to-private-bucket evals/cli/lib, plus the wholetest:cli-libsuitepnpm --silent eval -- list --experiment-suite cli --eval build-storage-002-move-to-private-bucket, which lists pinned, stable, beta and nextshell.test.tsruns the real listing and curl commands against a temp dir and a local HTTP server.supabase stopis now named as such.No local stack was started; this PR's
run-evals-changedrefresh is the live run.Results
Latest refresh: 40355625422 on
a9bf4dc, with the stack pre-started; 3 runs per environment. nodaemon and absent skip the eval.How the passing runs got there:
config.toml(a privateinvoicesbucket, PDFs moved out ofmedia'sobjects_path) and moved the live objects too. In all 12 runs, the probe found the invoice bytes only in the private bucket andmediaholding just the 3 avatars.storage cp/mv/rm --experimental, often withseed bucketsfor the new bucket).fetchor supabase-js. That route doesn't appear instorageCommands, which counts only CLI storage commands.docker execcalls were read-onlypsqlselects, and the detour judge passed all 12.lastStackCommandis null or a redundantsupabase start.Earlier refreshes on the pre-started stack:
a32fd2d: 11/12. Beta run 2 was an agent gap. It fixed only the seed config and left the live invoices public, and its report said so.b1f4bd1: 11/12. Beta run 3 was a false fail.statusCodeis"404". The report judge failed a correct report for calling that a 404.a9bf4dctells the judge about that reply, with a regression test built from the transcript.The earlier design, where the agent started the stack, passed 3/3 on all four Docker arms (40316873437). 19 of those 20 passes fixed the config before the first start and never moved a live object. On the pre-started stack, the config-only fix fails, as the first refresh's beta run 2 showed.
Scorer fixes along the way:
b1f4bd1(from review): a config field the CLI rejects fails check 4 instead of falling back to its default. Examples are a quotedpublic = "false", a non-booleanstorage.enabled, a non-stringobjects_path, or a bucket that isn't a table. Every channel'ssupabase startrefuses to load such a config, so check 4 could previously pass one that never starts.0ab6236(earlier design, 40315089602): the report judge failed four runs whose claims the ground truth confirmed. It now accepts a check summarised from a sample, or one whose output wasn't recorded, when the ground truth confirms the result.🤖 Generated with Claude Code