KB-22AC

dot-iu-cutter v0.2 — Phase α DDL Verification Plan (2026-05-15)

14 min read Revision 1
dieu44-trien-khaidot-iu-cutterv0.2phase-alphaddl-verificationno-execution2026-05-15

dot-iu-cutter v0.2 — Phase α DDL Verification Plan

document_path: knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-ddl-verification-plan-2026-05-15.md
revision: r1
date: 2026-05-15
author: Agent (Claude Code CLI, Opus 4.7 1M)
phase: v0.2 — Phase α DDL post-application verification PLAN (planning only)
no_execution: TRUE
no_verification_queries_run_in_this_doc: TRUE

§1 — Purpose

Define the verification queries and pass/fail criteria that MUST be evaluated after the Phase α DDL is applied (either in dry-run or production). This plan is written so the verifier can re-run the queries verbatim without ambiguity. Nothing is executed in this document.

The plan applies in two contexts:

  1. dry-run env (after the Phase α DDL applies inside the fresh dry-run sibling env)
  2. production env (after the eventual production execution of Phase α DDL under explicit prompt)

In production, the queries are the closing gates of the production command-review package's verification phase.


§2 — Verification Queries (read-only; NOT executed here)

2.1 V-α-1 — New columns exist on public.tac_logical_unit

-- expected: 2 rows (authority, canonical_address_format_version)
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema='public'
  AND table_name='tac_logical_unit'
  AND column_name IN ('authority', 'canonical_address_format_version')
ORDER BY column_name;

Expected result:

authority                          | text | YES | 'draft'::text
canonical_address_format_version   | text | NO  | 'canonical-address-v1'::text

PASS condition: exactly 2 rows; authority is nullable with DEFAULT 'draft'; canonical_address_format_version is NOT NULL with DEFAULT 'canonical-address-v1'.

2.2 V-α-2 — Mirror columns exist on sandbox_tac.logical_unit

-- expected: 2 rows
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema='sandbox_tac'
  AND table_name='logical_unit'
  AND column_name IN ('authority', 'canonical_address_format_version')
ORDER BY column_name;

Expected result: identical shape to §2.1.

PASS condition: same as §2.1.

2.3 V-α-3 — Alias table exists

-- expected: 1 row
SELECT count(*)
FROM information_schema.tables
WHERE table_schema='cutter_governance'
  AND table_name='canonical_address_alias'
  AND table_type='BASE TABLE';

Expected result: 1.

PASS condition: exactly 1.

2.4 V-α-4 — Alias table columns

-- expected: 9 rows in correct order
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema='cutter_governance'
  AND table_name='canonical_address_alias'
ORDER BY ordinal_position;

Expected columns (9):

alias_id          | uuid        | NO  | gen_random_uuid()
target_unit_id    | uuid        | NO  | (none)
alias_text        | text        | NO  | (none)
alias_kind        | text        | NO  | (none)
valid_from        | timestamptz | NO  | now()
valid_until       | timestamptz | YES | (none)
created_by        | text        | NO  | (none)
rationale         | text        | YES | (none)
scenario_ref      | text        | YES | (none)

PASS condition: exactly 9 columns in the expected order with the expected nullability/default shape.

2.5 V-α-5 — Alias table indexes

-- expected: 5 indexes (1 PK + 4 btree)
SELECT indexname, indexdef
FROM pg_indexes
WHERE schemaname='cutter_governance'
  AND tablename='canonical_address_alias'
ORDER BY indexname;

Expected indexes:

canonical_address_alias_pkey
idx_alias_alias_kind
idx_alias_alias_text
idx_alias_target_unit_id
idx_alias_validity_window

PASS condition: exactly 5 indexes present; PK is on alias_id; the 4 btree indexes match the columns specified in the DDL draft Step 8.

2.6 V-α-6 — public.tac_logical_unit.authority distribution

SELECT authority, count(*) AS n
FROM public.tac_logical_unit
GROUP BY authority
ORDER BY authority NULLS FIRST;

Expected result (production state after backfill):

draft   | 86

Expected result (production state — explicit):

authority      | n
---------------|----
draft          | 86
(no other rows; no 'enacted'; no 'runtime'; no NULL)

PASS conditions:

  • exactly 1 row in the result
  • authority='draft' with n=86
  • no NULL row
  • no 'enacted' or 'runtime' rows
  • if the production state were to include any active or retired rows in the future (currently zero), those would map to 'enacted' per BR-4; rerun before treating as failure.

2.7 V-α-7 — public.tac_logical_unit.canonical_address_format_version distribution

SELECT canonical_address_format_version, count(*) AS n
FROM public.tac_logical_unit
GROUP BY canonical_address_format_version
ORDER BY canonical_address_format_version;

