Files
gstack/supabase/migrations/002_eval_runs.sql
T
Garry Tan f7ae465415 feat: add Supabase migration SQL for team data store
- 001_teams.sql: teams + team_members + RLS
- 002_eval_runs.sql: eval results with universal format, indexes, upsert key
- 003_data_tables.sql: retro, QA, ship, greptile, transcripts + RLS

All tables use RLS: team members read/insert, admins delete.
Transcript table has tighter policy (admin-only read).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 02:02:47 -05:00

72 lines
2.6 KiB
SQL

-- 002_eval_runs.sql — Eval result storage.
--
-- Mirrors EvalResult from test/helpers/eval-store.ts.
-- Supports both gstack's native eval format and the universal
-- adapter format (any language pushes JSON results).
create table if not exists eval_runs (
id uuid primary key default gen_random_uuid(),
team_id uuid references teams(id) not null,
user_id uuid references auth.users(id),
repo_slug text not null,
hostname text not null default '',
-- Eval metadata
schema_version int not null default 1,
version text not null default '',
branch text not null default '',
git_sha text not null default '',
timestamp timestamptz not null default now(),
tier text not null default 'e2e',
-- Summary stats
total_tests int not null default 0,
passed int not null default 0,
failed int not null default 0,
total_cost_usd numeric(10,4) not null default 0,
total_duration_ms int not null default 0,
-- Universal format fields (adapter mode)
label text, -- e.g. "dev_fix-terseness_standard"
prompt_sha text, -- SHA of prompt source files
by_category jsonb, -- { "post_generation": { passed: 16, total: 17 } }
costs jsonb, -- [{ model, calls, input_tokens, output_tokens }]
-- Full test results (transcripts stripped for team sync)
tests jsonb not null default '[]'::jsonb,
created_at timestamptz default now()
);
-- Indexes for common queries
create index if not exists idx_eval_runs_team on eval_runs(team_id);
create index if not exists idx_eval_runs_repo on eval_runs(team_id, repo_slug);
create index if not exists idx_eval_runs_branch on eval_runs(team_id, branch);
create index if not exists idx_eval_runs_timestamp on eval_runs(team_id, timestamp desc);
create index if not exists idx_eval_runs_label on eval_runs(team_id, label) where label is not null;
-- Upsert natural key: timestamp + hostname + repo_slug (idempotent pushes)
create unique index if not exists idx_eval_runs_natural_key
on eval_runs(team_id, timestamp, hostname, repo_slug);
-- RLS
alter table eval_runs enable row level security;
create policy "team_read" on eval_runs
for select using (
team_id in (select team_id from team_members where user_id = auth.uid())
);
create policy "team_insert" on eval_runs
for insert with check (
team_id in (select team_id from team_members where user_id = auth.uid())
);
create policy "admin_delete" on eval_runs
for delete using (
team_id in (
select team_id from team_members
where user_id = auth.uid() and role in ('owner', 'admin')
)
);