KB-3EA1

IU Mutation-Safety Foundation for d/e/f-enable — Live Apply (2026-05-28)

31 min read Revision 1
iumutation-safetybounded-gate-protocollive-apply2026-05-28C4

IU Mutation-Safety Foundation for d / e / f-enable — Live Apply (2026-05-28)

Macro: IU_MUTATION_SAFETY_FOUNDATION_FOR_D_E_AND_F_ENABLE_LIVE_APPLY_150000X Execution class: mixed C4 + C5 (live gate-protocol implementation + substrate-readiness assessment). Builds the reusable mutation-safety layer that every mutating IU test (d, e, f-enable) depends on. No split/merge, no compose, no event emission, no inbound capture, no link enable, no gate left open. Apply channel: SSH workflow_admindocker exec -i postgres psql -U workflow_admin -d directus. Read-proof channel: MCP query_pg (role context_pack_readonly). Companion appendix: iu-mutation-safety-foundation-for-d-e-f-enable-live-apply-appendix-2026-05-28.md. Precursors: iu-b-c-f-additive-dot-wrapper-and-harness-live-apply-2026-05-28.md, iu-b-to-f-execution-readiness-refactor-2026-05-28/ (Prompt 4 = M-D).

1. Final status — PASS

  • Branch A — Bounded gate protocol: IMPLEMENTED + self-tested live. PASS.
  • Branch B — Review-decision readiness: VERIFIED + correctly DEFERRED (no object needed; split/merge already wired). Author-ready Prompt for test d.
  • Branch C — Event-contract readiness: VERIFIED + correctly DEFERRED (registration unvalidatable without emit; delivery already route-scoped/fail-closed). Author-ready Prompt for test e.
  • Branch D — Rollback / fail-closed: PROVEN for every live object; the rollback's own fail-closed guard demonstrated.
  • Branch E — Next execution prompts: 3 paste-ready prompts (§13).

PASS rationale: the one branch that is safe to apply now (the gate protocol) was implemented and proven; the two branches that cannot be safely applied without crossing a forbidden line (fabricating a governance review_decision; registering unexercisable event types) are precisely classified and handed off author-ready. No gate is open; both never-flip keys remain false; no forbidden action taken.


2. Source matrix

# Source Found Used for
S1 iu-b-c-f-additive-dot-wrapper-and-harness-live-apply-2026-05-28.md + appendix local Baseline (catalog 47 / run 55 / schema 1,617,882 B); the fail-closed logger contract; channel pattern
S2 iu-b-to-f-execution-readiness-refactor-2026-05-28/02,03,04 local M-D spec (Prompt 4), gate/law matrix, 8-gate inventory + never-flip rule, the 6 authority prompts
S3 Live DB directus — dot_config, pg_proc bodies, cutter_governance, event_type_registry, route layer live The real substrate (corrected several prompt assumptions — see §14)
S4 Master Design Rev5; laws Hiến pháp / Đ0-G / Đ7 / Đ30 / Đ31 / Đ32 / Đ35 / Đ38-39 / Đ45 KB/auto-memory Owner-law mapping, never-flip absolutes, refs-only payload, register-before-emit
S5 Prompt standard 100000x v1.3 auto-memory PASS/PARTIAL/BLOCKED, underload rule, evidence requirements

Source gaps (non-blocking): items 3 (iu-bcf-dot-pass-gpt-next-mutation-safety-foundation-2026-05-28.md) and 4 (…command-pack…/08-bounded-gate-protocol.md) of the mission read-list were not present at the literal local paths; the bounded-gate baseline they carry is reproduced in the refactor pack 02/04 (M-D spec) and auto-memory. Laws live under iu-cutter-build/repo/iu-cutter/knowledge/dev/laws/ (not top-level knowledge/dev/laws/); their content was carried in auto-memory and the gate-law matrix. No gate/authority decision depended on a missing copy.