Expected result:

canonical-address-v1 | 86

PASS condition: exactly 1 row; value 'canonical-address-v1'; n=86.

2.8 V-α-8 — sandbox_tac.logical_unit.authority distribution (no backfill expected)

SELECT authority, count(*) AS n
FROM sandbox_tac.logical_unit
GROUP BY authority
ORDER BY authority NULLS FIRST;

Expected result:

(NULL)  | 76

(SQL aggregation typically renders the NULL group as an empty cell or (null) indicator.)

PASS conditions:

  • exactly 1 row
  • authority IS NULL with n=76
  • NO 'draft' rows (since sandbox is NOT backfilled in Phase α; the column has a DEFAULT 'draft' for FUTURE inserts but no UPDATE was run on existing rows)
  • This is intentional per BR-7 Option II + GPT Q4 decision.

2.9 V-α-9 — sandbox_tac.logical_unit.canonical_address_format_version distribution

SELECT canonical_address_format_version, count(*) AS n
FROM sandbox_tac.logical_unit
GROUP BY canonical_address_format_version
ORDER BY canonical_address_format_version;

Expected result:

canonical-address-v1 | 76

PASS condition: exactly 1 row; value 'canonical-address-v1'; n=76 (DEFAULT applied at column-add time across all 76 sandbox rows).

2.10 V-α-10 — Alias table row count = 0

SELECT count(*) AS n
FROM cutter_governance.canonical_address_alias;

Expected: 0.

PASS condition: alias table is empty (Phase α creates it with no rows; writers are Phase β).

2.11 V-α-11 — Existing canonical_address column unchanged

-- column metadata unchanged
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema='public'
  AND table_name='tac_logical_unit'
  AND column_name='canonical_address';

Expected result:

canonical_address | text | NO | (none)

PASS condition: column still text NOT NULL; no default added; UNIQUE constraint still present (verifiable via V-α-12 below).

2.12 V-α-12 — UNIQUE constraint on canonical_address still in place

SELECT conname, pg_get_constraintdef(c.oid)
FROM pg_constraint c
JOIN pg_class t ON t.oid=c.conrelid
WHERE t.relname='tac_logical_unit' AND conname='tac_logical_unit_canonical_address_key';

Expected: 1 row showing UNIQUE (canonical_address).

PASS condition: UNIQUE constraint intact.

2.13 V-α-13 — v0.1 cutter_governance tables unchanged

-- exactly 6 tables in cutter_governance after Phase α
-- (5 from v0.1 + 1 new alias table)
SELECT relname, n_live_tup
FROM pg_stat_user_tables
WHERE schemaname='cutter_governance'
ORDER BY relname;

Expected result (post-Phase-α):

canonical_address_alias       | 0
cut_change_set                | 0
cut_change_set_affected_row   | 0
decision_backlog_entry        | 0
dot_pair_signature            | 0
verify_result                 | 0

PASS conditions:

  • exactly 6 tables
  • all 6 have n_live_tup = 0
  • the original 5 v0.1 tables are present with names exactly as shipped in v0.1 (no rename / no drop)

2.14 V-α-14 — Row count of public.tac_logical_unit unchanged

SELECT count(*) AS rows_total,
       count(canonical_address) AS canonical_non_null,
       count(DISTINCT canonical_address) AS distinct_canonical
FROM public.tac_logical_unit;

Expected result:

86 | 86 | 86

PASS condition: row count unchanged from pre-Phase-α state (86); canonical_address still 100% non-null; still 100% distinct.

2.15 V-α-15 — Row count of sandbox_tac.logical_unit unchanged

SELECT count(*) FROM sandbox_tac.logical_unit;

Expected: 76.

PASS condition: row count unchanged from pre-Phase-α state.

2.16 V-α-16 — Schema diff between pre-Phase-α snapshot and post-Phase-α schema

# Compare CREATE TABLE / ALTER TABLE / CREATE INDEX / CREATE SCHEMA additions.
diff \
  <(grep -E '^(CREATE TABLE|CREATE SCHEMA|CREATE INDEX|ALTER TABLE)' <pre_snapshot.sql>  | sort) \
  <(grep -E '^(CREATE TABLE|CREATE SCHEMA|CREATE INDEX|ALTER TABLE)' <post_snapshot.sql> | sort)

Expected diff: ADDITIONS ONLY, exclusively within:

  • public.tac_logical_unit (the 2 new ALTER-style entries for new columns)
  • sandbox_tac.logical_unit (the 2 new ALTER-style entries for mirror columns)
  • cutter_governance.canonical_address_alias (1 CREATE TABLE + 4 explicit CREATE INDEX + PG-generated PK/comment metadata)
  • comments via COMMENT ON

