KB-4BE8

dot-iu-cutter v0.5 — Lifecycle Implementation Authoring · Live Re-check + Scope Lock (G0+G1 PASS) (doc 1 of 6)

19 min read Revision 1
dot-iu-cutterv0.5lifecycle-enactment-implementation-authoringlive-recheckscope-lockdesign-finding-holdsfn-iu-apply-edit-draft-md5-22875ce2no-fn-iu-enact-yetdirectus-secdef-can-probe-cutter-governancedieu442026-05-20

dot-iu-cutter v0.5 — Lifecycle Implementation Authoring · Live Re-check + Scope Lock

doc 1 of 6 · 2026-05-20 · READ-ONLY RE-CHECK + AUTHORING SCOPE LOCK

phase             : G0 (SSOT re-confirm) + G1 (scope lock)
outcome           : PASS — all design facts still hold; scope locked
production_mutation : NONE

0. Macro framing

This macro is the implementation-authoring follow-on to the design package at [[dot-iu-cutter-v0-5-06-final-lifecycle-design-report-2026-05-20]]. Per the GPT ruling (reviews/dot-iu-cutter-v0.5-lifecycle-enactment-design-ready-gpt-ruling-2026-05-20.md):

M3_lifecycle_design         : PASS
selected_next_path          : PATH_1_IMPLEMENTATION_AUTHORING_MACRO
OQ_defaults                 : ACCEPT_AGENT_RECOMMENDED_DEFAULTS
production_enactment        : not_authorized_yet
new_review_decision_required_before_enactment : true

This macro authors DDL/function bodies + patches + the operator package. It does NOT execute DDL, mutate lifecycle state, deploy, merge, or push.

1. G0 — live state re-check (2026-05-20T07:09:51Z)

1.1 Authoritative inventory unchanged

SELECT COUNT(*) AS n_icx_const,
       COUNT(*) FILTER (WHERE lifecycle_status='draft') AS n_draft,
       array_agg(DISTINCT lifecycle_status) AS statuses
FROM public.information_unit
WHERE canonical_address LIKE 'ICX-CONST%';
n_icx_const : 60
n_draft     : 60
statuses    : ['draft']
SELECT (SELECT count(*) FROM public.information_unit) AS iu_total,
       (SELECT count(*) FROM public.unit_version)     AS uv_total,
       (SELECT count(*) FROM public.unit_version WHERE enacted_at IS NOT NULL)
                                                        AS uv_enacted_at_nonnull;
iu_total                : 158
uv_total                : 165
uv_enacted_at_nonnull   : 0

1.2 No new lifecycle infrastructure crept in

public.iu_lifecycle_vocab          : DOES NOT EXIST
public.iu_lifecycle_log            : DOES NOT EXIST
public.fn_iu_enact                  : DOES NOT EXIST
public.fn_iu_enacted_immut          : DOES NOT EXIST
public.fn_uv_enacted_immut          : DOES NOT EXIST
trg_iu_enacted_immut                : NOT ATTACHED
trg_uv_enacted_immut                : NOT ATTACHED
dot_config.iu_enact.*               : ABSENT (0 keys)

1.3 Function body fingerprints unchanged from design

function body md5 (live now) design finding
public.fn_iu_create 3017892a5ac605a6daeaa5348e2a6cdf match
public.fn_iu_apply_edit_draft 22875ce25b2e2d1751cc4f3d1757252e match (latent defect still present)
public.fn_iu_gateway_write_guard 6907fa4e5e46b5617d7dfecbd86326d7 match
public.fn_iu_verify_invariants 6d005323d15eb4802f22802470b2c966 (new pin; matches G1 doc 01 of design)

fn_iu_apply_edit_draft body BYTE-IDENTICAL to the body the design package analyzed. The patch text in doc 03 of this package is directly applicable; no re-derivation needed.

1.4 Gateway policy unchanged

SELECT key, value FROM public.dot_config
 WHERE key='iu_create.gateway.allowed_marker_values' OR key LIKE 'iu_enact.%';
