03 — Trigger Reconciliation Migration Readiness
03 — Trigger Reconciliation Migration Readiness (Track C)
Decision: OPERATOR_OWNER_PACKET_READY — NOT auto-applied. Trigger DDL is platform-owned; the gateway already neutralizes the only birth-relevant contradiction at runtime, so there is no production urgency.
Contradiction inventory (v_birth_trigger_reconciliation_plan)
| class | n | owner | severity | action |
|---|---|---|---|---|
| EXEMPT_BUT_TRIGGER_ACTIVE | 29 | platform | low (gateway already enforces) | optional DROP via reviewed migration; priority entity_labels, registry_changelog |
| DEFERRED_BUT_TRIGGER_ACTIVE | 50 | collection-owner | review | classify BIRTH_REQUIRED or BIRTH_EXEMPT; do NOT mass-disable |
| DUPLICATE_TRIGGER | 18 | platform | medium | DROP redundant sibling (keep one) via reviewed migration |
| REQUIRED_BUT_NO_TRIGGER | 5 | collection-owner | review | add trigger if truly managed, else reclassify |
No-go guard (v_birth_trigger_reconciliation_no_go_guard) — 3/3 PASS
- no trigger DDL applied this session (staged only) — true
- gateway neutralizes exempt triggers (births skipped) — true
- every contradiction has owner+action — true
Narrow scope chosen for the apply packet: the 18 DUPLICATE_TRIGGER tables
Each duplicate table has two AFTER INSERT … fn_birth_registry_auto triggers (birth_trigger_<t> and trg_birth_<t>), plus an unrelated trg_before_birth_gate_<t> (BEFORE, fn_birth_gate) that is kept.
TG_ARGV parity — why blind dedup is unsafe
Two tables have non-identical arguments between the duplicates:
table_registry:birth_trigger_table_registry=fn_birth_registry_auto()(no arg) vstrg_birth_table_registry('table_id'). Packet drops the no-arg one, keeps('table_id').workflows:birth_trigger_workflows= no-arg vstrg_birth_workflows('process_code'). Packet drops no-arg, keeps('process_code').
The apply packet ranks triggers to keep the arg-carrying sibling (v_birth_trigger_reconciliation_apply_packet), and rollback recreates the exact original (including the no-arg form). This is exactly why this must be a reviewed migration, not a mechanical "drop one of the pair."
Rehearsal — PROVEN safe & reversible (BEGIN..ROLLBACK on tasks)
triggers_before = 2
DROP birth_trigger_tasks
triggers_after_drop = 1 (kept trg_birth_tasks present = 1)
birth_before == birth_after_drop == 1,210,742 (DROP is birth-neutral)
ROLLBACK
triggers_restored = 2 (birth_trigger_tasks restored)
A [TRIGGER-GUARD] event trigger audited the DROP (writes to an exempt log → no birth). Nothing was committed.
Readiness summary (v_birth_trigger_reconciliation_migration_readiness)
duplicate_trigger=18, exempt_active=29, deferred_active=50, required_missing=5, no_go_guard_pass=true, trigger_ddl_applied_this_session=false, apply_decision=OPERATOR_OWNER_PACKET_READY.
Operator packet
/opt/incomex/docs/mcp-writes/birth-fix-next-cycle-2026-06-05/02_trigger_reconciliation_OPERATOR_PACKET.sql — wrapped in BEGIN…ROLLBACK by default (flip to COMMIT after the in-transaction verify queries return: each of the 18 tables shows exactly one birth trigger and birth_before==birth_after). Includes full rollback DDL.
Blocker: platform authority to COMMIT the migration. No engineering blocker.