PASS conditions:

  • NO removed lines
  • NO ALTER lines outside public.tac_logical_unit / sandbox_tac.logical_unit (additive only on those tables; existing columns unchanged)
  • NO touched lines on any other production table

These are the Q-CHK-1/2/3 checks recommended in the fn_tac_birth_gate_lu inspection doc. They run before Step 3 backfill UPDATE to confirm trigger re-validation will not fail.

3.1 Q-CHK-1 — section_type vocab activity

SELECT count(*) AS rows_with_inactive_section_type
FROM public.tac_logical_unit u
LEFT JOIN public.tac_section_type_vocab v
       ON v.code = u.section_type
WHERE coalesce(v.lifecycle_status, 'missing') != 'active';

Expected: 0.

PASS condition: every row's section_type is active in the vocab.

3.2 Q-CHK-2 — parent_id resolution + doc_code parity

SELECT count(*) AS rows_with_parent_problem
FROM public.tac_logical_unit child
LEFT JOIN public.tac_logical_unit parent
       ON parent.id = child.parent_id
WHERE child.parent_id IS NOT NULL
  AND (parent.id IS NULL OR parent.doc_code != child.doc_code);

Expected: 0.

PASS condition: every non-null parent resolves and shares doc_code.

3.3 Q-CHK-3 — canonical_address regex defensive recheck

SELECT count(*) AS rows_failing_regex
FROM public.tac_logical_unit
WHERE canonical_address !~ '^D38-[A-Z0-9]+-((ROOT)|(S[0-9]+(-P[0-9]+(-[0-9]+)*)?))$';

Expected: 0.

PASS condition: every row passes the canonical-address-v1 regex (matches the trigger's hardcoded regex).

If any of the three pre-backfill checks fail, the Phase α DDL must NOT proceed in that environment until the underlying data is fixed.


§4 — Failure-Stop Criteria (per verification query)

fail_action_on_ANY_failure_during_dry_run:
  - record evidence (query output + timestamp)
  - rollback the dry-run transaction
  - do NOT proceed to subsequent scenarios
  - escalate to GPT review

fail_action_on_ANY_failure_during_production_post_DDL_verification:
  - STOP immediately
  - capture all verification query outputs to the production artefact directory
  - execute the rollback per the rollback draft (separate file)
  - record an admin_fallback_log entry (manual; the runtime APR path is not Phase α scope)
  - notify Đ32 (standard path) + G-4 Custodian
  - do NOT self-retry

specific_pass_threshold:
  - V-α-1 .. V-α-16: ALL must PASS
  - Q-CHK-1, Q-CHK-2, Q-CHK-3: ALL must PASS (pre-backfill)
  - any single failure: STOP

production_specific_rollback_trigger:
  any_of:
    - V-α-1 / V-α-2 missing columns
    - V-α-3 / V-α-4 alias table malformed or missing
    - V-α-6 authority distribution not {'draft' x 86}
    - V-α-7 format_version distribution not {'canonical-address-v1' x 86}
    - V-α-13 cutter_governance tables changed beyond the additive alias table
    - V-α-14 / V-α-15 row counts differ from pre-state
    - V-α-16 schema diff shows ANY non-additive change

§5 — Hard Boundaries

no_verification_query_executed_here: TRUE
no_DDL_executed: TRUE
no_mutation: TRUE
no_dry_run_started: TRUE
no_production_migration_allowed: TRUE
output_form: phase_alpha_verification_planning_only

§6 — Cross-References

fn_inspection:        knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-fn-tac-birth-gate-lu-inspection-2026-05-15.md
ddl_draft:            knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-ddl-draft-2026-05-15.sql.md
rollback_draft:       knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-rollback-draft-2026-05-15.md
authoring_report:     knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-ddl-authoring-report-2026-05-15.md
dry_run_plan:         knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-dry-run-plan-2026-05-15.md
risk_review_plan:     knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-risk-review-plan-2026-05-15.md
v0_1_verification_pattern_(C-09a..e): knowledge/dev/laws/dieu44-trien-khai/execution/dot-iu-cutter-v0.1-p0-production-command-review-package-2026-05-15.md  (§2.9)
v0_1_production_execution_report: knowledge/dev/laws/dieu44-trien-khai/execution/dot-iu-cutter-v0.1-production-execution-report-2026-05-15.md  (§8 verification results pattern)

End of Phase α DDL verification plan.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.2-ddl-authoring/dot-iu-cutter-v0.2-phase-alpha-ddl-verification-plan-2026-05-15.md