KB-5E49

10000x · 04 — Migration 028: Piece MERGE primitive (fn_iu_piece_merge + iu_merge_set)

3 min read Revision 1
iu-corev0.610000xmigration-028mergefn_iu_piece_mergeiu_merge_setcontent-policy

10000x · 04 — Migration 028: Piece MERGE primitive

File

sql/iu-core/028_piece_merge_primitive.sql (transactional). ~324 lines.

Substrate

Table public.iu_merge_set

id                          uuid PK DEFAULT gen_random_uuid()
merged_iu_id                uuid NOT NULL REFERENCES information_unit(id)
merged_canonical_address    text NOT NULL
source_iu_ids               uuid[] NOT NULL
source_canonical_addresses  text[] NOT NULL
actor                       text NOT NULL
review_decision_id          uuid NOT NULL
change_set_id               uuid
reason                      text
tool_revision               text
idempotency_key             text NOT NULL UNIQUE
created_at                  timestamptz NOT NULL DEFAULT now()
rolled_back_at              timestamptz
rolled_back_by              text
rolled_back_reason          text

CHECK (cardinality(source_iu_ids) = cardinality(source_canonical_addresses))
CHECK (cardinality(source_iu_ids) >= 2)
INDEX (merged_iu_id, created_at DESC)

Function public.fn_iu_piece_merge

(p_merged_spec               jsonb,
 p_source_canonical_addresses text[],
 p_actor                     text,
 p_review_decision_id        uuid,
 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
SECURITY DEFINER
SET search_path = pg_catalog, public

Refusal contract

Refusal Status
NULL actor invalid_input
NULL review_decision_id invalid_input
NULL merged_spec or non-object invalid_input
missing merged_spec.canonical_address invalid_input
missing / empty merged_spec.body invalid_input (content-policy refusal)
<2 sources invalid_input
duplicate source addresses invalid_input
merged_canonical = ANY(sources) invalid_input (forbids self-merge)
source IU not found source_iu_not_found
review_decision_id not in FK review_decision_not_found

Content policy

Merged body MUST be explicit in p_merged_spec.body. The function refuses to concatenate or otherwise synthesise content from sources — preventing fake content that would not match any human authorisation. For intentionally empty merged body, pass body='__EMPTY__' (stored verbatim).

This is the strongest divergence from naive "merge = concat sources" implementations.

Why sources are NOT auto-superseded

Same reasoning as 027. After merged piece is enacted, operator invokes dot_iu_supersede_piece ONCE PER SOURCE.

Live apply

BEGIN
CREATE TABLE
CREATE INDEX
COMMENT
CREATE FUNCTION
COMMENT
COMMIT

Rollback file

sql/iu-core/rollback/028_piece_merge_primitive.rollback.sql — drops function, index, table in safe order.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-10000x-piece-platform-dot-lifecycle-open-goal/04-merge-migration-028.md