Files
zeekay 5049a97947 fix(migrations): build the tables the ledger says were already built
Eleven model tables do not exist in production while the migrations that
create them are recorded as applied. All eleven come from plain CreateModel
operations, so the rows were faked past a failure rather than run.

Nothing reports this on its own. A migration recorded as applied cannot run
again, `migrate` says there is nothing to do, and `migrate --check` passes,
because all three read django_migrations rather than the schema. Meanwhile
every query against these models raises UndefinedTable, which is why canvas,
workflows, replay vision and the Streamlit apps are dead in production.

CreateTableIfNotExists and AddColumnIfNotExists build what state already
carries and skip what is already there, taking no field definition of their
own: the shape comes from migration state, the same source the original
operation was written from. That makes one migration both a repair on a
database that was faked past and a no-op where the work was really done, and
makes it safe under bin/migrate's retry. Neither reverses, because the
reverse would drop something the migration may not have created.

insights_flow is renamed rather than recreated. The squashed baseline creates
InsightsFlow as insights_flow; workflows/0007 then adopts the model declaring
insights_hogflow, and adopts it state-only, so nothing ever renames the table.
That leaves an empty insights_flow nobody reads -- every reader, including the
nodejs workflow tests, uses insights_hogflow -- holding the index and
constraint names the real table needs. Renaming carries those indexes across,
which is why it beats dropping and recreating: they are the ones the model
asks for. It arrives with the baseline's shape, so five columns later
migrations added are added here too.

Verified against a clone of production's schema and migration ledger (485
tables, 2060 rows): migrate exits 0, no model table or column is missing
afterwards, and a second run applies nothing.
2026-08-08 20:39:49 -07:00
..