Run #005 ✓ PASS (FIX-AND-SHIP applied)

Migration Audit — Confirmed Applied

2026-04-30 · 5 agents · internal-only subset · Next Chapter OS
Swarm verdict
Migrations 0010–0016 are fully applied. No Ewing action required.
PR #36 merged to main at 2026-04-30T22:52:27Z. The "nc_app lacks ALTER" warning was a false alarm — migrations run as postgres superuser, not the REST API role.
Live evidence
7
Deals live
16+
Tables created
4
Documents seeded
2
Clients seeded
2
Deal rooms

Deals confirmed in production

SlugSideStageCompany
hr-comsellsigned_contractHR.com Ltd
design-precastbuyfirst_meetingDesign Precast
capstone-constructionbuyfirst_meetingCapstone Construction Partners
aquasciencesellclosed_lostAquaScience
wieser-concretebuyclosed_lostWieser Concrete
air-controlsellclosed_lostAir Control
springer-floorsellclosed_lostSpringer Floor
Why the warning was a false alarm

Two actors — two different moments

The commit warning says "nc_app lacks ALTER privileges." This is true — but nc_app is the PostgREST REST API role. It has restricted read-only access by design, and it never touches schema DDL. Migrations run via SUPABASE_POSTGRES_CONN — a direct postgres superuser connection string stored in Doppler. The ALTER TABLE statements ran as postgres superuser, succeeded, and the nc_app warning fires afterward as a routine runtime observation.

Old columns + new columns on deals table — correct by design

The live deals table has both legacy columns (company_name, status, deal_type) and new schema columns (slug, side, stage, client_company, etc.). This is the expected output of migration 0010's additive strategy: it uses ADD COLUMN IF NOT EXISTS rather than DROP + CREATE. The old columns are inert — no current code reads them. They will be removed in migration 0017.

audit-quality correction (FIX-AND-SHIP)

The synthesis initially conflated public.schema_migrations (the custom 0004 ledger) with the Supabase CLI's internal supabase_migrations.schema_migrations table. These are two different systems. apply-deal-tracker-migrations.sh uses supabase migration repair --status applied which writes to the Supabase CLI internal table. migrate.sh (the newer runner) uses raw psql and writes to neither. The gap: public.schema_migrations (custom 0004) is not written to by either script.

Three open items (none block current operation)
PriorityItemOwner
P2 public.schema_migrations (custom 0004 ledger) not written to by migrate.sh — seed migrations could re-run and overwrite live edits. Fix: add INSERT to ledger after each psql call. Claude drafts, Ewing applies
P2 Orphan columns (company_name, status, deal_type) on deals table. Write migration 0017 to DROP them — before next major schema change cycle. Claude drafts, Ewing applies
P3 iss_0094: 11,058-row contacts table has duplicate emails — uniq_contacts_email cannot be created. Claude produces dedup query; Ewing decides strategy. Ewing decision
Phase 1 agents
📖
storyteller T2
Named the pattern: "self-cancelling alarm." Warning was written mid-fix, resolved within same session. Identified worktree isolation trap — vigorous-ritchie-899943 only has migrations 0001–0009.
🏗️
architect
Schema verdict: ACCEPTABLE. Identified sha256 drift blindspot in migrations runner. Clarified schema_migrations vs Supabase CLI internal table distinction.
🏈
quarterback T2
Key correction: PR #36 was MERGED (not open) at 22:52 UTC. Conductor briefing was stale. Sequenced next 6 plays with Ewing-required vs Claude-owned split.
👂
listener
Read Ewing's real concern: "is the app trustworthy?" not "is the migration applied?" Drafted the one-line answer. Flagged 2 unstaged .gdoc files in worktree.
📝
debrief
Named the "two-actor problem" framework for future runs. Proposed swarm_migrations log table. Wrote upgrade-signals for Phase 0 checklist.
Currency events — Run 005
From → ToScoreWhy
storyteller → conductor+30 (3×10)nc_app "self-cancelling alarm" framing — changed how conductor reads privilege warnings
storyteller → architect+15 (3×5)Legacy column families coexist by design — gave architect the schema-read audit directive
quarterback → conductor+30 (3×10)PR #36 state correction: OPEN → MERGED. Critical fact preventing re-work
debrief → conductor+15 (3×5)"Live data = applied" rule — changes primary migration audit indicator
debrief → architect+15 (3×5)Two-actor disambiguation framework — reusable model for future runs
listener → conductor+10 (2×5)One-line Ewing answer drafted, used verbatim
architect → all+10 (2×5)sha256 drift blindspot in migration runner — medium priority improvement
Score impacts: storyteller +45→235 (T2) · quarterback +30→130 (T2) · debrief +30→115 (T2 🆕) · architect +10→105 (T2 🆕) · listener +10→100 (T2 🆕)
Upgrade signals for swarm-upgrade
[upgrade-signal:gap]
Two-actor disambiguation missing from Phase 0 migration checklist — postgres superuser (apply) vs nc_app REST role (runtime) confusion is a recurring false-negative pattern.

[upgrade-signal:gap]
"Live data = applied" rule missing from Phase 0 — direct DB row count is the primary migration status indicator, stronger than any log line or privilege warning.

[upgrade-signal:gap]
migrate.sh does not write to public.schema_migrations — seed re-runs can overwrite live edits silently.