KB-11E4
RS3C-09 — Rerun: Trigger Inventory Reconciliation (C3) — 2026-06-21
7 min read Revision 1
rs3ctrigger-inventorypg_triggerC3reconciliationrerun2026-06-21
RS3C-09 — Rerun: Trigger Inventory Reconciliation (Codex C3) — 2026-06-21
Macro: RS3C (Mục tiêu F, reruns RS3B-08) · Deliverable: 09 of 13
Codex C3: RS3B-08 claimed 14 dot_tools triggers (13 enabled + 1 disabled) but listed only 13 names. Reconcile from pg_catalog.pg_trigger.
Date: 2026-06-21 · read-only · 0 mutations
Source: pg_catalog.pg_trigger JOIN pg_class/pg_proc, db directus, 2026-06-21. Raw result = 17 rows (13 user + 4 internal FK).
1. Raw trigger result table (verbatim from pg_catalog.pg_trigger)
1a. User (non-internal) triggers — tgisinternal = false — 13 total
| # | tgname | enabled | timing | events | function |
|---|---|---|---|---|---|
| 1 | birth_trigger_dot_tools |
enabled | AFTER | INSERT | fn_birth_registry_auto |
| 2 | trg_auto_code_dot_tools |
enabled | BEFORE | INSERT | gen_code_dot_tools |
| 3 | trg_before_birth_gate_dot_tools |
enabled | BEFORE | INSERT | fn_birth_gate |
| 4 | trg_birth_dot_tools |
enabled | AFTER | INSERT | fn_birth_registry_auto |
| 5 | trg_context_pack_dot_register |
enabled | AFTER | INSERT UPDATE | fn_context_pack_on_dot_register |
| 6 | trg_count_dot_tools |
disabled | AFTER | INSERT DELETE UPDATE TRUNCATE | refresh_registry_count |
| 7 | trg_desc_guard_dot_tools |
enabled | BEFORE | INSERT UPDATE | fn_description_birth_guard |
| 8 | trg_desc_provenance_dot_tools |
enabled | AFTER | INSERT | fn_auto_label_provenance |
| 9 | trg_label_assign_dot_tools |
enabled | AFTER | INSERT UPDATE | fn_auto_label_assignment |
| 10 | trg_normalize_dot_filepath |
enabled | BEFORE | INSERT UPDATE | fn_normalize_dot_filepath |
| 11 | trg_refresh_dot_count |
enabled | AFTER | INSERT DELETE UPDATE | fn_refresh_dot_count |
| 12 | trg_refresh_orphan_dot |
enabled | AFTER | INSERT DELETE UPDATE | trg_fn_refresh_orphan_dot |
| 13 | trg_validate_dot_origin_dot_tools |
enabled | BEFORE | INSERT UPDATE | fn_validate_dot_origin |
User triggers: 13 total = 12 enabled + 1 disabled (trg_count_dot_tools).
1b. Internal constraint triggers — tgisinternal = true — 4 total (FK enforcement, not governance)
| # | tgname | enabled | timing | events | function |
|---|---|---|---|---|---|
| 14 | RI_ConstraintTrigger_a_80056 |
enabled | AFTER | DELETE | RI_FKey_noaction_del |
| 15 | RI_ConstraintTrigger_a_80057 |
enabled | AFTER | UPDATE | RI_FKey_noaction_upd |
| 16 | RI_ConstraintTrigger_c_62435 |
enabled | AFTER | INSERT | RI_FKey_check_ins |
| 17 | RI_ConstraintTrigger_c_62436 |
enabled | AFTER | UPDATE | RI_FKey_check_upd |
2. Count reconciliation
| Field | Value |
|---|---|
claimed_count (RS3B-08) |
14 |
listed_count (RS3B-08 names) |
13 |
actual_pg_catalog_count — user/governance triggers (tgisinternal=false) |
13 |
actual_pg_catalog_count — internal FK constraint triggers (tgisinternal=true) |
4 |
actual_pg_catalog_count — all rows |
17 |
| enabled user triggers | 12 |
| disabled user triggers | 1 (trg_count_dot_tools) |
difference |
claimed 14 vs actual-user 13 = +1 over-count |
resolution |
No 14th governance trigger exists. RS3B-08's "14 = 13 enabled + 1 disabled" mis-stated enabled as 13; the truth is 13 user triggers = 12 enabled + 1 disabled. The 13 names RS3B listed are the complete set. There is no missing trigger; the arithmetic was wrong, not the list. |
TRIGGER_INVENTORY = RECONCILED → verdict is NOT RS3C_HOLD_TRIGGER_INVENTORY_UNRECONCILED.
3. Side-effect classification (all 13 user triggers)
| Trigger | Side-effect class | Registration impact |
|---|---|---|
trg_before_birth_gate_dot_tools (fn_birth_gate) |
GATE (BEFORE INSERT) | may block/permit the insert — a pre-birth gate |
trg_validate_dot_origin_dot_tools (fn_validate_dot_origin) |
VALIDATION (BEFORE) | validates DOT origin before insert |
trg_auto_code_dot_tools (gen_code_dot_tools) |
MUTATION of NEW (BEFORE) | may override registrar's code (RS3C-03 B13) |
trg_normalize_dot_filepath (fn_normalize_dot_filepath) |
MUTATION of NEW (BEFORE) | normalizes file_path → explains dedup mismatch (RS3C-03 B8) |
trg_desc_guard_dot_tools (fn_description_birth_guard) |
VALIDATION/MUTATION (BEFORE) | guards/sets description |
birth_trigger_dot_tools + trg_birth_dot_tools (fn_birth_registry_auto) |
CROSS-TABLE WRITE (AFTER) | birth-registry side write (two triggers, same fn) — writes elsewhere, not a 2nd dot_tools row |
trg_desc_provenance_dot_tools (fn_auto_label_provenance) |
CROSS-TABLE/LABEL (AFTER) | provenance labeling |
trg_label_assign_dot_tools (fn_auto_label_assignment) |
CROSS-TABLE/LABEL (AFTER) | label assignment |
trg_refresh_dot_count (fn_refresh_dot_count) |
COUNT REFRESH (AFTER) | recomputes a count |
trg_refresh_orphan_dot (trg_fn_refresh_orphan_dot) |
COUNT/ORPHAN REFRESH (AFTER) | recomputes orphan set |
trg_count_dot_tools (refresh_registry_count) |
COUNT REFRESH — DISABLED | inert |
trg_context_pack_dot_register (fn_context_pack_on_dot_register) |
ACTIVATION / NOTIFY (AFTER INSERT UPDATE) | the activation surface — see §4 |
4. Activation-risk analysis retained (trg_context_pack_dot_register)
- Fires AFTER INSERT OR UPDATE via
fn_context_pack_on_dot_register(this rerun confirms it triggers on UPDATE too, not only INSERT). - The registrar inserts with
status:"active"(RS3C-03 B12), so each registered row trips this trigger → context-pack notification for watched tiers. Mass registration ⇒ mass activation notifications (G7 activation side-effect). - Closed-at-registration obligation stands: a hardened registrar must register inert (non-active) so this trigger does not fire on registration, and must make no gate/wiring change.
5. New adversarial case
TRIGGER_INVENTORY_COUNT_MISMATCH— any inventory whose stated count ≠ enumerated names must fail-closed and be re-derived frompg_catalog.pg_trigger(distinguishingtgisinternal), as done here. (Added to RS3C-10.)
6. Status
- Deliverable:
TRIGGER_INVENTORY_RECONCILED— 13 user triggers (12 enabled + 1 disabled) + 4 internal FK; no missing trigger; RS3B over-counted by one. - Activation surface confirmed (
trg_context_pack_dot_register, INSERT+UPDATE); closed-at-registration retained. - Registration gate unchanged:
REGISTRATION_HOLD·CAN_PROCEED = NO.