From 8f5630310c2db8063fcfd9890aaaf88373329853 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 2 May 2026 02:36:31 +0000 Subject: [PATCH 1/2] Add substrate_cids ADD COLUMN migration for existing deployments The Hippius merge added substrate_cids to CREATE TABLE IF NOT EXISTS, but pre-existing deployments skip the create and never get the column, so SCHEMA_INDEX_DDL's GIN(substrate_cids) crashes with UndefinedColumnError. https://claude.ai/code/session_01XTnxjCgAJE6wwvW2U7cFRJ --- shared/pg_schema.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared/pg_schema.py b/shared/pg_schema.py index de4d58c..32fa1f9 100644 --- a/shared/pg_schema.py +++ b/shared/pg_schema.py @@ -41,6 +41,11 @@ -- ``shared.challenge.generate_challenge`` and can exceed INT32's 2.1B max. -- Widen existing deployments to BIGINT; no-op if already BIGINT. ALTER TABLE experiments ALTER COLUMN round_id TYPE BIGINT; +-- Migration (TEN-240): substrate_cids was added to the CREATE TABLE above +-- after deployments already had an experiments table, so the IF NOT EXISTS +-- table-create is a no-op and the column is missing. Add it explicitly. +ALTER TABLE experiments + ADD COLUMN IF NOT EXISTS substrate_cids JSONB NOT NULL DEFAULT '[]'; """ SCHEMA_INDEX_DDL = """ From 8c0b65c92d7dd77bfc3b564f7ce0afea8de1bc84 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 2 May 2026 02:42:11 +0000 Subject: [PATCH 2/2] Add 003 substrate_cids bootstrap-safety migration Counterpart to the SCHEMA_TABLE_DDL fix in 8f56303. Migration 002 adds the column, but the runner only fires AFTER init_schema(), so legacy deployments crash on the GIN index before 002 can apply. This migration re-asserts the column + index idempotently as defense-in-depth and satisfies the "schema change requires migration" CI policy. https://claude.ai/code/session_01XTnxjCgAJE6wwvW2U7cFRJ --- .../003_substrate_cids_bootstrap_safety.sql | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 database/migrations/003_substrate_cids_bootstrap_safety.sql diff --git a/database/migrations/003_substrate_cids_bootstrap_safety.sql b/database/migrations/003_substrate_cids_bootstrap_safety.sql new file mode 100644 index 0000000..07fb4b9 --- /dev/null +++ b/database/migrations/003_substrate_cids_bootstrap_safety.sql @@ -0,0 +1,41 @@ +-- Bootstrap-order safety net for substrate_cids. +-- +-- Problem this records: migration 002_substrate_cids.sql adds the +-- substrate_cids column + GIN index, but the migration runner is +-- invoked AFTER ``PgExperimentStore.init_schema()`` in +-- ``database/neuron.py``. ``init_schema`` runs SCHEMA_INDEX_DDL from +-- ``shared/pg_schema.py``, which contains +-- CREATE INDEX IF NOT EXISTS idx_substrate_cids +-- ON experiments USING GIN(substrate_cids); +-- On legacy deployments that booted before TEN-240 the column does not +-- yet exist when SCHEMA_INDEX_DDL runs, so init_schema crashes with +-- ``UndefinedColumnError: column "substrate_cids" does not exist`` +-- before migration 002 ever gets a chance to apply. +-- +-- The crash is fixed in ``shared/pg_schema.py`` by an idempotent +-- ``ALTER TABLE ... ADD COLUMN IF NOT EXISTS substrate_cids`` placed in +-- SCHEMA_TABLE_DDL (executed before SCHEMA_INDEX_DDL within the same +-- ``init_schema`` call). This file is the migration counterpart of that +-- fix: an idempotent re-assertion that the column + index exist, so any +-- replica restored from a snapshot taken between TEN-240 and this fix +-- catches up without manual intervention. +-- +-- Same table-existence guard as the other migrations: on a fresh deploy +-- the migration runner runs against an empty schema (CI's "Migrations +-- apply to empty DB" job), so the body must be a no-op when the +-- experiments table doesn't exist yet. + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 + FROM information_schema.tables + WHERE table_schema = 'CURRENT_SCHEMA' + AND table_name = 'experiments' + ) THEN + ALTER TABLE CURRENT_SCHEMA.experiments + ADD COLUMN IF NOT EXISTS substrate_cids JSONB NOT NULL DEFAULT '[]'; + CREATE INDEX IF NOT EXISTS idx_substrate_cids + ON CURRENT_SCHEMA.experiments USING GIN (substrate_cids); + END IF; +END $$;