KB-6C41

90000x · 06 — Verify CUT (Migration 041)

7 min read Revision 1
iu-core90000xverify-cutfn_iu_verify_cutdot_iu_verify_cut_resultaxis-a-b-cmigration-041authored-ready2026-05-25

90000x · 06 — Verify CUT

Phase: F Status: AUTHORED-READY Migration: 041 D9 delta after apply: +1 fn (fn_iu_verify_cut), +1 DOT (dot_iu_verify_cut_result).

What it asserts (post-cut)

Assertion ID Statement How
V-recon fn_iu_reconstruct_source(run_id) returns normalized text equal to manifest.source_text (whitespace_collapse_v1 normalization) call existing fn fn_iu_reconstruct_source
V-axisA source_position of pieces created by this run is dense + monotonic from 1 within the run SELECT … FROM information_unit JOIN dot_iu_command_run payload pieces
V-axisB every created piece has piece_role + section_type set (NOT NULL) SELECT count(*) WHERE piece_role IS NULL OR section_type IS NULL FOR pieces in run
V-axisC fn_iu_subtree(root_unit_id) returns the expected piece-set (size + content_digests match) call existing fn fn_iu_subtree
V-noVec 0 new rows in iu_vector_sync_point referencing these pieces (cut does not vectorize) count
V-dieu DIEU-28/32/35 axis counts unchanged (27/23/36 baseline preserved) count over information_unit per dieu
V-prod production_documents row count unchanged vs run start (this fn doesn't compare; healthcheck doc 09 records the count) external

Migration 041 — authored

-- IU Core 90000x · Migration 041 · Verify CUT
BEGIN;

CREATE OR REPLACE FUNCTION fn_iu_verify_cut(
  p_run_id    uuid,
  p_actor     text DEFAULT 'fn_iu_verify_cut'
) RETURNS jsonb LANGUAGE plpgsql AS $$
DECLARE
  v_run dot_iu_command_run;
  v_staging iu_core.iu_staging_record;
  v_manifest jsonb;
  v_pieces_created uuid[];
  v_pieces_count int;
  v_axis_a_ok boolean; v_axis_a_min int; v_axis_a_max int; v_axis_a_holes int;
  v_axis_b_problems int;
  v_axis_c_ok boolean;
  v_no_vector_count int;
  v_problems text[] := '{}';
BEGIN
  SELECT * INTO v_run FROM dot_iu_command_run
   WHERE command_name='dot_iu_cut_from_manifest'
     AND payload_json @> jsonb_build_object('run_id', p_run_id)
   ORDER BY created_at DESC LIMIT 1;
  IF NOT FOUND THEN RETURN jsonb_build_object('ok',false,'reason','run_not_found'); END IF;

  v_pieces_created := ARRAY(SELECT (jsonb_array_elements_text(v_run.payload_json->'pieces_created'))::uuid);
  v_pieces_count := COALESCE(array_length(v_pieces_created,1), 0);

  SELECT * INTO v_staging FROM iu_core.iu_staging_record WHERE consumed_by_run_id = p_run_id;
  IF NOT FOUND THEN RETURN jsonb_build_object('ok',false,'reason','staging_not_consumed'); END IF;
  SELECT payload_json INTO v_manifest FROM iu_core.iu_staging_payload
   WHERE staging_record_id = v_staging.staging_record_id AND part_name = 'cut_manifest';

  -- V-axisA dense monotonic from 1
  SELECT MIN(source_position), MAX(source_position),
         (MAX(source_position) - MIN(source_position) + 1) - COUNT(*)::int
    INTO v_axis_a_min, v_axis_a_max, v_axis_a_holes
  FROM iu.information_unit WHERE id = ANY(v_pieces_created);
  v_axis_a_ok := (v_axis_a_min=1) AND (v_axis_a_holes=0) AND (v_pieces_count > 0);
  IF NOT v_axis_a_ok THEN
    v_problems := v_problems || ('V-axisA: min='||COALESCE(v_axis_a_min::text,'NULL')||' holes='||COALESCE(v_axis_a_holes::text,'NULL'));
  END IF;

  -- V-axisB piece_role + section_type present
  SELECT count(*) INTO v_axis_b_problems
  FROM iu.information_unit
  WHERE id = ANY(v_pieces_created) AND (piece_role IS NULL OR section_type IS NULL);
  IF v_axis_b_problems > 0 THEN
    v_problems := v_problems || ('V-axisB: '||v_axis_b_problems||' pieces missing piece_role or section_type');
  END IF;

  -- V-axisC subtree check (root = pieces with no parent in this run; size match)
  -- structural call to fn_iu_subtree for each root and aggregate count
  WITH roots AS (
    SELECT id FROM iu.information_unit
    WHERE id = ANY(v_pieces_created)
      AND id NOT IN (
        SELECT child_unit_id FROM iu_sql_link WHERE parent_unit_id = ANY(v_pieces_created)
      )
  ), subtree_size AS (
    SELECT (SELECT count(*) FROM fn_iu_subtree(r.id)) AS sz FROM roots r
  )
  SELECT (COALESCE(SUM(sz),0) = v_pieces_count) INTO v_axis_c_ok FROM subtree_size;
  IF NOT v_axis_c_ok THEN v_problems := v_problems || 'V-axisC: subtree size ≠ pieces created'; END IF;

  -- V-noVec
  SELECT count(*) INTO v_no_vector_count
  FROM iu_vector_sync_point WHERE unit_id = ANY(v_pieces_created);
  IF v_no_vector_count > 0 THEN
    v_problems := v_problems || ('V-noVec: '||v_no_vector_count||' iu_vector_sync_point rows reference cut pieces (expected 0)');
  END IF;

  -- Audit
  INSERT INTO dot_iu_command_run (command_name, payload_json, actor, status)
  VALUES ('dot_iu_verify_cut_result',
          jsonb_build_object('run_id',p_run_id,'staging_record_id',v_staging.staging_record_id,
                             'pieces_count',v_pieces_count,
                             'axis_a_ok',v_axis_a_ok,'axis_b_ok',(v_axis_b_problems=0),
                             'axis_c_ok',v_axis_c_ok,'no_vector_ok',(v_no_vector_count=0),
                             'problems',to_jsonb(v_problems)),
          p_actor, CASE WHEN array_length(v_problems,1) IS NULL THEN 'ok' ELSE 'fail' END);

  RETURN jsonb_build_object(
    'ok', (array_length(v_problems,1) IS NULL),
    'verdict', CASE WHEN array_length(v_problems,1) IS NULL THEN 'verified' ELSE 'failed' END,
    'pieces_count', v_pieces_count,
    'axis_a_ok', v_axis_a_ok,
    'axis_b_ok', (v_axis_b_problems=0),
    'axis_c_ok', v_axis_c_ok,
    'no_vector_ok', (v_no_vector_count=0),
    'problems', COALESCE(to_jsonb(v_problems),'[]'::jsonb)
  );
END; $$;

INSERT INTO dot_iu_command_catalog (command_name, category, mutating, reversible, target_functions, registered_at)
VALUES ('dot_iu_verify_cut_result', 'verify', false, false, ARRAY['fn_iu_verify_cut']::text[], now());

COMMIT;

Rollback 041

BEGIN;
DELETE FROM dot_iu_command_catalog WHERE command_name='dot_iu_verify_cut_result';
DROP FUNCTION IF EXISTS fn_iu_verify_cut(uuid,text);
COMMIT;

Mutating flag

mutating=false at DOT level: verify only writes one audit row in dot_iu_command_run — no IU pieces touched, no staging changes. The audit row is treated as durable telemetry, not data mutation.

  • 80000x doc 06 — three-axis requirements (definition source).
  • fn_iu_reconstruct_source — wire here optionally for V-recon byte-for-byte assertion in a future revision.
  • [[feedback-iu-sql-link-link-role-vocab-eleven]] — iu_sql_link.link_role='represents' for piece-collection edges.
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-90000x-mark-to-cut-automated-pipeline-hardening/06-verify-cut.md