iu_create.gateway.allowed_marker_values : 'fn_iu_create,fn_iu_apply_edit_draft'  (1 row)
iu_enact.*                              : (0 rows)

1.5 Cross-schema privilege probe (critical for fn_iu_enact SECDEF body)

SELECT nspacl FROM pg_namespace WHERE nspname='cutter_governance';
-- {workflow_admin=UC/workflow_admin,
--  directus=U/workflow_admin,
--  cutter_ro=U/workflow_admin,
--  cutter_exec=U/workflow_admin,
--  cutter_verify=U/workflow_admin}

SELECT has_schema_privilege('directus','cutter_governance','USAGE')          AS directus_usage;
-- true

SELECT relacl FROM pg_class c JOIN pg_namespace n ON c.relnamespace=n.oid
 WHERE n.nspname='cutter_governance' AND c.relname IN ('review_decision','cut_change_set');
-- review_decision: directus=r/workflow_admin
-- cut_change_set : directus=r/workflow_admin
directus_schema_usage_cutter_governance : true
directus_table_select_review_decision    : true
directus_table_select_cut_change_set     : true

fn_iu_enact running SECURITY DEFINER as directus CAN execute PERFORM 1 FROM cutter_governance.review_decision WHERE review_decision_id = p_review_decision_id. No additional grant required for the design's step-6 governance-link probe.

1.6 Governance table PK column names (must match in function body)

SELECT c.relname AS tbl, a.attname
  FROM pg_constraint co
  JOIN pg_class c ON co.conrelid=c.oid
  JOIN pg_namespace n ON c.relnamespace=n.oid
  JOIN pg_attribute a ON a.attrelid=c.oid AND a.attnum=ANY(co.conkey)
 WHERE n.nspname='cutter_governance'
   AND c.relname IN ('review_decision','cut_change_set')
   AND co.contype='p';
cutter_governance.review_decision : PK = review_decision_id   (uuid)
cutter_governance.cut_change_set  : PK = change_set_id         (uuid)

Function body MUST reference review_decision_id (not id) when probing review_decision; MUST reference change_set_id (not id) when probing cut_change_set. Captured here so the DDL author does not silently use id.

2. G1 — implementation scope lock

2.1 Objects to CREATE / REPLACE (full list)

The macro authors but does NOT execute the following. Ordering matches the 7-phase implementation sequence from the design ( [[dot-iu-cutter-v0-5-05-grant-verification-rollback-plan-2026-05-20]] §2):

Bundle A — Vocab + Log tables (Phase 1 in execution macro):
  A.1 CREATE TABLE public.iu_lifecycle_vocab
  A.2 4-row INSERT … ON CONFLICT DO UPDATE (seed)
  A.3 CREATE TABLE public.iu_lifecycle_log
  A.4 5 indexes on iu_lifecycle_log
  A.5 GRANT SELECT on vocab/log to read roles (PUBLIC for vocab;
       cutter_exec/cutter_verify/context_pack_readonly/workflow_admin for log)

Bundle B — Immutability functions + triggers (Phase 2):
  B.1 CREATE OR REPLACE FUNCTION public.fn_iu_enacted_immut()      (non-SECDEF)
  B.2 CREATE TRIGGER trg_iu_enacted_immut BEFORE UPDATE OR DELETE
       ON public.information_unit FOR EACH ROW EXECUTE FUNCTION ...
  B.3 CREATE OR REPLACE FUNCTION public.fn_uv_enacted_immut()      (non-SECDEF)
  B.4 CREATE TRIGGER trg_uv_enacted_immut BEFORE UPDATE OR DELETE
       ON public.unit_version FOR EACH ROW EXECUTE FUNCTION ...

Bundle C — fn_iu_enact body (Phase 3):
  C.1 CREATE OR REPLACE FUNCTION public.fn_iu_enact(
        p_canonical_address text,
        p_actor             text,
        p_review_decision_id uuid,
        p_target_lifecycle  text     DEFAULT 'enacted',
        p_change_set_id     uuid     DEFAULT NULL,
        p_reason            text     DEFAULT NULL,
        p_tool_revision     text     DEFAULT NULL,
        p_dry_run           boolean  DEFAULT false
      ) RETURNS jsonb
      LANGUAGE plpgsql
      SECURITY DEFINER
      SET search_path = pg_catalog, public;

