D — Compose / Add / Remove / Reorder / Split / Merge / Render Evidence (2026-05-29)
D — Compose / Add / Remove / Reorder / Split / Merge / Render Evidence
Capability: build a new demo document from IU bricks; add/remove/reorder pieces; split one piece; merge two pieces; render; prove no production law IU mutated.
Verdict: PASS. Channel: governed BEGIN … ROLLBACK via workflow_admin. Persisted mutation: none (full rollback; exit==entry).
D.1 Method (safety envelope)
One transaction: SET LOCAL statement_timeout='60s'; SET LOCAL idle_in_transaction_session_timeout='120s'; then all steps, then ROLLBACK. Gates opened inside the transaction (functions see them open via own-write visibility); rollback guarantees no gate is ever committed open. All minted content lives in the TEST/iu-demo/* namespace. The full script is in 07-raw-sql-dot-appendix.md.
D.2 Functions used
fn_iu_test_review_decision_create(actor, reason, manifest_tag)→ test-scope Điều-32 artifact (NOT a production approval).fn_iu_gate_open(gate_key, approval_id uuid, actor, reason, ttl_seconds)/fn_iu_gate_close(...).fn_iu_compose(collection_key, collection_kind, title, description, pieces jsonb, actor).fn_iu_collection_add_piece / remove_piece / reorder_piece,fn_iu_collection_render.fn_iu_piece_split(source_canonical_address, child_specs jsonb, actor, review_decision_id, …).fn_iu_piece_merge(merged_spec jsonb, source_canonical_addresses text[], actor, review_decision_id, …).
D.3 Step-by-step evidence
D1 — Test review_decision (Điều 32 test-scope)
review_decision_id = d4448cbe-a5d3-4b0c-80e0-cdcbaca0e483, status test_review_decision_created. Used as gate approval_id and as review_decision_id for split/merge.
D2 — Gates opened
iu_core.composer_enabled → opened (ttl 300, approval d4448cbe…); iu_core.structure_ops_enabled → opened. (Both closed again in D11; both rolled back — net iu_gate_transition delta = 0.)
D3 — Compose
fn_iu_compose('TEST/iu-demo/compose-1','document','IU A-F Demo Composed Document', …, pieces, 'iu_demo_harness'):
{ ok:true, collection_id:990d8c79-6933-43ba-9e9b-086afd7b0a6b, pieces_attached:4, pieces_minted:3 }.
Pieces = 1 existing law brick (DIEU-37-v3.3#title, by iu_id) + 3 minted demo bricks (brick-alpha/beta/gamma).
Initial membership:
| ord | role | status | canonical_address |
|---|---|---|---|
| 0 | intro | active | DIEU-37-v3.3#title |
| 1 | body | active | TEST/iu-demo/brick-alpha |
| 2 | body | active | TEST/iu-demo/brick-beta |
| 3 | body | active | TEST/iu-demo/brick-gamma |
D4 — Add (existing law brick DIEU-37-v3.3#goal at order 4)
fn_iu_collection_add_piece(...) → {ok:true, piece_order:4, piece_role:appendix}. Membership now 5 rows (orders 0–4).
D5 — Remove (DIEU-37-v3.3#title)
fn_iu_collection_remove_piece(...) → {ok:true, detail:"membership removed (reversible); remaining pieces renumbered", piece_count:4}. The removed row becomes membership_status='removed' (reversible — not hard-deleted); active pieces renumbered 0–3.
D6 — Reorder (brick-beta → order 0)
fn_iu_collection_reorder_piece(...) → {ok:true, new_order:0, piece_count:4}. New active order: beta(0), alpha(1), gamma(2), DIEU-37#goal(3).
D7 — Split (brick-gamma → brick-gamma-1 + brick-gamma-2)
fn_iu_piece_split('TEST/iu-demo/brick-gamma', [2 child specs], 'iu_demo_harness', 'd4448cbe…'):
status: split_recorded, split_set_id: e735b594-3d7d-4780-a5c6-fb0007f7fcc1
child_iu_ids: [df624d90…, 3bfe6a68…], child_canonical_addresses: [TEST/iu-demo/brick-gamma-1, brick-gamma-2]
source_lifecycle_status: draft (SOURCE UNTOUCHED)
review_decision_id: d4448cbe… idempotency_key: 5bd54315…
Confirmed: source TEST/iu-demo/brick-gamma still present and draft (untouched); iu_split_set ledger row recorded with the review_decision. Children born draft via fn_iu_create (additive — source not auto-superseded).
D8 — Merge (brick-alpha + brick-beta → brick-merged)
fn_iu_piece_merge({merged_spec with explicit body}, ARRAY['TEST/iu-demo/brick-alpha','TEST/iu-demo/brick-beta'], 'iu_demo_harness', 'd4448cbe…'):
status: merge_recorded, merge_set_id: befc8de5-f235-4f4a-9891-3e2adb04b1f9
merged_iu_id: 7af27db2… source_iu_ids: [b88dddca…, ae31f8e3…] idempotency_key: a60005c4…
Merged body was author-supplied explicit (the function refuses to auto-concatenate). iu_merge_set ledger row recorded with the review_decision; sources untouched.
D9 — Render final document
fn_iu_collection_render(990d8c79…) returned the ordered active pieces:
(0, body, brick-beta, draft)
(1, body, brick-alpha, draft)
(2, body, brick-gamma, draft)
(3, appendix, DIEU-37-v3.3#goal, draft) ← source_ref dieu37 law file
D10 — Proof no production law IU mutated
- New
information_unitrows created in the tx (allTEST/iu-demo/*, alldraft):brick-alpha, brick-beta, brick-gamma, brick-gamma-1, brick-gamma-2, brick-merged(6 rows). No law canonical address among them. - Law pieces referenced by compose/add were never re-versioned:
DIEU-37-v3.3#title→ 1 version (max_seq 1);DIEU-37-v3.3#goal→ 1 version (max_seq 1). Composition references pieces via membership rows only — it never edits the piece body.
D4-counts In-tx deltas vs baseline
| iu | coll | memb | split_set | merge_set | |
|---|---|---|---|---|---|
| D0 baseline | 219 | 45 | 227 | 1 | 0 |
| D12 in-tx | 225 | 46 | 232 | 2 | 1 |
| D13 post-ROLLBACK | 219 | 45 | (227) | 1 | 0 |
Post-rollback TEST/iu-demo/* rows = 0. Nothing persisted. |
D.5 What a human can look at
The membership tables at each step (D3→D6) show the document being assembled and re-ordered live; the iu_split_set / iu_merge_set rows are the auditable governance ledger for the structural ops; the render output is the final assembled document. The post-rollback counts prove the demo left the database exactly as it found it.
D.6 Safety
Governed bounded-gate protocol; test-scope review_decision (no self-minted production approval); allow_no_review_decision never flipped; split/merge are additive (sources preserved); all work rolled back; gates closed and rolled back (net transition delta 0).