KB-521A

03 — Trigger Reconciliation Migration Readiness

4 min read Revision 1

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) vs trg_birth_table_registry('table_id'). Packet drops the no-arg one, keeps ('table_id').
  • workflows: birth_trigger_workflows = no-arg vs trg_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.

Back to Knowledge Hub knowledge/dev/reports/architecture/birth-fix-next-cycle-verification-trigger-reconciliation-rp-hygiene-2026-06-05/03-trigger-reconciliation-readiness.md