Bundle D — Gateway policy + dot_config + grants (Phase 4):
  D.1 UPDATE dot_config: allowed_marker_values append ',fn_iu_enact'
  D.2 INSERT 8 keys iu_enact.* (ON CONFLICT DO UPDATE)
  D.3 REVOKE EXECUTE ON FUNCTION public.fn_iu_enact(...) FROM PUBLIC
  D.4 GRANT EXECUTE ON FUNCTION public.fn_iu_enact(...) TO cutter_exec
  D.5 (optional, deferred to a separate step) GRANT EXECUTE TO workflow_admin

Bundle E — fn_iu_apply_edit_draft patch (Phase 5):
  E.1 CREATE OR REPLACE FUNCTION public.fn_iu_apply_edit_draft(
        p_draft_id uuid, p_actor text, p_review_note text
      ) RETURNS jsonb
      LANGUAGE plpgsql
      SECURITY DEFINER
      SET search_path = pg_catalog, public;
      -- replace global lifecycle_status block with per-anchor lookup;
      -- add 'base_version_enacted' refusal

Bundle F — Caller / repo integration (Phase 6; authored here, repo work
in a follow-on commit gated on Bundle A..E execution):
  F.1 cutter_agent/lifecycle_enact_adapter.py (module + tests)
  F.2 cutprod_canonical.py 'enact' sub-command
  F.3 knowledge/dev/laws/dieu44-trien-khai/readme/iu-lifecycle-enactment-readme.md

2.2 Objects EXPLICITLY NOT touched in any execution phase

production rows NOT touched:
  - 158 information_unit rows  (all lifecycle_status, all data)
  - 165 unit_version rows      (all lifecycle_status, all data, all enacted_at)
  - all 60 ICX-CONST IUs remain lifecycle_status='draft' through the
    full implementation execution; only Phase 7 (separate sovereign gate)
    enacts them.

production functions NOT touched:
  - public.fn_iu_create
  - public.fn_iu_gateway_write_guard
  - public.fn_iu_verify_invariants
  - public.fn_iu_create_plan / fn_iu_create_preflight
  - public.fn_iu_create_edit_draft / fn_iu_create_edit_draft_for_supersede
  - public.fn_iu_save / fn_iu_edit / fn_iu_edit_plan
  - public.fn_iu_comment / fn_iu_comment_edit_draft
  - public.fn_iu_mark_read / fn_iu_unread / fn_iu_notification_board
  - public.fn_iu_notif_* (3 functions)
  - public.fn_iu_classify_existing / fn_iu_resolve_default
  - public.fn_birth_registry_auto / fn_birth_auto_certify / fn_birth_change_flag_matrix
  - public.fn_iu_birth_gate_layer1 / fn_iu_birth_gate_layer2 / fn_iu_updated_at
  - public.fn_law_enacted_immutable / fn_law_enacted_must_have_enforcement
  - public.fn_nrm_enacted_* (3 functions)
  - public.fn_tac_enacted_immut / fn_tac_pm_enacted_lock / fn_tac_birth_gate_lu
  - public.fn_transition_lifecycle / fn_bulk_transition / fn_backfill_lifecycle_log
  - public.fn_enforce_apr_lifecycle / fn_iu_verify_invariants
  - public.fn_content_hash
  - all sandbox_tac.* functions

production tables/triggers NOT touched:
  - public.lifecycle_log (the existing INTEGER-keyed log; left alone)
  - public.birth_registry (data NOT touched; triggers attached NOT touched)
  - public.dot_config (8 INSERTs in iu_enact.* namespace + 1 row UPDATE only;
                       no other rows changed)
  - public.collection_registry (unchanged)
  - public.tac_*_lifecycle_vocab (unchanged; we author iu_lifecycle_vocab,
                                   not tac_*)
  - public.tac_unit_version (unchanged)
  - public.normative_registry (unchanged)
  - public.approval_requests (unchanged)
  - all triggers ALREADY on information_unit & unit_version are unchanged
    (gateway, birth-gate L1, birth-gate L2, updated_at, notif-version)
  - all cutter_governance.* tables (no write; only SELECT-probes from SECDEF)
  - all sandbox_tac.* tables

