KB-630B rev 2

dot-iu-cutter v0.2 — P0-6 + P0-5 Remainder DDL Draft (r2, A-1 resolved) (2026-05-16)

15 min read Revision 2
dot-iu-cutterdieu44v0.2p0-6p0-5-remainderddl-authoringddl-draftr2a1-resolvednot-executedready-for-gpt-review

dot-iu-cutter v0.2 — P0-6 + P0-5 Remainder DDL Draft

document_path: knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-p0-6-p0-5-remainder-ddl-draft-2026-05-16.sql.md
revision: r2
supersedes: r1 (2026-05-16) — r1 SUPERSEDED, DO NOT EXECUTE
date: 2026-05-16
author: Agent (Claude Code CLI, Opus 4.7 1M)
sovereign: User / anh Huyên
verifier: GPT (P0-6 + P0-5-remainder r2 DDL re-revision review — PENDING)
phase: v0.2 — P0-6 + P0-5-remainder DDL AUTHORING REVISION (r2)
a1_status: RESOLVED in r2 (live decision_backlog_entry PK = entry_id uuid)
ddl_authored: true
ddl_executed: false
mutation_performed: false
dry_run_started: false
dry_run_allowed: false (until GPT r2 review PASS)
production_migration_allowed: false

⛔ r1 SUPERSEDED — DO NOT EXECUTE r1. THIS IS r2.

r1 referenced a non-existent column decision_backlog_entry.decision_id and was correctly HALTED at the A-1 dry-run gate. r1 must NOT be executed. This r2 applies the GPT-selected fix (rename child columns to the entry_id family). r2 is still a DDL DRAFT for review only — no psql, no migration tool, no dry-run env, no production. Execution gated on: GPT r2 review PASS + explicit dry-run authorization + explicit User production prompt + separate session.


§1 — A-1 Resolution (root cause + fix)

root_cause: live cutter_governance.decision_backlog_entry PK = entry_id uuid;
            it has NO decision_id column (lean 6-col table:
            entry_id uuid, kind text, status text, payload jsonb,
            emitted_at timestamptz, scenario_ref text).
observed: production read-only catalog (workflow_admin @ `postgres`/directus),
          2026-05-16; SELECT-only, zero mutation. A-1 is now RESOLVED by
          direct observation — no longer an unverified assumption.
gpt_selected_fix: rename child columns to the entry_id family for consistency.
r2_changes (ONLY these; all other ratified decisions unchanged):
  decision_backlog_history:    decision_id      -> entry_id
  decision_backlog_dependency: from_decision_id -> from_entry_id
  decision_backlog_dependency: to_decision_id   -> to_entry_id
  all three FK targets:        cutter_governance.decision_backlog_entry(entry_id)
forbidden_in_r2: keeping decision_id / from_decision_id / to_decision_id names
unchanged: review_decision (FKs target manifest_envelope/manifest_unit_block/
  self — all confirmed correct in r1 dry-run preflight); escalation_ref stays
  a SOFT uuid (no FK) so the name mismatch never affected it.

§2 — Scope & Posture (unchanged from r1 except the A-1 fix)

  • Four new empty tables in schema cutter_governance: review_decision (P0-6), decision_backlog_history, decision_backlog_dependency, decision_backlog_sweep_log (P0-5 remainder).
  • 7 in-schema PostgreSQL FKs (count unchanged; targets corrected):
    1. review_decision.manifest_id → manifest_envelope.envelope_id
    2. review_decision (manifest_id, manifest_unit_local_id) → manifest_unit_block (envelope_id, unit_local_id) — nullable composite
    3. review_decision.prior_review_decision_id → review_decision.review_decision_id (self)
    4. review_decision.superseded_by_review_decision_id → review_decision.review_decision_id (self)
    5. decision_backlog_history.entry_id → decision_backlog_entry.entry_id (r2)
    6. decision_backlog_dependency.from_entry_id → decision_backlog_entry.entry_id (r2)
    7. decision_backlog_dependency.to_entry_id → decision_backlog_entry.entry_id (r2)
  • No cross-schema FK, PG enum, lookup table, Đ24 lookup FK, trigger, CHECK, DEFAULT, INSERT/seed/backfill, IF NOT EXISTS. Enum-class fields = text + documented allowed values (BATCH-1).
  • Single transaction (BEGIN … COMMIT); rollback = DROP the four empty tables.

