echo "=== Environment check ===" && echo "SUPABASE_URL: set" && echo "SUPABASE_PROJECT_REF: set" && echo "SUPABASE_ANON_KEY: set" && echo "SUPABASE_SERVICE_ROLE_KEY: set" && echo "SUPABASE_DB_URL: set" && echo "SUPABASE_DB_PASSWORD: set" && echo "" && echo "=== Tools check ===" && which pg_dump && which psql && echo "" && echo "=== Connection test ===" && psql "$SUPABASE_DB_URL" -c "SELECT current_database(), current_user;" 2>&1
=== Environment check === SUPABASE_URL: set SUPABASE_PROJECT_REF: set SUPABASE_ANON_KEY: set SUPABASE_SERVICE_ROLE_KEY: set SUPABASE_DB_URL: set SUPABASE_DB_PASSWORD: set === Tools check === /usr/bin/pg_dump /usr/bin/psql === Connection test === current_database | current_user ------------------+-------------- postgres | postgres (1 row)
echo "=== Pre-incident: payments row count ===" && psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;" && echo "" && echo "=== Pre-incident: incident_log (should be empty or have prior records) ===" && psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.incident_log;" && echo "" && echo "=== Payments table structure ===" && psql "$SUPABASE_DB_URL" -c "\d public.payments"
=== Pre-incident: payments row count ===
count
-------
80
(1 row)
=== Pre-incident: incident_log (should be empty or have prior records) ===
count
-------
0
(1 row)
=== Payments table structure ===
Table "public.payments"
Column | Type | Collation | Nullable | Default
--------------+--------------------------+-----------+----------+---------
id | integer | | not null |
ref_code | text | | not null |
payer | text | | not null |
amount_cents | integer | | not null |
paid_at | timestamp with time zone | | not null |
Indexes:
"payments_pkey" PRIMARY KEY, btree (id)
# Take a full logical backup of ONLY the payments table (schema + data) pg_dump "$SUPABASE_DB_URL" \ --table=public.payments \ --no-owner \ --no-privileges \ --format=plain \ --file=/tmp/payments_backup.sql 2>&1 echo "=== Backup file created ===" ls -la /tmp/payments_backup.sql echo "" echo "=== Backup file size ===" wc -c /tmp/payments_backup.sql echo "" echo "=== Verify backup contains COPY data ===" grep -c "^COPY public.payments" /tmp/payments_backup.sql echo "" echo "=== Compute pre-incident checksum for verification ===" psql "$SUPABASE_DB_URL" -t -A -c "SELECT md5(string_agg(t::text, '|' ORDER BY id)) FROM public.payments t;" > /tmp/payments_checksum_pre.txt cat /tmp/payments_checksum_pre.txt
=== Backup file created === -rw-r--r-- 1 root root 6370 Jul 24 15:42 /tmp/payments_backup.sql === Backup file size === 6370 /tmp/payments_backup.sql === Verify backup contains COPY data === 1 === Compute pre-incident checksum for verification === 0dc7461b7b8bece10b61939f1ac53348
# Extra safety: export all rows as CSV for verification psql "$SUPABASE_DB_URL" -c "\COPY (SELECT * FROM public.payments ORDER BY id) TO '/tmp/payments_pre_incident.csv' WITH CSV HEADER" 2>&1 echo "=== CSV export ===" wc -l /tmp/payments_pre_incident.csv echo "" echo "=== Row count check (should be 80) ===" psql "$SUPABASE_DB_URL" -t -A -c "SELECT count(*) FROM public.payments;" echo "" echo "=== Make backup copies for safety ===" cp /tmp/payments_backup.sql /tmp/payments_backup_backup.sql ls -la /tmp/payments_*.sql /tmp/payments_*.csv /tmp/payments_*.txt
COPY 80 === CSV export === 81 /tmp/payments_pre_incident.csv === Row count check (should be 80) === 80 === Make backup copies for safety === -rw-r--r-- 1 root root 6370 Jul 24 15:42 /tmp/payments_backup.sql -rw-r--r-- 1 root root 6370 Jul 24 15:42 /tmp/payments_backup_backup.sql -rw-r--r-- 1 root root 33 Jul 24 15:42 /tmp/payments_checksum_pre.txt -rw-r--r-- 1 root root 5054 Jul 24 15:42 /tmp/payments_pre_incident.csv
echo "=== Triggering incident: SELECT public.run_incident(); ===" psql "$SUPABASE_DB_URL" -c "SELECT public.run_incident();" 2>&1 echo "" echo "=== Verify incident was logged ===" psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.incident_log;" 2>&1 echo "" echo "=== Post-incident: payments row count ===" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;" 2>&1
=== Triggering incident: SELECT public.run_incident(); ===
run_incident
-------------------
incident executed
(1 row)
=== Verify incident was logged ===
id | ran_at | details
----+-------------------------------+--------------------------------------
1 | 2026-07-24 15:43:02.782319+00 | payments corrupted by incident drill
(1 row)
=== Post-incident: payments row count ===
count
-------
54
(1 row)
# First, save the incident_log so it survives the restore # The backup file contains schema (CREATE TABLE) + data (COPY) for payments only. # Since the table still exists but is corrupted, we need to: # 1. Truncate the corrupted payments table # 2. Restore data from backup # But first, let's check if the schema is still intact echo "=== Current table structure (post-incident) ===" psql "$SUPABASE_DB_URL" -c "\d public.payments" 2>&1 echo "" echo "=== Current incident_log (must survive) ===" psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.incident_log;" 2>&1
=== Current table structure (post-incident) ===
Table "public.payments"
Column | Type | Collation | Nullable | Default
--------------+--------------------------+-----------+----------+---------
id | integer | | not null |
ref_code | text | | not null |
payer | text | | not null |
amount_cents | integer | | not null |
paid_at | timestamp with time zone | | not null |
Indexes:
"payments_pkey" PRIMARY KEY, btree (id)
=== Current incident_log (must survive) ===
id | ran_at | details
----+-------------------------------+--------------------------------------
1 | 2026-07-24 15:43:02.782319+00 | payments corrupted by incident drill
(1 row)
# The backup contains schema + data. Since the table still exists with correct schema, # we only need to restore the DATA. Extract just the COPY block from the backup. echo "=== Inspecting backup structure ===" grep -n "^COPY\|^\\\\\." /tmp/payments_backup.sql echo "" echo "=== Truncating corrupted payments data ===" psql "$SUPABASE_DB_URL" -c "TRUNCATE public.payments;" 2>&1 echo "" echo "=== Restoring data from backup (COPY block only) ===" # Extract everything between COPY and the terminating \. line, inclusive sed -n '/^COPY public.payments/,/^\\.$/p' /tmp/payments_backup.sql | psql "$SUPABASE_DB_URL" 2>&1 echo "" echo "=== Post-restore: payments row count ===" psql "$SUPABASE_DB_URL" -c "SELECT count(*) FROM public.payments;" 2>&1
=== Inspecting backup structure ===
43:COPY public.payments (id, ref_code, payer, amount_cents, paid_at) FROM stdin;
124:\.
=== Truncating corrupted payments data ===
TRUNCATE TABLE
=== Restoring data from backup (COPY block only) ===
COPY 80
=== Post-restore: payments row count ===
count
-------
80
(1 row)
# Compute post-restore checksum and compare with pre-incident checksum
psql "$SUPABASE_DB_URL" -t -A -c "SELECT md5(string_agg(t::text, '|' ORDER BY id)) FROM public.payments t;" > /tmp/payments_checksum_post.txt
echo "=== Pre-incident checksum: ==="
cat /tmp/payments_checksum_pre.txt
echo ""
echo "=== Post-restore checksum: ==="
cat /tmp/payments_checksum_post.txt
echo ""
echo "=== Checksums match? ==="
if [ "$(cat /tmp/payments_checksum_pre.txt)" = "$(cat /tmp/payments_checksum_post.txt)" ]; then
echo "✅ MATCH — payments table restored to exact pre-incident state"
else
echo "❌ MISMATCH — data is not identical"
fi
echo ""
echo "=== Incident log preserved? ==="
psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.incident_log;" 2>&1
echo ""
echo "=== Row-by-row verification against CSV backup ==="
psql "$SUPABASE_DB_URL" -c "\COPY (SELECT * FROM public.payments ORDER BY id) TO '/tmp/payments_post_restore.csv' WITH CSV HEADER" 2>&1
diff /tmp/payments_pre_incident.csv /tmp/payments_post_restore.csv
RESULT=$?
if [ $RESULT -eq 0 ]; then
echo "✅ EXACT MATCH — all 80 rows identical to pre-incident state"
else
echo "❌ DIFFERENCES DETECTED (diff exit: $RESULT)"
fi=== Pre-incident checksum: === 0dc7461b7b8bece10b61939f1ac53348 === Post-restore checksum: === 0dc7461b7b8bece10b61939f1ac53348 === Checksums match? === ✅ MATCH — payments table restored to exact pre-incident state === Incident log preserved? === id | ran_at | details ----+-------------------------------+-------------------------------------- 1 | 2026-07-24 15:43:02.782319+00 | payments corrupted by incident drill (1 row) === Row-by-row verification against CSV backup === COPY 80 ✅ EXACT MATCH — all 80 rows identical to pre-incident state
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