echo "SUPABASE_URL=$SUPABASE_URL"
echo "SUPABASE_PROJECT_REF=$SUPABASE_PROJECT_REF"
echo "SUPABASE_DB_URL=$SUPABASE_DB_URL"
echo "SUPABASE_ANON_KEY length: ${#SUPABASE_ANON_KEY}"
echo "SUPABASE_SERVICE_ROLE_KEY length: ${#SUPABASE_SERVICE_ROLE_KEY}"
echo "SUPABASE_DB_PASSWORD length: ${#SUPABASE_DB_PASSWORD}"SUPABASE_URL=https://<ref>.supabase.co SUPABASE_PROJECT_REF=<ref> SUPABASE_DB_URL=<redacted:SUPABASE_DB_URL> SUPABASE_ANON_KEY length: 208 SUPABASE_SERVICE_ROLE_KEY length: 219 SUPABASE_DB_PASSWORD length: 48
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;"
count
-------
80
(1 row)
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.incident_log;" 2>&1 || echo "incident_log may not exist yet"
count
-------
0
(1 row)
mkdir -p /tmp/drill-backup # pg_dump: logical backup of ONLY public.payments, with clean (DROP + CREATE) and data PGPASSWORD="$SUPABASE_DB_PASSWORD" pg_dump "$SUPABASE_DB_URL" \ --table=public.payments \ --data-only \ --column-inserts \ --no-owner \ --no-privileges \ -f /tmp/drill-backup/payments_backup.sql echo "Exit code: $?" wc -l /tmp/drill-backup/payments_backup.sql head -30 /tmp/drill-backup/payments_backup.sql
Exit code: 0
113 /tmp/drill-backup/payments_backup.sql
--
-- PostgreSQL database dump
--
\restrict 5nRIWt8EHmaOxGcKhonQdD1RfIYe6DNCgnr8i64g98RpbWxJeencFkSmu3fCOMH
-- Dumped from database version 17.6
-- Dumped by pg_dump version 18.4 (Debian 18.4-1.pgdg12+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET transaction_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Data for Name: payments; Type: TABLE DATA; Schema: public; Owner: -
--
INSERT INTO public.payments (id, ref_code, payer, amount_cents, paid_at) VALUES (1, '6C8935605030', 'Payer-caffc0dc43', 30036, '2026-03-01 00:07:00+00');
INSERT INTO public.payments (id, ref_code, payer, amount_cents, paid_at) VALUES (2, '300351D74397', 'Payer-b964e8caa9', 101426, '2026-03-01 00:14:00+00');
INSERT INTO public.payments (id, ref_code, payer, amount_cents, paid_at) VALUES (3, '381DA59BBE42', 'Payer-77e253b14e', 484618, '2026-03-01 00:21:00+00');
INSERT INTO public.payments (id, ref_code, payer, amount_cents, paid_at) VALUES (4, 'FD441D715532', 'Payer-e8610229a5', 470397, '2026-03-01 00:28:00+00');
INSERT INTO public.payments (id, ref_code, payer, amount_cents, paid_at) VALUES (5, '49C2E5E745B1', 'Payer-9719c24260', 193265, '2026-03-01 00:35:00+00');
# Get a checksum of the payments data from the live DB (pre-incident) PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -t -A -c \ "SELECT md5(string_agg(row::text, ',' ORDER BY id)) FROM public.payments;" \ > /tmp/drill-backup/pre_incident_checksum.txt cat /tmp/drill-backup/pre_incident_checksum.txt echo "---" # Also get the exact row count and a sample PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) AS row_count FROM public.payments;"
---
row_count
-----------
80
(1 row)
ERROR: column "row" does not exist
LINE 1: SELECT md5(string_agg(row::text, ',' ORDER BY id)) FROM publ...
^
# Fix the checksum query using a subquery alias PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -t -A -c \ "SELECT md5(string_agg(t.row_data, ',' ORDER BY t.id)) FROM (SELECT id, to_jsonb(public.payments) AS row_data FROM public.payments) t;" \ > /tmp/drill-backup/pre_incident_checksum.txt echo "Pre-incident checksum:" cat /tmp/drill-backup/pre_incident_checksum.txt
Pre-incident checksum:
ERROR: missing FROM-clause entry for table "public"
LINE 1: ...ta, ',' ORDER BY t.id)) FROM (SELECT id, to_jsonb(public.pay...
^
# Simpler approach - just dump all rows as text and checksum PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -t -A -c \ "SELECT md5((SELECT string_agg(x, ',' ORDER BY ord) FROM (SELECT id || ':' || ref_code || ':' || payer || ':' || amount_cents || ':' || paid_at AS x, id AS ord FROM public.payments) sub));" \ > /tmp/drill-backup/pre_incident_checksum.txt echo "Pre-incident checksum:" cat /tmp/drill-backup/pre_incident_checksum.txt echo "" echo "Pre-incident row count confirmed: 80"
Pre-incident checksum: dca6b5ecb8549e6e114b1a31002e7236 Pre-incident row count confirmed: 80
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT public.run_incident();"
run_incident ------------------- incident executed (1 row)
# Check the state of payments after incident PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;" 2>&1 echo "---" # Check incident_log PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.incident_log;" 2>&1 echo "---" # Check what happened to payments PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.payments LIMIT 5;" 2>&1
count
-------
54
(1 row)
---
id | ran_at | details
----+-------------------------------+--------------------------------------
1 | 2026-07-26 03:24:57.250978+00 | payments corrupted by incident drill
(1 row)
---
id | ref_code | payer | amount_cents | paid_at
----+--------------+-----------+--------------+------------------------
1 | 6C8935605030 | CORRUPTED | 0 | 2026-03-01 00:07:00+00
2 | 300351D74397 | CORRUPTED | 0 | 2026-03-01 00:14:00+00
4 | FD441D715532 | CORRUPTED | 0 | 2026-03-01 00:28:00+00
5 | 49C2E5E745B1 | CORRUPTED | 0 | 2026-03-01 00:35:00+00
7 | E4006BBC4247 | CORRUPTED | 0 | 2026-03-01 00:49:00+00
(5 rows)
# Step 3: Restore payments from backup # First, TRUNCATE payments (removes all corrupted data), then re-insert from backup # This only touches public.payments — incident_log is untouched PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "TRUNCATE public.payments RESTART IDENTITY;" echo "After truncate:" PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;"
TRUNCATE TABLE
After truncate:
count
-------
0
(1 row)
# Re-insert all original data from backup PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -f /tmp/drill-backup/payments_backup.sql 2>&1
SET SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1
# Reset the identity sequence to the max id
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c \
"SELECT setval(pg_get_serial_sequence('public.payments', 'id'), COALESCE((SELECT MAX(id) FROM public.payments), 1));"
echo "---"
echo "Post-restore row count:"
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;"
echo "---"
echo "Post-restore checksum:"
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -t -A -c \
"SELECT md5((SELECT string_agg(x, ',' ORDER BY ord) FROM (SELECT id || ':' || ref_code || ':' || payer || ':' || amount_cents || ':' || paid_at AS x, id AS ord FROM public.payments) sub));"
echo ""
echo "Pre-incident checksum (from backup):"
cat /tmp/drill-backup/pre_incident_checksum.txt
echo "---"
echo "incident_log (must survive):"
PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.incident_log;" setval
--------
(1 row)
---
Post-restore row count:
count
-------
80
(1 row)
---
Post-restore checksum:
dca6b5ecb8549e6e114b1a31002e7236
Pre-incident checksum (from backup):
dca6b5ecb8549e6e114b1a31002e7236
---
incident_log (must survive):
id | ran_at | details
----+-------------------------------+--------------------------------------
1 | 2026-07-26 03:24:57.250978+00 | payments corrupted by incident drill
(1 row)
# Final spot check: verify a few rows match original backup values PGPASSWORD="$SUPABASE_DB_PASSWORD" psql "$SUPABASE_DB_URL" -c " SELECT id, ref_code, payer, amount_cents, paid_at FROM public.payments WHERE id IN (1, 2, 3, 40, 80) ORDER BY id; "
id | ref_code | payer | amount_cents | paid_at ----+--------------+------------------+--------------+------------------------ 1 | 6C8935605030 | Payer-caffc0dc43 | 30036 | 2026-03-01 00:07:00+00 2 | 300351D74397 | Payer-b964e8caa9 | 101426 | 2026-03-01 00:14:00+00 3 | 381DA59BBE42 | Payer-77e253b14e | 484618 | 2026-03-01 00:21:00+00 40 | 3E1DD4E6A86D | Payer-2c91fc5391 | 159879 | 2026-03-01 04:40:00+00 80 | E02258DCCE80 | Payer-180be3be40 | 267068 | 2026-03-01 09:20:00+00 (5 rows)
8 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