Branch B — IU DOT Wrapper Completeness (1 live + 7 packs) (2026-05-29)
Branch B — IU DOT Wrapper Completeness
Doc 02 (2026-05-29)
1. DOT execution model (discovered live)
There is no generic DOT dispatcher. The IU DOT functions are: fn_dot_iu_command_log (fail-closed audit logger — refuses any command not in dot_iu_command_catalog), fn_dot_iu_operator_runtime_enabled, fn_dot_iu_runtime_lease_acquire/release. A DOT is "wrapped" by: (1) registering it in dot_iu_command_catalog (so the fail-closed logger accepts it) + (2) the caller invoking the target function then calling fn_dot_iu_command_log to write the dot_iu_command_run audit row. The catalog has no triggers, only category CHECK ∈ {collection,piece,lifecycle,read,health} + PK on command_name. ⇒ a read-only registration is a safe additive INSERT and is itself the meaningful wrapper for read ops.
2. Live change — dot_iu_reconstruct_source registered (read-only)
INSERT INTO dot_iu_command_catalog (command_name, category, mutating, reversible, target_functions, registered_at)
VALUES ('dot_iu_reconstruct_source','read', false, true, ARRAY['fn_iu_reconstruct_source'], now());
Dress-rehearsed (BEGIN..ROLLBACK, count 53→54) then committed. Now reconstruct calls are catalog-recognised and auditable. Catalog 53 → 54.
3. Implementation packs for the 7 mutating wrappers (deferred — gated, need paired Tier-A)
Each is a dot_iu_command_catalog row + the caller calling the (existing) target fn under its gate + fn_dot_iu_command_log. Mutating wrappers were not auto-registered this session because they require a Tier-A companion and gate discipline (and the relevant runtime gates are intentionally closed).
| Proposed DOT | Target fn (exists) | category | mutating | Gate | Paired Tier-A | Notes |
|---|---|---|---|---|---|---|
dot_iu_emit |
fn_iu_emit_event / fn_iu_piece_emit_event |
lifecycle | true | piece_event_runtime.emit_enabled |
dot_iu_emit_verify (read outbox) |
refs-only payload (Đ45 signal-not-data) |
dot_iu_route_worker_run |
fn_iu_route_worker_run |
lifecycle | true | routes master gate | dot_iu_route_status |
dry_run honored |
dot_iu_dlq_replay |
fn_iu_route_dead_letter_replay |
lifecycle | true | routes master + queue.dlq.replay_enabled |
dot_iu_dlq_inspect (read v_iu_route_dead_letter_open) |
replay never bypasses Đ32 |
dot_iu_relation_assert |
(iu_relation write path) | lifecycle | true | none; ABox auto-rules | dot_iu_kg_edge_audit (existing, read) |
provenance-or-quarantine (Đ39 A8); honor kg_auto_approve_rules |
dot_iu_enact |
fn_iu_enact |
lifecycle | true | never-flip iu_enact.allow_no_review_decision stays false; requires review_decision_id |
dot_iu_enact_precheck |
no agent self-mint of Đ32 |
dot_iu_capture_status |
reads inbound-capture results | read | false | none | (self) | inbound capture itself is trigger-driven (trg_iu_sql_in_iu_sql_link) |
dot_iu_vector_reindex / dot_iu_vector_verify |
fn_iu_vector_sync_record_v2 / Qdrant read |
health | true/false | iu_core.vector_sync_enabled (never-flip, stays false) |
each other | see Doc 04; reindex must NOT write vector in pilot |
Coverage after this session: read-only reconstruct closed; ~16/22 core ops now wrapped. The 7 above are specified and one INSERT-per-row away (plus Tier-A companions) when their gates/owners are ratified.
4. Why not register the mutating rows now
- Đ35 philosophy: every Tier-B needs a Tier-A companion; registering Tier-B without its check is half-governance.
- Their runtime gates are deliberately closed; a registered-but-ungated mutating DOT could mislead. Safer to land them together with Tier-A in a dedicated macro (M2 from the prior audit), under APR.