feat: add docs homepage quickstart eval - #108
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
aa840a8 to
ab5421a
Compare
nrichers
left a comment
There was a problem hiding this comment.
@czenko as mentioned on Slack, I think you just broke the ice on getting docs into Evals! 👏
I tested your PR locally and for the intent of adding a happy path smoke test, LGTM. 👍 I will defer to the Evals team for approval of the actual code changes as these are outside of my wheelhouse.
This is a great first step towards our a AEO testing aspirations. Way cool and thank you so much! 🚀
Verdict: Approve with a note
| Check | Result |
|---|---|
pnpm --filter @supabase-evals/framework typecheck |
✅ pass |
pnpm --filter @supabase-evals/core test |
✅ 47/47 pass |
pnpm --filter @supabase-evals/sandbox test |
✅ 35/35 pass |
SANDBOX_DOCKER_TESTS=1 ... test:docker -t skipCliInstall |
✅ pass — CLI genuinely absent, shim doesn't crash setup |
pnpm eval:dry --eval build-cli-004-quickstart-nextjs --experiment claude-code-sonnet-5,claude-code-sonnet-5-no-skills |
✅ matches PR claim exactly: SKIP claude-code-sonnet-5-no-skills ... (skipEval), PLAN claude-code-sonnet-5 ... |
| CI | Only Vercel preview checks run on this repo; no required checks configured |
Verified:
skills/skipCliInstallfrontmatter plumbing is threaded correctly end-to-end:eval-metadata.ts→run-eval.ts(ev.metadata.skills ?? exp.skills) →agent-environment.ts→local-stack-runtime.ts/supabase.ts(skip both CLI install and the CLI wrapper whenskipCliInstall).skipEvalonclaude-code-sonnet-5-no-skillsand the newlist --evalfiltering inrun-eval.ts/eval-refresh.ymlcorrectly avoid planning a redundant duplicate run — confirmed live viaeval:dry.- New eval's scorer (
EVAL.ts) checks are sound:supabase/config.tomlexistence,supabase --versionrunnable, an LLM-judge rubric for "relevant next steps," and a regex check for the plugin-install command actually being attempted (explicitly not asserting install success, with a comment explaining why — reasonable scoping).
Notes (non-blocking):
- The checked-in
apps/web/src/data/regression-eval-results.jsoncurrently contains a stale entry:claude-code-sonnet-5-no-skills×build-cli-004-quickstart-nextjsshowspassed: true, but per this PR's ownskipEvallogic, that experiment should no longer run against this eval at all. Tracing the twochore: refresh eval resultsbot commits: the first (ab5421a, 2026-07-22 23:22 UTC) ran before theskipEvalfix (cc8b18a, 2026-07-23 19:18 UTC) and recorded that result; the second (f93b41a, 19:24 UTC) ran after the fix but used the PR-triggeredrun-evals-changedpath, which callsexport-results --merge.export-results.ts's merge logic (apps/framework/scripts/export-results.ts:274-289) only overwritesexperiment::evalkeys present in the new results — it never prunes keys that stop being produced. Since the skipped combo now produces no artifact at all, the stale pre-fix "passed" result will persist through every future merge-mode refresh, only self-correcting on the next full (non-merge) scheduled regression run. This is a pre-existing gap inexport-results.ts's merge semantics, not something this PR broke, but this PR is the first to exerciseskipEvaland is shipping a visibly-stale row intomainas a result. Worth a follow-up (either prune-on-merge inexport-results.ts, or manually drop that row before merging). claude-code-sonnet-5's own real (non-dry) regression result for the new eval showspassed: false(supabase CLI is installed and runnablefailed — CLI not found after the agent'snpm install -g supabase), while everything else passed (init, plugin-install attempt, next-steps judge). Worth confirming with the author whether this is expected/tracked behavior (a real capability gap the eval is meant to surface) or a PATH-related environment artifact — not a reason to block the PR either way, since the eval mechanically does exactly what it's designed to do.
DOCS-1199 Add one happy-path quickstart Eval test
Ship one narrow happy-path quickstart test for a popular framework using the shared docs E2E harness. The goal for this milestone is one reliable smoke path by the deadline rather than broader cross-framework coverage. Include enough structure or documentation so additional framework tests can be added later without reshaping the setup. Text to EvaluateFrom Supabase.com/docs Slack thread contextMiranda asked whether evaluating the AI prompt on the docs homepage should live in the Relevant guidance from matt.rossman:
Original question from the thread:
See the Slack thread for the full discussion. |
|
@nrichers Thanks for flagging the merge-mode gap. Fixes in
|
nrichers
left a comment
There was a problem hiding this comment.
LGTM, thank you for addressing my comment. 🚀
There was a problem hiding this comment.
Hey @czenko I tested running this new eval locally. During that local run, the agent failed to install supabase CLI with npm because the Node image installs node as root and doesn't expose sudo access, so it gets stuck on the npm install -g supabase step:
$ npm install -g supabase 2>&1
Exit code 243
npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/lib/node_modules/supabase
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/supabase'
...
npm error It is likely you do not have the permissions to access this file as the current user
npm error
npm error If you believe this might be a permissions issue, please double-check the
npm error permissions of the file and its containing directories, or try running
npm error the command again as root/Administrator.I believe the CI run failed for the same reason:
I figure a typical user's machine will have Node configured in a way that npm install -g "just works" for a user without needing sudo, maybe we should update the Dockerfile to configure it this way to make the scenario more fair?
I found this Global npm dependencies section in the docs for the official Node.js docker images, which recommends the following:
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying pathThe ENV PATH line may need to be adapted for our use case, because we override PATH with an explicit SANDBOX_PATH list here, so we can instead add it like:
--- a/packages/sandbox/src/docker-sandbox.ts
+++ b/packages/sandbox/src/docker-sandbox.ts
@@
const SANDBOX_PATH = [
+ "/home/node/.npm-global/bin",
"/usr/local/sbin",
"/usr/local/bin",
"/usr/sbin",
"/usr/bin",
"/sbin",
"/bin",
].join(":");I think we'll also need to make sure the /home/node/.npm-global folder isn't created as root during image build, otherwise subsequent npm install -g may not work. Note the npm install -g skills line implicitly initializes this folder as whichever user is active (root` unless otherwise specified in the Dockerfile), so we could explicitly create the folder + set up the npm config prefix beforehand.
--- a/packages/sandbox/Dockerfile
+++ b/packages/sandbox/Dockerfile
@@
FROM node:22-slim
RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \
ca-certificates curl git docker.io postgresql-client \
&& rm -rf /var/lib/apt/lists/*
+USER node
+RUN mkdir -p /home/node/.npm-global
+ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
+
# Vercel's agent-skills CLI, used to install agent skills from local sources
# into each session's workspace (both modes). Baked in (pinned) so installs are
# offline and instant rather than an npx download per session.
ARG SKILLS_CLI_VERSION
RUN npm install -g "skills@${SKILLS_CLI_VERSION}"I tested this change locally and verified it allows the new eval to pass 4/4 checks, vs failing one of the checks otherwise.
|
Also may want to add a test to lock in the behavior: it(
"npm install -g lands on PATH without sudo/workarounds",
{ timeout: TEST_TIMEOUT_MS },
async () => {
const image = await ensureSupabaseSandboxImage();
const sandbox = await DockerSandbox.create({ image, network: "host" });
try {
const install = await sandbox.runShell("npm install -g supabase 2>&1");
expect(install.ok).toBe(true);
const version = await sandbox.runShell("supabase --version");
expect(version.ok).toBe(true);
} finally {
await sandbox.stop();
}
},
); |
d28e30b to
b73235c
Compare
|
@mattrossman Thanks for digging into this. Thoughtful, thorough feedback. Applied basically as you proposed:
|
8ec4afe to
5bdc255
Compare
959273e to
ca5498a
Compare
| import { stripIndent } from 'common-tags'; | ||
|
|
||
| const PLUGIN_INSTALL_PATTERN = | ||
| /npx\s+plugins\s+add\s+supabase-community\/supabase-plugin/i; |
There was a problem hiding this comment.
Thanks. Will look into this on Monday.
There was a problem hiding this comment.
Pushing a fix for the regex, @mattrossman.
As another note, if there is more feedback that seems to be low-hanging, feel free to commit it directly so this can be merged. Or maybe we can review it together live? I admit that a lot of this PR is AI-assisted and your context and expertise will be valuable for me.
Adds a happy-path smoke test for the "Help me get set up with Supabase" prompt shown on the docs homepage, seeded with a bare Next.js app so the agent has a real project to detect and initialize.
Adds `skills: []` and `skipCliInstall: true` frontmatter overrides plus an experiment-level `skipEval` predicate, so a scenario can test an agent installing its own Supabase CLI/skills regardless of which experiment runs it. Applies both to the docs homepage quickstart eval, which now exercises the CLI/plugin-install steps for real instead of having them pre-satisfied by the sandbox. Also teaches the eval-refresh workflow's discovery step (and the underlying `pnpm eval -- list --eval`) to drop experiment/eval pairs that skipEval would skip, so a no-skills experiment paired with a skills:[] eval doesn't get scheduled — the pairing that broke publish-results by expecting an artifact that skipEval prevents from ever being produced. Also fixes `npm install -g supabase` failing with EACCES in the sandbox image: the node:22-slim image installs global packages as root, so point NPM_CONFIG_PREFIX at a node-owned directory and add it to PATH so unelevated global installs work. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also drops a stale pre-skipEval result row for claude-code-sonnet-5-no-skills/build-cli-004-quickstart-nextjs: merge mode in export-results.ts only overwrites keys present in new results and never prunes keys that stop being produced, so the old "passed: true" row would otherwise persist through every merge-mode refresh now that skipEval excludes that experiment from this eval. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mattrossman reported a local run failing this check because the agent ran `npx --yes plugins add supabase-community/supabase-plugin` and the regex didn't allow flags between `npx` and `plugins`.
8c02111 to
f8ee821
Compare

Closes DOCS-1199
Problem
The docs homepage shows a "Help me get set up with Supabase" prompt. That flow installs the Supabase CLI and Supabase plugin, detects or initializes the project, and suggests next steps, but no eval covers it. CI wouldn't catch a regression in the CLI or plugin install steps, and the sandbox pre-satisfying those steps would mask a failure even in a new eval.
Solution
evals/build-cli-004-quickstart-nextjs, seeded with a bare Next.js app, to exercise the docs homepage quickstart prompt end-to-end.skills: []andskipCliInstall: trueoverrides so the eval tests the CLI and plugin install steps directly, instead of relying on the sandbox to pre-satisfy them.skipEvalpredicate so the no-skills experiment skips evals whose skills list is already empty, avoiding a duplicate run.skipEval. Without this fix,publish-resultstried to download an artifact for a pair thatskipEvalprevents from ever being produced. This broke CI on the first run of this PR.Manual testing
pnpm eval:dry -- --eval build-cli-004-quickstart-nextjs --experiment claude-code-sonnet-5,claude-code-sonnet-5-no-skills. Onlyclaude-code-sonnet-5should be planned. The no-skills experiment should printSKIP ... (skipEval).evals/build-cli-004-quickstart-nextjs/EVAL.tsfor the checks that confirm the CLI and plugin were installed, rather than already present. That's the part most likely to break if the sandbox's base image changes.run-evals-changedlabel to confirmpublish-resultscompletes without the artifact-download failure.