§3 — Live Parent PK Facts (confirmed, production read-only 2026-05-16)

cutter_governance.decision_backlog_entry : PRIMARY KEY (entry_id)             ; entry_id uuid
cutter_governance.manifest_envelope      : PRIMARY KEY (envelope_id)          ; envelope_id uuid
cutter_governance.manifest_unit_block    : PRIMARY KEY (envelope_id, unit_local_id) ; envelope_id uuid, unit_local_id text
nullable_composite_FK_semantics: MATCH SIMPLE (default) — review→unit_block
  composite FK not enforced when manifest_unit_local_id IS NULL.

§4 — DDL Draft r2 (NOT executed)

-- =====================================================================
-- dot-iu-cutter v0.2 — P0-6 + P0-5 REMAINDER DDL DRAFT  (r2; A-1 RESOLVED)
-- ⛔ r1 SUPERSEDED — DO NOT EXECUTE. DO NOT EXECUTE r2 WITHOUT EXPLICIT
--    GPT r2 PASS + dry-run authorization + User prompt + separate session.
-- =====================================================================
-- r2 change vs r1: child column renames to entry_id family +
--                  FK targets -> decision_backlog_entry(entry_id)
-- target schema         : cutter_governance
-- transaction           : single BEGIN … COMMIT (atomic)
-- constraints policy    : no CHECK / no trigger / no DEFAULT / no PG enum /
--                         no lookup table / no Đ24 lookup FK / no cross-schema FK
-- in-schema FKs only    : 7 (unchanged count)
-- data                  : 4 tables created EMPTY (no INSERT/seed/backfill)
-- enum-class fields     : text + documented allowed values (BATCH-1)
-- =====================================================================

BEGIN;

