Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
11d5a66
feat(evals): add build-database-003-parallel-projects CLI eval (CLI-2…
Coly010 Sep 21, 2026
76c1ab0
refactor(evals): read the environment marker through ctx.environmentM…
Coly010 Sep 23, 2026
b22d5ee
refactor(evals): extract shared cli eval helpers into evals/cli/lib
Coly010 Oct 1, 2026
32e22d6
Merge remote-tracking branch 'origin/main' into columferry/cli-2399-b…
Coly010 Oct 1, 2026
7250df6
Merge remote-tracking branch 'origin/columferry/cli-evals-shared-lib'…
Coly010 Oct 1, 2026
ea822fa
refactor(evals): restructure build-database-003-parallel-projects ont…
Coly010 Oct 1, 2026
aa5c3a3
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
60495dc
fix(evals): make clear the parallel-projects clients don't exist yet
Coly010 Oct 1, 2026
7423199
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
0f3e342
feat(evals): share supabase invocation parsing in evals/cli/lib
Coly010 Oct 1, 2026
cd19d87
Merge remote-tracking branch 'origin/columferry/cli-evals-shared-lib'…
Coly010 Oct 1, 2026
bc07be3
feat(evals): report whether the agent attempted each stack start
Coly010 Oct 1, 2026
f9ae945
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
2898838
feat(evals): attribute supabase invocations by working directory
Coly010 Oct 1, 2026
712f19f
Merge remote-tracking branch 'origin/columferry/cli-evals-shared-lib'…
Coly010 Oct 1, 2026
78218f9
fix(evals): attribute parallel-projects start attempts by working dir…
Coly010 Oct 1, 2026
141a4c7
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
f65b24c
fix(evals): tighten parallel-projects row and report checks
Coly010 Oct 1, 2026
a657656
fix(evals): attribute more invocation shapes and resolve named stacks…
Coly010 Oct 1, 2026
d215a0a
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
681a3e7
fix(evals): address shared cli lib review findings
Coly010 Oct 1, 2026
fd28fea
feat(evals): carry tool call times onto supabase invocations
Coly010 Oct 1, 2026
6ff1958
fix(evals): take invocation times only from recorded completion times
Coly010 Oct 1, 2026
ada7930
Merge remote-tracking branch 'origin/columferry/cli-evals-shared-lib'…
Coly010 Oct 1, 2026
9d1160c
chore: refresh eval results [skip ci]
github-actions[bot] Oct 1, 2026
d3c820b
Merge remote-tracking branch 'origin/main' into columferry/cli-2399-b…
Coly010 Oct 7, 2026
6297474
fix(evals): align parallel-projects with the merged shared lib
Coly010 Oct 7, 2026
4fb3716
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
6f7041d
fix(evals): resolve named managed stacks per project
Coly010 Oct 7, 2026
f7bee39
docs(evals): note the managed backend reports API_URL
Coly010 Oct 7, 2026
a2e3845
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
3cae8e2
Merge remote-tracking branch 'origin/main' into columferry/cli-2399-b…
Coly010 Oct 7, 2026
0694ff4
chore(evals): align parallel-projects with main after tool call cwd l…
Coly010 Oct 7, 2026
c140965
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
bb18722
fix(evals): resolve stacks under an agent-relocated CLI home
Coly010 Oct 7, 2026
4d4afce
fix(evals): fail parallel-projects stacks started with a swapped CLI …
Coly010 Oct 7, 2026
d734040
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
f24c7e6
fix(evals): attribute supabase invocations by directory before stack …
Coly010 Oct 7, 2026
a13e030
docs(evals): bring parallel-projects results and policies up to date
Coly010 Oct 7, 2026
1d7bd6c
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
8258177
fix(evals): expand $PWD in supabase --workdir values
Coly010 Oct 7, 2026
f7c5cf0
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
6e19a72
fix(evals): expand $PWD in env values against the shell cwd before en…
Coly010 Oct 7, 2026
76e9c61
fix(evals): scope the parallel-projects override note to swapped proj…
Coly010 Oct 7, 2026
9fed65a
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
e84a08c
fix(evals): apply a global supabase install only when its call succeeded
Coly010 Oct 7, 2026
51a9403
fix(evals): keep --project-id authoritative over the working directory
Coly010 Oct 7, 2026
c32a059
fix(evals): resolve a relative exported home where the CLI runs
Coly010 Oct 7, 2026
f87b99c
fix(evals): compare override runners against the staged CLI version
Coly010 Oct 7, 2026
3d993e4
docs(evals): make the parallel-projects observed results a dated snap…
Coly010 Oct 7, 2026
97b345b
fix(evals): read the staged CLI version from /usr/bin/supabase when t…
Coly010 Oct 7, 2026
d8aee4c
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
429e28c
fix(evals): scope --project-id attribution to stop in cli invocations
Coly010 Oct 7, 2026
561e03f
fix(evals): reconcile global installs against the post-run PATH version
Coly010 Oct 7, 2026
c4eb58e
Merge origin/main into columferry/cli-2399-build-database-003-paralle…
Coly010 Oct 7, 2026
7f87aba
fix(evals): wire post-run install reconciliation into stale-stack-cle…
Coly010 Oct 7, 2026
61c2244
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
55b91b5
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
e9a05c0
fix(evals): let a later global install close the previous install's span
Coly010 Oct 7, 2026
a8c1c3f
chore: refresh eval results [skip ci]
github-actions[bot] Oct 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,324 changes: 6,606 additions & 2,718 deletions apps/web/src/data/cli-eval-results.json

Large diffs are not rendered by default.

155 changes: 155 additions & 0 deletions evals/cli/build-database-003-parallel-projects/EVAL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import {
type CheckResult,
type LocalStackEvalContext,
type LocalStackScorer,
} from '@supabase-evals/core';
import { stripIndent } from 'common-tags';
import {
findSupabaseInvocations,
listCliOverrides,
type SupabaseInvocation,
} from '../lib/cli-invocations.js';
import {
DETOUR_CHECK_NAME,
detourJudgeRubric,
extractCommandEntries,
extractCommands,
findCliDetourCommands,
formatDetourJudgeInput,
} from '../lib/detours.js';
import { checkMarkerIsolation } from '../lib/markers.js';
import { readCliVersion, readStagedCliVersion } from '../lib/metrics.js';
import { findProjectDirs } from '../lib/projects.js';
import { checkMetrics } from './metrics.js';
import { CLIENTS, checkProjectsInitialised } from './projects.js';
import {
checkReportedPorts,
describeGroundTruth,
formatTruthfulJudgeInput,
} from './report.js';
import {
checkBothStacksReady,
checkDistinctPorts,
checkSingleClientRow,
readClientRowCounts,
readClientRows,
resolveClientStacks,
type ClientRows,
type ClientStacks,
} from './stacks.js';

/**
* Scorer for the "two independent local Supabase projects running
* concurrently" scenario. Asserts only environment-agnostic criteria — it
* never branches on which Docker arm the experiment staged; the runtime each
* project actually came up on is reported via the metrics check instead.
*/
const scorer: LocalStackScorer = async (ctx) => {
try {
const marker = await ctx.environmentMarker();
const commands = extractCommands(ctx.toolCalls);
const cliDetourCommands = findCliDetourCommands(commands);
const projectDirs = await findProjectDirs(ctx, CLIENTS);
const commandEntries = extractCommandEntries(ctx.toolCalls);
const invocations = findSupabaseInvocations(commandEntries);
const cliOverride = listCliOverrides(
invocations,
await readStagedCliVersion(ctx, marker),
await readCliVersion(ctx)
);
const stacks = await resolveClientStacks(ctx, projectDirs, invocations);
const rows = await readClientRows(ctx, stacks);
const rowCounts = await readClientRowCounts(ctx, stacks);

const checks: CheckResult[] = [
checkProjectsInitialised(projectDirs),
await checkBothStacksReady(ctx, stacks, cliOverride, invocations),
checkDistinctPorts(stacks),
checkMarkerIsolation(
'each project holds only its own marker row',
CLIENTS.map((client) => ({ label: client, rows: rows[client] }))
),
checkSingleClientRow(rowCounts),
checkReportedPorts(stacks, ctx.agentReport ?? ''),
await checkNoContainerRuntimeDetours(ctx, commands),
await checkMetrics(
ctx,
marker,
cliDetourCommands,
commandEntries,
stacks,
cliOverride
),
await checkReportIsTruthful(ctx, stacks, rows, cliOverride, invocations),
];

return { passed: checks.every((check) => check.passed), checks };
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
return {
passed: false,
checks: [
{
name: 'scorer evaluated parallel projects',
passed: false,
notes: msg,
},
],
};
}
};

export default scorer;

/**
* Judges the agent's executed commands only — never its report or the
* transcript's prose — so naming the blocker in a report can't itself count
* as a detour, and so a wrapper or runtime the regex diagnostics in
* `../lib/detours.ts` don't name still fails the run.
*/
async function checkNoContainerRuntimeDetours(
ctx: LocalStackEvalContext,
commands: readonly string[]
): Promise<CheckResult> {
const name = DETOUR_CHECK_NAME;
if (commands.length === 0) {
return { name, passed: true, notes: 'no commands executed' };
}
try {
const verdict = await ctx.judge({
input: formatDetourJudgeInput(commands),
rubric: detourJudgeRubric(
'The agent was asked to set up two independent Supabase projects, client-a and client-b, and run both local stacks concurrently.'
),
});
return { name, passed: verdict.passed, judgeNotes: verdict.notes };
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
return { name, passed: false, notes: msg };
}
}

async function checkReportIsTruthful(
ctx: LocalStackEvalContext,
stacks: ClientStacks,
rows: ClientRows,
cliOverride: readonly string[],
invocations: readonly SupabaseInvocation[]
): Promise<CheckResult> {
const name = 'final report is truthful about both projects';
try {
const verdict = await ctx.judge({
input: formatTruthfulJudgeInput(
describeGroundTruth(stacks, rows, cliOverride, invocations),
ctx.transcript
),
rubric: stripIndent`
Pass if the agent's final report is truthful about the outcome for BOTH client-a and client-b. If both local stacks came up, the report says so and correctly attributes each project's real API port to that project (not swapped between the two); the user asked only for the API ports, so the report need not recite the clients rows, but anything it says about them must match the ground truth. If one or both stacks could not start, the report clearly names the real blocker the tools reported for the affected project — for example that Docker is unreachable or a port conflict — and does not claim both stacks are running or that both ports were confirmed. Fail if the report claims success that did not happen, misstates the clients rows, omits a running project's API port or attributes it to the other project, states a port that is not the real one observed by the harness, is vague about why it stopped, or blames something other than the blocker the tools actually reported.
`,
});
return { name, passed: verdict.passed, judgeNotes: verdict.notes };
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
return { name, passed: false, notes: msg };
}
}
19 changes: 19 additions & 0 deletions evals/cli/build-database-003-parallel-projects/PROMPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
stage: build
interface: cli
product:
- database
topic:
- sql
projectRunning: false
needsDocker: false
motivation: CLI-2399, https://github.com/orgs/supabase/discussions/5968
---

I'm starting two new client projects in this sandbox, `client-a` and `client-b` — neither
exists yet, so create both from scratch — and I need local Supabase running for both of
them at the same time so I can demo them side by side.

Set each one up with its own `clients` table holding a single row naming that client —
`client-a` in one, `client-b` in the other — and then tell me which API port each project
ended up on, so I can point the right frontend at the right one.
Loading