roles NOT created/dropped:
  - new GRANTs to existing roles only; no CREATE ROLE / DROP ROLE
  - no role membership change

2.3 Idempotency contract (per OQ-1..OQ-7 defaults)

fn_iu_enact idempotency:
  - same (canonical_address, target) re-call: returns status='already_<target>',
    no new log row, no rows written
  - same (canonical_address, target) re-call from a different actor:
    still returns 'already_<target>' (the lifecycle_log row from the
    ORIGINAL transition remains authoritative; we do NOT append a
    duplicate transition row)
  - re-call after a successful 'plan_ok' dry_run: full transition fires
    (dry_run never wrote anything)

DDL idempotency (vocab/log/functions/triggers):
  - CREATE TABLE … IF NOT EXISTS is intentionally NOT used because we
    want CREATE-failures to surface and be diagnosed (rather than
    silently skip a schema-drift). Instead the macro guards with a
    preflight probe (PHASE 1 P0.4 in design doc 05 §2).
  - CREATE OR REPLACE FUNCTION is used; safe by definition.
  - CREATE TRIGGER does NOT support OR REPLACE; the execution macro
    will use a guarded DROP TRIGGER IF EXISTS … followed by CREATE TRIGGER.
    Same guard pattern as Pack 22-P3 rev7.
  - INSERT … ON CONFLICT (key) DO UPDATE for vocab seed + dot_config
    iu_enact.* keys (idempotent).
  - UPDATE dot_config WHERE key=… (idempotent on the value; safe to
    re-run with the same final value).

GRANT idempotency:
  - GRANT is idempotent in PostgreSQL (re-running a grant does nothing).

2.4 Fail-closed guards in fn_iu_enact

G-IN-1 : input validation (canonical_address/actor/review_decision_id required)
         else: status='invalid_input'
G-IN-2 : target_lifecycle must exist in iu_lifecycle_vocab
         else: status='invalid_target_lifecycle'
G-IDM  : idempotent no-op if from==to
         status='already_<target>'
G-FSM  : FSM transition matrix
         else: status='fsm_denied'
G-INV  : fn_iu_verify_invariants(canonical_address) all_pass
         else: status='invariant_failed'
G-GOV  : review_decision_id exists in cutter_governance.review_decision
         else: status='review_decision_not_found'
G-GOV2 : if change_set_id provided, must exist in cutter_governance.cut_change_set
         else: status='change_set_not_found'
G-LOCK : pg_advisory_xact_lock(hashtext('iu_enact:'||iu_id::text))
         serializes per-IU; no failure mode
G-MARK : set_config('app.canonical_writer','fn_iu_enact',true)
         no failure mode; transaction-local
G-POST : post-write re-check IU.lifecycle_status==target
         else: RAISE EXCEPTION 'fn_iu_enact post-write mismatch' (txn rolls back)

If ANY guard trips, the function returns a failure-status JSON or
RAISEs an exception that aborts the transaction. No partial state.

2.5 Required p_review_decision_id contract

HARD REQUIRE (OQ-5 default):
  NOT NULL                            : enforced at step 0 (input validation)
  exists in cutter_governance.review_decision : enforced at step 6
  semantic appropriateness            : NOT enforced by function;
                                         operational discipline checks that
                                         the row's governance_event_kind and
                                         review_scope are appropriate for
                                         enactment (vs CUT or other events)

The function does NOT enforce "must differ from CUT review_decision
(29c88a7b-…)" because the row's contents — not its identity — determine
appropriateness. The operator obtaining the new review_decision via
leg-B style governed recording is responsible for ensuring the row's
content (decision_at, decided_by, verdict, review_scope) reflects an
ENACTMENT decision, not a CREATION decision.