-- ---------------------------------------------------------------------
-- P0-6 — Table cutter_governance.review_decision  (#9)  [UNCHANGED from r1]
-- ---------------------------------------------------------------------
CREATE TABLE cutter_governance.review_decision (
    review_decision_id              uuid        NOT NULL,
    governance_event_kind           text        NOT NULL,  -- fixed 'review_decision' (Đ44 Step 3 umbrella; no CHECK)
    manifest_id                     uuid        NOT NULL,  -- in-schema FK -> manifest_envelope.envelope_id (RD-1)
    manifest_version                text        NOT NULL,
    review_scope                    text        NOT NULL,  -- {envelope_level,unit_level,mixed} (no CHECK)
    manifest_unit_local_id          text        NULL,       -- composite-FK part2 -> manifest_unit_block.unit_local_id (RD-2); NULL=envelope-level
    status                          text        NOT NULL,  -- {pending,in_review,pass,fail,needs_human,escalated,superseded}
    verdict                         text        NOT NULL,  -- {PASS,FAIL,NEEDS_HUMAN} cutter-local v0.2 (RD-4)
    findings                        jsonb       NOT NULL,  -- D2 §4.6 10-item; all-10-for-PASS = app rule v0.2 (RD-5)
    reviewer_class                  text        NOT NULL,  -- {ai,human,council,dot_pair_verifier}
    reviewer_identity               jsonb       NOT NULL,  -- polymorphic; pseudonymous (G-5)
    reviewer_independence_evidence  jsonb       NULL,       -- app-layer enforcement v0.2 (RD-6; no trigger)
    risk_class_assessment           text        NOT NULL,  -- {low,standard,high}
    escalation_ref                  uuid        NULL,       -- SOFT -> cutter_governance.decision_backlog_entry (NO PG FK)
    cut_change_set_ref              uuid        NULL,       -- SOFT -> cutter_governance.cut_change_set (NO PG FK; P0-3 cross-link)
    prior_review_decision_id        uuid        NULL,       -- in-schema self-FK (RD-3)
    superseded_by_review_decision_id uuid       NULL,       -- in-schema self-FK (RD-3)
    decision_at                     timestamptz NOT NULL,
    decided_by                      text        NOT NULL,
    tool_revision                   text        NULL,
    review_duration_ms              integer     NULL,       -- advisory only
    cross_signed_by_dot_verifier    boolean     NOT NULL,  -- app-layer enforcement v0.2 (no DEFAULT)
    version                         text        NOT NULL,  -- record semver Đ38
    created_at                      timestamptz NOT NULL,  -- no DEFAULT (writer = P1)
    updated_at                      timestamptz NOT NULL,  -- no DEFAULT
    CONSTRAINT review_decision_pkey
        PRIMARY KEY (review_decision_id),
    CONSTRAINT review_decision_manifest_fk
        FOREIGN KEY (manifest_id)
        REFERENCES cutter_governance.manifest_envelope (envelope_id),
    CONSTRAINT review_decision_unit_block_fk
        FOREIGN KEY (manifest_id, manifest_unit_local_id)
        REFERENCES cutter_governance.manifest_unit_block (envelope_id, unit_local_id),
        -- MATCH SIMPLE (default): not enforced when manifest_unit_local_id IS NULL
    CONSTRAINT review_decision_prior_fk
        FOREIGN KEY (prior_review_decision_id)
        REFERENCES cutter_governance.review_decision (review_decision_id),
    CONSTRAINT review_decision_superseded_fk
        FOREIGN KEY (superseded_by_review_decision_id)
        REFERENCES cutter_governance.review_decision (review_decision_id)
);

-- ---------------------------------------------------------------------
-- P0-5 remainder — cutter_governance.decision_backlog_history (#10)
-- r2: child column `decision_id` RENAMED -> `entry_id`;
--     FK target -> decision_backlog_entry(entry_id).
-- Append-only Đ38 trail for the LIVE decision_backlog_entry.
-- ---------------------------------------------------------------------
CREATE TABLE cutter_governance.decision_backlog_history (
    history_id            uuid        NOT NULL,
    entry_id              uuid        NOT NULL,  -- r2: was decision_id; in-schema FK -> decision_backlog_entry.entry_id
    entry_version_before  text        NULL,       -- NULL for change_kind='create'
    entry_version_after   text        NOT NULL,
    change_kind           text        NOT NULL,  -- {create,status_change,field_update,closure,re_open,supersede} cutter-local v0.2 (DBH-2)
    change_diff           jsonb       NULL,       -- field-level delta for 'field_update'
    changed_by            text        NOT NULL,
    changed_at            timestamptz NOT NULL,  -- no DEFAULT
    rationale             text        NULL,
    CONSTRAINT decision_backlog_history_pkey
        PRIMARY KEY (history_id),
    CONSTRAINT decision_backlog_history_entry_fk
        FOREIGN KEY (entry_id)
        REFERENCES cutter_governance.decision_backlog_entry (entry_id)
);

-- ---------------------------------------------------------------------
-- P0-5 remainder — cutter_governance.decision_backlog_dependency (#11)
-- r2: child columns `from_decision_id`->`from_entry_id`,
--     `to_decision_id`->`to_entry_id`; FK targets -> entry_id.
-- Entry-to-entry directed graph; cycle detection = app-layer v0.2 (DBD-1).
-- ---------------------------------------------------------------------
CREATE TABLE cutter_governance.decision_backlog_dependency (
    dependency_id     uuid        NOT NULL,
    from_entry_id     uuid        NOT NULL,  -- r2: was from_decision_id; in-schema FK -> decision_backlog_entry.entry_id
    to_entry_id       uuid        NOT NULL,  -- r2: was to_decision_id;   in-schema FK -> decision_backlog_entry.entry_id
    dependency_kind   text        NOT NULL,  -- {blocks,supersedes,refines,related_to} cutter-local v0.2 (DBD-2)
    created_at        timestamptz NOT NULL,  -- no DEFAULT
    created_by        text        NOT NULL,
    CONSTRAINT decision_backlog_dependency_pkey
        PRIMARY KEY (dependency_id),
    CONSTRAINT decision_backlog_dependency_from_fk
        FOREIGN KEY (from_entry_id)
        REFERENCES cutter_governance.decision_backlog_entry (entry_id),
    CONSTRAINT decision_backlog_dependency_to_fk
        FOREIGN KEY (to_entry_id)
        REFERENCES cutter_governance.decision_backlog_entry (entry_id)
    -- NO UNIQUE(from,to,kind): edge-dedup is app-layer (no extra constraint)
    -- NO CHECK(from<>to) / NO cycle trigger: DBD-1 = application-layer v0.2
);

-- ---------------------------------------------------------------------
-- P0-5 remainder — cutter_governance.decision_backlog_sweep_log (#12)
-- [UNCHANGED from r1] Standalone sweep audit. NO FK, NO soft entity ref.
-- ---------------------------------------------------------------------
CREATE TABLE cutter_governance.decision_backlog_sweep_log (
    sweep_id                    uuid        NOT NULL,
    swept_at                    timestamptz NOT NULL,
    swept_by                    text        NOT NULL,
    trigger_kind                text        NOT NULL,  -- {scheduled,governance_review,health_report,self_review,ad_hoc} cutter-local v0.2 (DBS-1)
    entries_evaluated_count     integer     NOT NULL,
    entries_re_surfaced_count   integer     NOT NULL,
    escalations_routed_count    integer     NOT NULL,
    mirror_regenerated_at       timestamptz NULL,
    mirror_path                 text        NULL,       -- soft text path to KB mirror (NOT an entity FK)
    findings                    jsonb       NULL,
    CONSTRAINT decision_backlog_sweep_log_pkey
        PRIMARY KEY (sweep_id)
);

COMMIT;

-- =====================================================================
-- END OF DDL DRAFT r2 — NOTHING ABOVE HAS BEEN EXECUTED.
-- 4 empty tables, 7 in-schema FKs, no INSERT/seed/backfill, no PG enum,
-- no lookup table, no Đ24 lookup FK, no cross-schema FK, no CHECK,
-- no trigger, no DEFAULT, no IF NOT EXISTS.
-- =====================================================================

§5 — Ratified-Decision Encoding Map (r2)

Decision r2 encoding
A-1 fix (GPT-selected) history entry_id, dependency from_entry_id/to_entry_id; all 3 FKs → decision_backlog_entry(entry_id)
BATCH-1 text + documented values all enum-class columns text + comment; no PG enum / lookup / lookup FK
RD-1 / RD-2 / RD-3 review_decision FKs unchanged (manifest_envelope / nullable composite manifest_unit_block / 2 self-FKs)
RD-4 / RD-5 / RD-6 / DBH-1/2 / DBD-1/2 / DBS-1 unchanged from r1 (text enums, app-layer rules, no trigger/CHECK)

§6 — Table-Count Effect (unchanged)

cutter_governance_pre:  8
cutter_governance_post: 12  (+ review_decision + decision_backlog_history
                              + decision_backlog_dependency + decision_backlog_sweep_log)
FK_count: 7 (unchanged; targets corrected in r2)

§7 — Hard Boundaries

revision: r2
r1_superseded: TRUE (DO NOT EXECUTE r1)
ddl_authored: TRUE (this file, r2)
ddl_executed: FALSE
no_psql_run: TRUE (no execution; A-1 resolved via prior read-only catalog observation)
no_mutation: TRUE
no_dry_run_env_created: TRUE
no_dry_run_run: TRUE
dry_run_allowed: FALSE (until GPT r2 review PASS)
production_migration_allowed: FALSE
no_INSERT_no_seed_no_backfill: TRUE
no_PG_enum / no_new_lookup_table / no_dieu24_lookup_FK: TRUE
no_cross_schema_FK / no_CHECK / no_trigger / no_DEFAULT: TRUE
in_schema_FK_only: TRUE (7)
agent_self_advance: PROHIBITED
output_form: p0_6_p0_5_remainder_ddl_draft_r2

End of P0-6 + P0-5-remainder DDL draft (r2, A-1 resolved).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-p0-6-p0-5-remainder-ddl-draft-2026-05-16.sql.md