env | grep -i supabase | sed 's/\(KEY=.\{12\}\).*/\1.../' ; which psql pg_dump; psql --versionSUPABASE_DB_PASSWORD=<redacted:SUPABASE_DB_PASSWORD> SUPABASE_DB_URL=<redacted:SUPABASE_DB_URL> SUPABASE_URL=https://<ref>.supabase.co SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJI... SUPABASE_PROJECT_REF=<ref> SUPABASE_ANON_KEY=eyJhbGciOiJI... /usr/bin/psql /usr/bin/pg_dump psql (PostgreSQL) 18.4 (Debian 18.4-1.pgdg12+1)
echo $SUPABASE_URL; echo $SUPABASE_PROJECT_REF
https://<ref>.supabase.co <ref>
cd /tmp && psql "$SUPABASE_DB_URL" -c "select version();" -c "\d public.orders"
version
------------------------------------------------------------------------------
PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 15.2.0, 64-bit
(1 row)
Table "public.orders"
Column | Type | Collation | Nullable | Default
----------------+--------------------------+-----------+----------+---------
id | integer | | not null |
customer_name | text | | not null |
customer_email | text | | not null |
item | text | | not null |
amount_cents | integer | | not null |
created_at | timestamp with time zone | | not null |
Indexes:
"orders_pkey" PRIMARY KEY, btree (id)
cd /tmp && psql "$SUPABASE_DB_URL" -c "select count(*) total, count(distinct customer_email) distinct_emails, count(distinct (customer_name,customer_email)) distinct_pairs, count(distinct lower(customer_email)) distinct_lower_emails from public.orders;"
total | distinct_emails | distinct_pairs | distinct_lower_emails -------+-----------------+----------------+----------------------- 120 | 40 | 40 | 40 (1 row)
cd /tmp && psql "$SUPABASE_DB_URL" -c "select customer_email, count(distinct customer_name) n_names, string_agg(distinct customer_name,' | ') names, count(*) orders from public.orders group by customer_email having count(distinct customer_name)>1 order by 1;"
customer_email | n_names | names | orders ----------------+---------+-------+-------- (0 rows)
cd /tmp && psql "$SUPABASE_DB_URL" -c "
select count(*) filter (where customer_email <> trim(customer_email)) email_ws,
count(*) filter (where customer_name <> trim(customer_name)) name_ws,
count(*) filter (where customer_email='' or customer_name='') empties,
min(id) min_id, max(id) max_id, sum(amount_cents) sum_amt
from public.orders;" email_ws | name_ws | empties | min_id | max_id | sum_amt
----------+---------+---------+--------+--------+---------
0 | 0 | 0 | 1 | 120 | 5108771
(1 row)
cd /tmp && psql "$SUPABASE_DB_URL" -c "select to_regclass('public.customers') customers_exists;" -c "select conname, pg_get_constraintdef(oid) from pg_constraint where conrelid='public.orders'::regclass;" -c "select trigger_name, event_manipulation from information_schema.triggers where event_object_table='orders';"customers_exists ------------------ (1 row) conname | pg_get_constraintdef -------------+---------------------- orders_pkey | PRIMARY KEY (id) (1 row) trigger_name | event_manipulation --------------+-------------------- (0 rows)
cd /tmp && pg_dump "$SUPABASE_DB_URL" --table=public.orders --no-owner --no-privileges -f orders_backup_$(date +%Y%m%d_%H%M%S).sql && ls -la orders_backup_*.sql && grep -c '^' orders_backup_*.sql
-rw-r--r-- 1 root root 12198 Jul 25 06:03 orders_backup_20260725_060256.sql 181
cd /tmp && psql "$SUPABASE_DB_URL" -At -F'|' -c "select id,customer_name,customer_email,item,amount_cents,created_at from public.orders order by id;" > baseline_full.txt && wc -l baseline_full.txt && md5sum baseline_full.txt && head -3 baseline_full.txt # baseline of the columns that must NOT change psql "$SUPABASE_DB_URL" -At -F'|' -c "select id,item,amount_cents,created_at from public.orders order by id;" > baseline_immutable.txt && md5sum baseline_immutable.txt
120 baseline_full.txt fbcbc3f03fb849de98acb2d6947ed1fd baseline_full.txt 1|Customer-2869aff5cb|66f4f3939508@example.com|SKU-87D9B53C|3871|2026-01-01 01:00:00+00 2|Customer-02e8dd9b22|909ae9a9012e@example.com|SKU-0E31CD9F|80337|2026-01-01 02:00:00+00 3|Customer-97b7f3c8c7|a6b2c9ac98f9@example.com|SKU-C4C1B8CF|56951|2026-01-01 03:00:00+00 37fa8e5da4c9a726dcfd7b5169a667ad baseline_immutable.txt
cd /tmp && cat > migrate.sql <<'SQL'
\set ON_ERROR_STOP on
BEGIN;
-- Lock orders so no concurrent writes can slip in between backfill and NOT NULL
LOCK TABLE public.orders IN SHARE ROW EXCLUSIVE MODE;
-- 1) customers: one row per distinct email, carrying that customer's name
CREATE TABLE public.customers (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL,
email text NOT NULL UNIQUE
);
INSERT INTO public.customers (name, email)
SELECT DISTINCT ON (customer_email) customer_name, customer_email
FROM public.orders
ORDER BY customer_email, id;
-- 2) customer_id column + FK, backfilled on exact (name,email) match
ALTER TABLE public.orders ADD COLUMN customer_id bigint;
UPDATE public.orders o
SET customer_id = c.id
FROM public.customers c
WHERE o.customer_email = c.email
AND o.customer_name = c.name;
-- Guard: every order must be matched before we proceed
DO $$
DECLARE unmatched int; missing int;
BEGIN
SELECT count(*) INTO unmatched FROM public.orders WHERE customer_id IS NULL;
IF unmatched > 0 THEN
RAISE EXCEPTION 'ABORT: % orders failed to match a customer', unmatched;
END IF;
SELECT count(*) INTO missing FROM public.orders o
LEFT JOIN public.customers c ON c.id = o.customer_id
WHERE c.id IS NULL OR c.email <> o.customer_email OR c.name <> o.customer_name;
IF missing > 0 THEN
RAISE EXCEPTION 'ABORT: % orders map to wrong customer', missing;
END IF;
IF (SELECT count(*) FROM public.orders) <> 120 THEN
RAISE EXCEPTION 'ABORT: order count changed';
END IF;
END $$;
ALTER TABLE public.orders
ALTER COLUMN customer_id SET NOT NULL,
ADD CONSTRAINT orders_customer_id_fkey
FOREIGN KEY (customer_id) REFERENCES public.customers(id);
CREATE INDEX orders_customer_id_idx ON public.orders (customer_id);
-- 3) drop the denormalized identity columns
ALTER TABLE public.orders DROP COLUMN customer_name, DROP COLUMN customer_email;
COMMIT;
SQL
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f migrate.sqlBEGIN LOCK TABLE CREATE TABLE INSERT 0 40 ALTER TABLE UPDATE 120 DO ALTER TABLE CREATE INDEX ALTER TABLE COMMIT
cd /tmp && psql "$SUPABASE_DB_URL" -At -F'|' -c "select o.id,c.name,c.email,o.item,o.amount_cents,o.created_at from public.orders o join public.customers c on c.id=o.customer_id order by o.id;" > after_reconstructed.txt wc -l after_reconstructed.txt; md5sum baseline_full.txt after_reconstructed.txt echo "--- diff (empty == zero loss) ---"; diff baseline_full.txt after_reconstructed.txt && echo "IDENTICAL: all 120 rows round-trip exactly"
120 after_reconstructed.txt fbcbc3f03fb849de98acb2d6947ed1fd baseline_full.txt fbcbc3f03fb849de98acb2d6947ed1fd after_reconstructed.txt --- diff (empty == zero loss) --- IDENTICAL: all 120 rows round-trip exactly
cd /tmp && psql "$SUPABASE_DB_URL" -At -F'|' -c "select id,item,amount_cents,created_at from public.orders order by id;" > after_immutable.txt && diff baseline_immutable.txt after_immutable.txt && echo "IMMUTABLE COLS UNCHANGED"; md5sum after_immutable.txt
IMMUTABLE COLS UNCHANGED 37fa8e5da4c9a726dcfd7b5169a667ad after_immutable.txt
cd /tmp && psql "$SUPABASE_DB_URL" -c "\d public.customers" -c "\d public.orders"
Table "public.customers"
Column | Type | Collation | Nullable | Default
--------+--------+-----------+----------+------------------------------
id | bigint | | not null | generated always as identity
name | text | | not null |
email | text | | not null |
Indexes:
"customers_pkey" PRIMARY KEY, btree (id)
"customers_email_key" UNIQUE CONSTRAINT, btree (email)
Referenced by:
TABLE "orders" CONSTRAINT "orders_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(id)
Table "public.orders"
Column | Type | Collation | Nullable | Default
--------------+--------------------------+-----------+----------+---------
id | integer | | not null |
item | text | | not null |
amount_cents | integer | | not null |
created_at | timestamp with time zone | | not null |
customer_id | bigint | | not null |
Indexes:
"orders_pkey" PRIMARY KEY, btree (id)
"orders_customer_id_idx" btree (customer_id)
Foreign-key constraints:
"orders_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(id)
cd /tmp && psql "$SUPABASE_DB_URL" -c "
select (select count(*) from public.orders) orders,
(select count(*) from public.customers) customers,
(select count(*) from public.orders where customer_id is null) null_fk,
(select sum(amount_cents) from public.orders) sum_amt,
(select count(*) from public.orders o left join public.customers c on c.id=o.customer_id where c.id is null) orphans,
(select count(*) from information_schema.columns where table_name='orders' and column_name in ('customer_name','customer_email')) leftover_cols,
(select count(*) from public.customers c where not exists (select 1 from public.orders o where o.customer_id=c.id)) unused_customers;"
echo "--- identity + generated check ---"
psql "$SUPABASE_DB_URL" -At -c "select column_name, data_type, is_nullable, is_identity, identity_generation from information_schema.columns where table_schema='public' and table_name='customers' order by ordinal_position;" orders | customers | null_fk | sum_amt | orphans | leftover_cols | unused_customers
--------+-----------+---------+---------+---------+---------------+------------------
120 | 40 | 0 | 5108771 | 0 | 0 | 0
(1 row)
--- identity + generated check ---
id|bigint|NO|YES|ALWAYS
name|text|NO|NO|
email|text|NO|NO|
cd /tmp && psql "$SUPABASE_DB_URL" -c "
BEGIN;
-- identity sequence must hand out a fresh id (no collision with the 40 existing)
INSERT INTO public.customers(name,email) VALUES ('smoke','smoke@test.invalid') RETURNING id;
-- FK must reject a bogus customer_id
SAVEPOINT s;
DO \$\$ BEGIN
INSERT INTO public.orders(id,item,amount_cents,created_at,customer_id) VALUES (999999,'X',1,now(),-1);
RAISE EXCEPTION 'FK DID NOT FIRE';
EXCEPTION WHEN foreign_key_violation THEN RAISE NOTICE 'OK: FK correctly rejected bad customer_id'; END \$\$;
ROLLBACK;"
echo "--- rolled back; confirm counts untouched ---"
psql "$SUPABASE_DB_URL" -At -c "select (select count(*) from public.customers)||' customers / '||(select count(*) from public.orders)||' orders';"BEGIN id ---- 41 (1 row) INSERT 0 1 SAVEPOINT DO ROLLBACK --- rolled back; confirm counts untouched --- 40 customers / 120 orders
NOTICE: OK: FK correctly rejected bad customer_id
curl -s "$SUPABASE_URL/rest/v1/orders?select=id,item,amount_cents,created_at,customers(name,email)&order=id.asc&limit=3" -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY"; echo; curl -s -I "$SUPABASE_URL/rest/v1/orders?select=id" -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" -H "Prefer: count=exact" -H "Range: 0-0" | grep -i content-range
[{"id":1,"item":"SKU-87D9B53C","amount_cents":3871,"created_at":"2026-01-01T01:00:00+00:00","customers":{"name": "Customer-2869aff5cb", "email": "66f4f3939508@example.com"}},
{"id":2,"item":"SKU-0E31CD9F","amount_cents":80337,"created_at":"2026-01-01T02:00:00+00:00","customers":{"name": "Customer-02e8dd9b22", "email": "909ae9a9012e@example.com"}},
{"id":3,"item":"SKU-C4C1B8CF","amount_cents":56951,"created_at":"2026-01-01T03:00:00+00:00","customers":{"name": "Customer-97b7f3c8c7", "email": "a6b2c9ac98f9@example.com"}}]
content-range: 0-119/120
9 earlier narration turn(s) are in the raw transcript.
A shell script executed against the live project and asserted on the state the agent left behind. No model judged another model.
Raw transcript · Task definition and verifier · Every attempt