Pre-Phase-7 prerequisite (NOT covered by this macro):
  - record a NEW cutter_governance.review_decision row with
    governance_event_kind suitable for enactment scope
  - record (optionally) a NEW cutter_governance.cut_change_set row
    linking to it
  - sovereign ruling on the new review_decision before phase 7 fires

2.6 Concurrency posture

single-IU concurrency:
  pg_advisory_xact_lock(hashtext('iu_enact:'||iu_id::text))
  - two concurrent enactments on the SAME IU: second waits for first
  - first finishes → second sees lifecycle_status=already_<target> →
    returns idempotent 'already_<target>'

cross-IU concurrency:
  - independent advisory locks per IU
  - two concurrent enactments on DIFFERENT IUs: both proceed in parallel
  - gateway marker app.canonical_writer is transaction-local (set_config
    with is_local=true) so no cross-session pollution

cross-with-other-canonical-writers:
  - fn_iu_create on a new IU (different canonical_address):
    no advisory-lock collision; both proceed
  - fn_iu_apply_edit_draft on an existing IU (same target IU as enact):
    no advisory-lock collision in design (apply_edit_draft uses FOR UPDATE
    on the IU row at its step 'SELECT * INTO v_iu FROM ... FOR UPDATE');
    advisory lock and row lock are different. If apply_edit_draft is
    creating a new UV while fn_iu_enact is transitioning the current
    UV anchor: serialized by FOR UPDATE on information_unit row.

2.7 What this macro produces — final deliverables list

KB artifacts (6 docs in v0.5-lifecycle-enactment-implementation-authoring/):
  - 01-live-recheck-and-scope-lock                      (this doc)
  - 02-fn-iu-enact-ddl-package                          (Bundles A+B+C+D)
  - 03-fn-iu-apply-edit-draft-patch-package             (Bundle E)
  - 04-verification-rollback-compensation-plan
  - 05-command-review-package
  - 06-final-implementation-authoring-report

repo artifacts (NOT committed in this macro; surfaced as backlog with
exact body sketches in doc 02 §13 and doc 03 §5):
  - cutter_agent/lifecycle_enact_adapter.py             (module body sketched)
  - cutter_agent/tests/test_lifecycle_enact_adapter.py   (tests sketched)
  - cutprod_canonical.py                                  (enact sub-command sketched)

operator README (authored but not yet placed):
  - knowledge/dev/laws/dieu44-trien-khai/readme/iu-lifecycle-enactment-readme.md
    (full body in doc 05 §7)

NOT included in this macro:
  - any SQL execution against production
  - any commit / push / tag / merge
  - any test invocation against live DB
  - any leg-B governed recording of a NEW review_decision
  - any phase-7 enactment

3. G0+G1 disposition

G0_live_state_re_check     : PASS — all design fingerprints unchanged
G1_scope_lock              : PASS — bundles A..F locked; non-touched
                              objects enumerated; idempotency contract
                              defined; concurrency posture defined
production_mutation         : NONE
next                       : G2 — DDL/function authoring
                              [[dot-iu-cutter-v0-5-02-fn-iu-enact-ddl-package-2026-05-20]]

Related KB documents in this package:

  • [[dot-iu-cutter-v0-5-02-fn-iu-enact-ddl-package-2026-05-20]]
  • [[dot-iu-cutter-v0-5-03-fn-iu-apply-edit-draft-patch-package-2026-05-20]]
  • [[dot-iu-cutter-v0-5-04-verification-rollback-compensation-plan-2026-05-20]]
  • [[dot-iu-cutter-v0-5-05-command-review-package-2026-05-20]]
  • [[dot-iu-cutter-v0-5-06-final-implementation-authoring-report-2026-05-20]]

Predecessors:

  • v0.5-lifecycle-enactment-design/ (6 docs; OPT-E1 + OQ-1..OQ-7 defaults)
  • reviews/dot-iu-cutter-v0.5-lifecycle-enactment-design-ready-gpt-ruling-2026-05-20.md (GPT ruling)
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.5-lifecycle-enactment-implementation-authoring/dot-iu-cutter-v0.5-01-live-recheck-and-scope-lock-2026-05-20.md