3. Hard Gate 0 — result (PASS)

Check Result
Host contabo VPS (ssh contabo reaches host; container postgres Up 5 weeks (healthy))
Container postgres
Database directus
Read channel query_pg = context_pack_readonly @ directus, 172.19.0.3/32, PG 16.13
Write channel (SELECT-first) docker exec -i postgres psql -U workflow_admin -d directuscurrent_user=workflow_admin, current_database=directus
Write probe (BEGIN/ROLLBACK) UPDATE dot_config SET value='true' WHERE key='iu_core.composer_enabled' → in-TX trueROLLBACKfalse (write + reversibility proven on the real target table, persisting nothing)
Rollback path writable /tmp/*.sql authored before apply; pg_dump --schema-only works
Snapshot taken gates, catalog/run counts, event_type_registry, review-decision tables, split/merge tables, route/DLQ tables — §4
Rollback prepared before change /tmp/rollback_gate_protocol.sql authored before apply

No no-go condition triggered.


4. Live baseline snapshot (pre-apply)

Gates (dot_config) — all at safe defaults:

Gate Value Class
iu_core.composer_enabled false governable
iu_core.structure_ops_enabled false governable
iu_core.delivery_enabled false governable
iu_core.three_axis_auto_refresh_enabled false governable
iu_core.operator_runtime_enabled false governable
queue.job_substrate.enabled false governable
queue.dlq.replay_enabled false governable
iu_enact.allow_no_review_decision false NEVER-FLIP
iu_core.vector_sync_enabled false NEVER-FLIP

Also observed (delivery scoping): iu_core.delivery_live_routes = "" (empty), iu_core.routes_master_enabled=true, iu_core.route_worker_enabled=true, piece_event_runtime.emit_enabled=false, piece_event_runtime.dry_run_only=true.

Counts: dot_iu_command_catalog=47, dot_iu_command_run=55, event_type_registry=31 (16 domain iu, 6 piece, 5 staging, 4 system), cutter_governance.review_decision=4, iu_split_set=0, iu_merge_set=0, iu_route_dead_letter=0, iu_outbound_route=15, iu_sql_link=3 (all enabled=false). Schema pg_dump --schema-only = 1,617,882 bytes.


5. Branch A — Bounded gate protocol (IMPLEMENTED, PASS)

Gap found: the DB had STABLE reader functions (fn_iu_composer_enabled, fn_iu_structure_ops_enabled, fn_iu_delivery_enabled, fn_iu_vector_sync_enabled, …) but no open/close/verify/watchdog writer protocol and no gate-transition ledger. That is exactly the M-D primitive every mutating test needs.

Installed (additive footprint):

Object Kind Notes
public.iu_gate_transition table (+1 index) ledger: gate_key, action∈{open,close,watchdog_close}, prev/new value, approval_id, ttl_seconds, expires_at, actor, reason, run_id, created_at
fn_iu_gate_open(gate,approval_id,actor,reason,ttl) VOLATILE opens ONE governable gate for a bounded TTL; fail-closed
fn_iu_gate_close(gate,actor,reason) VOLATILE forces a gate to safe default false
fn_iu_gate_verify_closed(gate?) STABLE (read) reports every governable+never-flip gate; all_safe proof
fn_iu_gate_watchdog(actor) VOLATILE force-closes any governable gate whose open window expired/orphaned
catalog dot_iu_gate_open/close/watchdog rows category=health, mutating=true, reversible=true
catalog dot_iu_gate_verify_closed row category=read, mutating=false, reversible=true

Fail-closed semantics (enforced in code, proven in self-test):

  1. Never-flip refusaliu_enact.allow_no_review_decision and iu_core.vector_sync_enabled raise insufficient_privilege; the gate is never touched. Error text: "supply a real review_decision_id instead of bypassing review."
  2. Non-governable deny — any key not in the 7-gate whitelist is refused (unknown → deny, not allow).
  3. Approval required (Điều 32)NULL approval_id raises check_violation; no mutating gate opens without one.
  4. TTL boundttl_seconds ∈ (0, 3600]; every open records expires_at.
  5. Watchdog — any governable gate left true past its window is force-closed; safety net for a crashed test.
  6. Verify-closed — single read returns all_safe over all 9 gates; mandatory macro-end proof.

Audit (Điều 31 via Điều 35): every open/close/watchdog writes both an iu_gate_transition row and a dot_iu_command_run row via canonical fail-closed logger fn_dot_iu_command_log (mutating=true). verify_closed is read-only and writes nothing.

Self-test (BEGIN/ROLLBACK — appendix A5): opened composer (approved) → verified governed-not-closed → refused both never-flip keys (values stayed false) → refused non-governable key → refused null-approval → closed composer → watchdog force-closed an expired delivery window → final all_safe=trueROLLBACKledger_rows=0, gates false, run_count=55. Every effect reverted; the exercise persisted nothing while the protocol persists.

Committed end-state: fn_iu_gate_verify_closed()all_safe=true, all_governed_closed=true, never_flip_intact=true. Protocol installed but dormant (iu_gate_transition=0 rows, dot_iu_command_run=55 unchanged): no gate opened in persisted state.


6. Branch B — Review-decision readiness (VERIFIED + DEFERRED)

Where review decisions live: cutter_governance.review_decision (RO role denied column/row visibility — read via workflow_admin). 4 rows exist. PK = review_decision_id (uuid).

Shape (heavy governance object — 17 NOT-NULL columns): governance_event_kind, manifest_id (FK→manifest_envelope.envelope_id), manifest_version, review_scope, status, verdict, findings (jsonb), reviewer_class, reviewer_identity (jsonb), risk_class_assessment, decision_at, decided_by, cross_signed_by_dot_verifier (bool), version, created_at, updated_at; plus FK (manifest_id, manifest_unit_local_id) → manifest_unit_block.

Is the wiring already there? — YES. fn_iu_piece_split and fn_iu_piece_merge (both SECURITY DEFINER, with p_dry_run) already:

  • reject a NULL p_review_decision_id (status=invalid_input … next_action=record_review_decision_first);
  • FK-probe cutter_governance.review_decision for existence (status=review_decision_not_found if absent);
  • do not consult allow_no_review_decision at all — the id is hard-required unconditionally.

Conclusion: No function wiring is missing. The "row-builder never committed" (TD-P1) is precisely: a valid review_decision is manifest-bound (FK to manifest_envelope + manifest_unit_block) and is a Điều 32 approval artifact (verdict + reviewer identity + cross-sign). Fabricating one is a governed-mutation act, out of scope for a safety-foundation macro (forbidden: no split/merge; fabricating governance approvals is itself unsafe). Therefore no object was created here — a privileged helper with no consumer (split already probes internally) would be unjustified surface.

Safe path for test d (Prompt 5, §13.1): under workflow_admin, create a test manifest_envelope + manifest_unit_block + review_decision bound to cloned test IUs, then pass that real review_decision_id to fn_iu_piece_split/merge — never flip allow_no_review_decision.


7. Branch C — Event-contract readiness (VERIFIED + DEFERRED)

event_type_registry shape (corrected): columns event_domain, event_type, event_stream, delivery_lane, default_severity, description, active, created_at. No JSON-schema column and no compat_mode column (the Prompt-6 assumption of "JSON schema, compat_mode=forward" does not match the live table). Types keyed by (event_domain, event_type), not a dotted single string.

Already registered (trigger-out for structure ops needs nothing new): 16 iu-domain types incl. structure_piece_split, structure_pieces_merged, structure_op_applied, structure_child_added, piece_added_to_collection, piece_removed_from_collection, piece_reordered; 6 piece-domain (created/updated/split/merged/retired/superseded).

Emission is multi-gated + fail-closed (from fn_iu_emit_event / fn_iu_piece_emit_event): (1) master gate fn_iu_core_routes_enabled(); (2) runtime gate piece_event_runtime.emit_enabled (false) + dry_run_only; (3) registry lookup — unknown/inactive (domain,type) returns NULL; (4) trigger trg_event_outbox_type_validate rejects any (domain,type) absent/inactive and requires event_stream/delivery_lane to MATCH the registry exactly.

Delivery is triple-gated + route-scoped (from fn_iu_route_deliver): (1) fn_iu_delivery_enabled() master kill-switch; (2) route must be registered in iu_outbound_route (15 rows); (3) per-route allowlist dot_config.iu_core.delivery_live_routes (currently EMPTY) — a route_code missing from this CSV is refused; this is the route-scoping mechanism (answers Prompt-6 R-B). With the allowlist empty, even an open delivery_enabled delivers nothing; (4) only ONE internal target supported (sql_function / fn_iu_structure_consumer); every external/network target refused.

Conclusion: registration could be applied (additive + reversible), but the lifecycle types the prompt names (route.delivered, route.failed, a trigger-in type) have no emitter in live code (fn_iu_route_deliver returns void and does not emit a delivery event). Registering rows that cannot be exercised in a no-emit macro is speculative. Deferred to Prompt 6 with the exact live contract documented. Trigger-out for d-structure events is already registered; what remains for test e is the trigger-in capture event + (optionally) route lifecycle events, to be registered and immediately exercised under Prompt 6's bounded delivery gate.


8. Rollback / fail-closed proof (Branch D)

Object Backup Rollback script Verified
iu_gate_transition + index pg_dump --schema-only (1,617,882 B pre) DROP TABLE in /tmp/rollback_gate_protocol.sql dry-run
4 gate functions schema dump DROP FUNCTION … (exact signatures) dry-run
4 catalog rows row snapshot DELETE … WHERE command_name IN (…) dry-run
any audit rows n/a (0 persisted) DELETE FROM dot_iu_command_run WHERE command_name IN (…)
  • Rollback dry-run (COMMIT→ROLLBACK): DELETE 0 (run) + DELETE 4 (catalog) + 4 DROP FUNCTION + DROP TABLE + assert catalog=47 / 0 fns / no table → ROLLBACK. Protocol confirmed still installed afterward (catalog=51, gatefns=4). Reverts to the exact baseline.
  • Rollback fail-closed guard: refuses to run if any governable gate is open. Proven: opened structure_ops in-TX → guard detected 1 gate(s) open → would REFUSE → ROLLBACK left it false. You cannot accidentally drop the watchdog while a gate is open.
  • Failed-branch safety: Branches B and C deliberately created nothing — zero unsafe state to roll back.

9. Before/after object diff

Before After Δ
Tables (public) iu_gate_transition +1 (+1 index, +1 comment)
Functions (gate protocol) 0 fn_iu_gate_open (v), fn_iu_gate_close (v), fn_iu_gate_verify_closed (s), fn_iu_gate_watchdog (v) +4
dot_iu_command_catalog rows 47 51 +4
pg_dump --schema-only bytes 1,617,882 1,628,568 +10,686

Nothing else changed. No existing object altered (reader functions, split/merge, emit, route layer untouched).


10. Before/after row-count delta

Table Before After Δ
information_unit 216 216 0
iu_three_axis_envelope 216 216 0
iu_metadata_tag 536 536 0
iu_split_set 0 0 0
iu_merge_set 0 0 0
iu_sql_link 3 3 0
event_type_registry 31 31 0
event_outbox (unchanged) (unchanged) 0
iu_route_attempt / iu_route_dead_letter 68 / 0 68 / 0 0
cutter_governance.review_decision 4 4 0
dot_iu_command_catalog 47 51 +4
dot_iu_command_run 55 55 0 (self-test rolled back; protocol dormant)
iu_gate_transition (new) 0 0 rows

Every IU-data / governance / event / route table delta = 0. Only persisted change is the additive gate-protocol footprint.


11. Changed objects list

Created (persisted): public.iu_gate_transition (+ index ix_iu_gate_transition_gate + comment); public.fn_iu_gate_open, fn_iu_gate_close, fn_iu_gate_verify_closed, fn_iu_gate_watchdog; catalog rows dot_iu_gate_open, dot_iu_gate_close, dot_iu_gate_watchdog, dot_iu_gate_verify_closed. Artifacts: migration /tmp/mig_gate_protocol.sql md5 be980c7e3ef77886494e532905811925; rollback /tmp/rollback_gate_protocol.sql md5 2d62a732884b238ea49d62e7763eb9da; self-test /tmp/selftest_gate_protocol.sql md5 0d7a7845758e65f29e9977c8dc53b2ef.


12. Branches applied vs deferred

Branch Verdict Why
A — bounded gate protocol APPLIED (live, self-tested) safe additive C4; reversible; proven fail-closed
B — review_decision readiness DEFERRED (author-ready) already wired in split/merge; only a manifest-bound Đ32 artifact is missing — creating it is governed-mutation, out of scope
C — event-contract readiness DEFERRED (author-ready) registry shape verified; delivery already route-scoped/fail-closed; lifecycle types unexercisable without emit (forbidden here)
D — rollback / fail-closed APPLIED (proven) for the one live object set
E — next prompts DELIVERED §13

13. Next three paste-ready execution prompts (Branch E)

All three build on the live gate protocol (fn_iu_gate_open/close/verify_closed/watchdog) and the corrected substrate findings in §6–§7. Shared channel: ssh contabo \"docker exec -i postgres psql -U workflow_admin -d directus -v ON_ERROR_STOP=1\" < /tmp/mig_NNN.sql (stdin pipe; container /tmp ≠ host /tmp; macOS md5 = openssl md5). MCP query_pg is read-only. 4 Mothers stays BLOCKED in all three.

13.1 — IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X

# MISSION: IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X
Effort: xhigh. Class: C3 GOVERNED_MUTATION_TEST. Mutating + governed.
PRECONDITION: bounded gate protocol live (fn_iu_gate_open/close/verify_closed/watchdog present; verify_closed all_safe=true). If absent, STOP.

## Goal
Run IU test d (d1 compose / d2 add / d3 remove / d4 reorder / d5 split / d6 merge / d7 render) on CLONED test IUs (lifecycle=testing), under bounded gates, with a REAL manifest-bound review_decision_id for d5/d6 — never bypassing review.

## Host / channel
contabo VPS, container postgres, db directus. Write: SSH workflow_admin stdin-pipe. Read: query_pg.

## Hard Gate 0
SSH workflow_admin BEGIN/ROLLBACK probe; pg_dump backup; Dependency Closure: confirm fn_iu_piece_split/merge (already require p_review_decision_id + FK-probe cutter_governance.review_decision), fn_iu_structure_op_apply/rollback, iu_split_set/iu_merge_set, the 9 d-commands; PRIVILEGED read of cutter_governance.review_decision shape (RO denied). If review_decision shape unreadable -> BLOCKED.

## Required approvals
- A real review_decision_id for d5/d6: create a TEST manifest_envelope + manifest_unit_block + review_decision (verdict=approved) bound to the cloned test IUs, under workflow_admin. (review_decision is manifest-bound: FK manifest_id->manifest_envelope, (manifest_id,unit_local_id)->manifest_unit_block.)
- An approval_id for every gate open (fn_iu_gate_open requires it).

## Gates (open via protocol ONLY: fn_iu_gate_open with approval_id + short ttl; close via fn_iu_gate_close; assert with fn_iu_gate_verify_closed)
- iu_core.composer_enabled (compose/add/remove/reorder/render)
- iu_core.structure_ops_enabled (split/merge/reparent)

## Rollback
fn_iu_structure_op_rollback per op; retire/mark test IUs; fn_iu_gate_close every opened gate + fn_iu_gate_verify_closed all_safe=true at end; pre-run pg_dump. If d5/d6 traverse the cut state machine, land U5 (IU_CUT_STATE_MACHINE_ROLLBACK_AFTER_APPROVAL_POLICY) FIRST.

## Forbidden
allow_no_review_decision flip (supply a real id); vector_sync flip; split/merge production law IUs (clones only); leaving any gate open; running split/merge without a review_decision_id; 4 Mothers; Nuxt/UI; secret logging.

## PASS/PARTIAL/BLOCKED
PASS: d1-d7 on test IUs, d5/d6 with a real review_decision_id producing durable iu_split_set/iu_merge_set rows, rollback proven, all gates closed (verify_closed all_safe=true), audit rows present.
PARTIAL: d1-d4/d7 pass; d5/d6 blocked on U5 state-machine edge (named); no unsafe state; gates closed.
BLOCKED: gate protocol absent, or review_decision shape unreadable, or channel down.

## Self-check
Real review_decision_id (not bypass)? Cloned IUs only? All opened gates closed via protocol? Rollback proven? 4 Mothers untouched?

13.2 — IU_TEST_E_TRIGGER_IN_OUT_GOVERNED_LIVE_TEST_60000X

# MISSION: IU_TEST_E_TRIGGER_IN_OUT_GOVERNED_LIVE_TEST_60000X
Effort: xhigh. Class: C2 (event-type registration) + C3 (bounded delivery) + C4 (delivery gate via protocol).
PRECONDITION: bounded gate protocol live. If absent, STOP.

## Goal
Define + exercise the per-IU trigger event contract: register the MISSING trigger-in / route-lifecycle event types (register-before-emit, refs-only), then prove a TEST IU can receive a trigger-in (fn_iu_sql_link_inbound_capture), emit a trigger-out (fn_iu_piece_emit_event -> event_outbox), route a forced failure to iu_route_dead_letter — all under a bounded, route-scoped delivery gate that cannot reach any of the 15 real routes.

## Host / channel
contabo VPS, container postgres, db directus. SSH workflow_admin / query_pg.

## Hard Gate 0 + corrected substrate facts (verified 2026-05-28)
- event_type_registry has NO json-schema/compat_mode columns; key = (event_domain,event_type); stream/lane MUST match registry (trg_event_outbox_type_validate). Source stream/lane from the registry, never hardcode.
- Trigger-OUT for structure ops is ALREADY registered (iu domain: structure_piece_split, structure_pieces_merged, ...). Register only what is genuinely missing (trigger-in capture type; route.delivered/route.failed IF you also add their emitter).
- Delivery is route-scoped by dot_config.iu_core.delivery_live_routes (CSV allowlist, currently EMPTY). A route not in the CSV is refused. The ONLY supported target is sql_function/fn_iu_structure_consumer; external targets refused. Master gate fn_iu_delivery_enabled.
- Confirm: fn_iu_emit_event, fn_iu_piece_emit_event, fn_iu_route_deliver, fn_iu_route_worker_run, fn_iu_route_dead_letter_replay; inventory the 15 iu_outbound_route rows.

## Required approvals
approval_id for fn_iu_gate_open on iu_core.delivery_enabled. Add ONLY a dedicated TEST route_code to iu_core.delivery_live_routes for the window; remove it on close. Never add any of the 15 real route_codes.

## Gates (protocol only)
iu_core.delivery_enabled — open via fn_iu_gate_open (approval_id, short ttl), close via fn_iu_gate_close, assert fn_iu_gate_verify_closed all_safe=true at end. fn_iu_gate_watchdog as the safety net.

## Rollback
Remove test route from allowlist + retire test route/IU/event rows; DELETE any newly-registered event types if the contract changes; gate close + verify_closed; pre-run pg_dump.

## Forbidden
Emitting unregistered events; delivering to ANY of the 15 real routes; leaving delivery_enabled open OR the test route in the allowlist; payload carrying body/secret/vector (refs-only, MP-D8 deny-list); allow_no_review_decision / vector_sync flip; 4 Mothers; secret logging.

## PASS/PARTIAL/BLOCKED
PASS: missing event types registered (refs-only); trigger-in captured for a test IU; trigger-out emits an outbox row; forced failure lands in iu_route_dead_letter (first population); delivery_enabled=false + allowlist empty at end; no real route touched.
PARTIAL: types registered (C2) but delivery test deferred because isolation/route-scoping cannot be fully proven; no unsafe state.
BLOCKED: gate protocol absent, or cannot guarantee the 15 real routes inert.

## Self-check
Register before emit? Any payload body/secret/vector (must be NO)? Could the flip reach a real route (must be NO — empty allowlist + only test route)? delivery_enabled=false + allowlist empty at end?

13.3 — IU_F_SQL_LINK_ENABLE_CAPTURE_GOVERNED_TEST_60000X

# MISSION: IU_F_SQL_LINK_ENABLE_CAPTURE_GOVERNED_TEST_60000X
Effort: xhigh. Class: C3 GOVERNED_MUTATION_TEST (flips iu_sql_link.enabled + runs inbound capture).
PRECONDITION: bounded gate protocol live; f-read proof already PASS. If gate protocol absent, STOP.

## Goal
Prove the WRITE half of test f: enabling a SQL link and running inbound capture on a TEST link/IU only — validate->enable->capture->resolve->disable->rollback — without touching the 3 real iu_sql_link rows live and without leaving any link enabled.

## Host / channel
contabo VPS, container postgres, db directus. SSH workflow_admin / query_pg.

## Hard Gate 0 + facts
- iu_sql_link has 3 real rows, all enabled=false. enabled=false suppresses runtime delivery/capture; validate/resolve read paths already PASS (prior macro).
- fn_iu_sql_link_inbound_capture() is the capture path (trigger-style). Confirm its exact contract + which dot_config gate(s) it honors before any enable.
- Inbound capture may emit/route — keep delivery route-scoped (delivery_live_routes empty + only a test route), reuse Branch C/Prompt-6 contract.
- Create a dedicated TEST iu_sql_link row pointing at a sandbox/test source; never enable a real link.

## Required approvals
approval_id for any gate open via fn_iu_gate_open (delivery/operator_runtime as the capture path requires); a recorded reason for the enable window.

## Gates (protocol only)
Whatever the capture path requires (likely iu_core.delivery_enabled and/or iu_core.operator_runtime_enabled) — open via fn_iu_gate_open, close via fn_iu_gate_close, assert fn_iu_gate_verify_closed all_safe=true at end; watchdog as safety net. Enable the TEST link inside the window; disable before close.

## Rollback
Set the test link enabled=false; delete the test link row + any captured rows; gate close + verify_closed; pre-run pg_dump.

## Forbidden
Enabling any of the 3 REAL iu_sql_link rows; leaving any link enabled; leaving any gate open; delivering to a real route; allow_no_review_decision / vector_sync flip; 4 Mothers; secret logging.

## PASS/PARTIAL/BLOCKED
PASS: a TEST link enabled inside a bounded window, capture demonstrated, resolve consistent, link disabled, gates closed (all_safe=true), real links untouched (still 3, all enabled=false).
PARTIAL: validate/resolve re-proven but capture deferred because the capture contract/gate cannot be safely bounded; no unsafe state.
BLOCKED: gate protocol absent, capture path cannot be isolated from real links/routes, or channel down.

## Self-check
Only a TEST link enabled (never the 3 real)? All links enabled=false at end? Capture isolated from real routes? All gates closed via protocol?

14. Law / gate / no-double-ownership review

  • Branch A owns the gate-protocol operation under Điều 35 (DOT catalog pairs) and the approval requirement under Điều 32 (approval_id mandatory on open; never-flip enforced). Audit (dot_iu_command_run + iu_gate_transition) satisfies Điều 31 as a cross-cutting integrity property — not a second owner. Reversibility satisfies Điều 30 — a property, not an owner. No double ownership.
  • Branch B is Điều 32 (review_decision) + Điều 38/39 (structure ops) territory — left for the governed test; the safety macro touches neither.
  • Branch C is Điều 45 (event/queue: register-before-emit, route-scoping, DLQ) — event-type registration is a Đ45 concern, not Đ35. Left for the delivery test.
  • Never-flip absolutes upheld: iu_enact.allow_no_review_decision and iu_core.vector_sync_enabled are coded into the protocol refusal list and remained false throughout (self-test T3/T3b + committed verify_closed).
  • No-double-ownership: each operation maps to exactly one owner law; Đ30/Đ31 appear only as cross-cutting requirements. The only new owner (4 Mothers / future Điều XX) stays BLOCKED.

15. Forbidden-compliance statement

No actual split/merge. No compose/add/remove/reorder/render. No event emission. No inbound SQL capture. No iu_sql_link.enabled flip. No persistent gate left open (committed verify_closed.all_safe=true). No iu_enact.allow_no_review_decision=true (coded refusal + stayed false). No iu_core.vector_sync_enabled=true (coded refusal + stayed false). No Qdrant/vector write. No Directus mutation. No 4 Mothers work. No Nuxt/UI. No schema/table/template/collection creation beyond the explicitly-justified additive safety objects (1 ledger table + 4 functions + 4 catalog rows). No final OSS selection. No law enactment. Only persisted writes: the gate-protocol DDL + 4 catalog rows; the self-test (which flipped gates) ran inside BEGIN/ROLLBACK and persisted nothing (dot_iu_command_run unchanged at 55). Plus these KB documents.


16. Underload self-check

  • Inspect gate substrate? Yes — found reader-only functions, no writer/ledger; built the missing protocol.
  • Inspect review-decision substrate? Yes — read full cutter_governance.review_decision shape + split/merge bodies; proved wiring already exists; classified the real gap (manifest-bound Đ32 artifact).
  • Inspect event-contract substrate? Yes — read registry shape, emit + route-deliver bodies; found delivery already route-scoped/fail-closed; corrected the prompt's schema/compat_mode assumption.
  • Inspect rollback/fail-closed paths? Yes — dry-ran the rollback; proved its open-gate refusal guard.
  • Apply all safe additive pieces? Yes — the gate protocol (the only branch safe to apply without crossing a forbidden line).
  • Produce next d/e/f-enable prompts? Yes — §13, all three building on the live protocol + corrected facts.
  • Prove no gate left open? Yes — committed verify_closed.all_safe=true; ledger 0 rows.
  • Keep 4 Mothers blocked? Yes — untouched; reaffirmed in all three next prompts.

Final verdict: PASS. The mutation-safety foundation is live: a fail-closed, approval-aware, watchdog-backed bounded gate protocol with a verify-closed proof — the single primitive d / e / f-enable depend on — plus precise author-ready hand-offs for the two branches that must stay governed.


IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X (§13.1) — the first governed mutating test, now unblocked by the live gate protocol. It needs a real manifest-bound review_decision_id (for cloned test IUs) and, if d5/d6 traverse the cut state machine, the U5 rollback edge first. Run d before e/f-enable. 4 Mothers remains BLOCKED until b–f + Wave-5 readiness close.

Back to Knowledge Hub knowledge/dev/reports/architecture/iu-mutation-safety-foundation-for-d-e-f-enable-live-apply-2026-05-28.md