80000x · 05 — DOT contract: dot_iu_cut_from_manifest (CLI, G1-G7 guards, atomic txn, rollback)
05 — DOT contract: dot_iu_cut_from_manifest
The single command that consumes an approved manifest and durably creates IU rows. This document is the command-review contract; an
R1-style code-authoring micro-cycle is the carry-forward.
1. Identity
dot_command_name: dot_iu_cut_from_manifest
command_catalog_table: dot_iu_command_catalog # PK column: command_name
command_run_table: dot_iu_command_run # audit; column: command_name
governance_lane: DOT-991 (cutter executor) # parallel to v0.5 cutter_exec
verifier_lane: DOT-992 (cutter verifier) # invoked from VERIFY stage
The command must be registered in dot_iu_command_catalog before it is callable. Registration is a small migration (sketched in 10-carry-forward-to-implementation.md).
2. CLI shape
python -m cutter_agent.cut_from_manifest \
--manifest <path/to/approved_manifest.json> \
--approval-doc-id <kb-doc-id-of-the-review-record> \
--expect-manifest-digest <sha256> \
--principal workflow_admin \
--apply \
--reconstruct \
--verify \
--out-dir <ephemeral-scratch-dir>
Switches:
--apply(required): without this flag the command runs as a CUT-plan dry-run (emits the SQL that WOULD execute, writes nothing).--reconstruct(default on): after CUT, re-runsfn_iu_reconstruct_sourceand compares tomanifest.articles[].original_text_hash. FAIL ⇒ rolls back.--verify(default on): after CUT + reconstruct, runs the V1–V8 checks (see01 §5.3) and emitsverify_report.md. FAIL ⇒ rolls back viarollback_plan.json.--principal: must be the role that owns the IU-core tables; defaultworkflow_adminper 70000x channel discovery.
3. Required pins (the six identity locks; any mismatch ⇒ REFUSED)
G1 approval : --approval-doc-id resolves in KB to a record whose
`manifest_digest` matches the file's digest
G2 manifest digest : sha256(canonical(manifest)) == --expect-manifest-digest
G3 source identity : fresh fetch of source.url_or_file has hash == manifest.source.source_hash
OR --skip-source-refetch (only allowed for inline-text manifests)
G4 principal : current_user == --principal
G5 vocab drift : every section_type / unit_kind / piece_role / link_role
still present in live DB CHECK constraints
G6 cut-once : no information_unit row exists at any of the proposed
canonical_addresses (or, for an explicit version-update,
the prior version is in `enacted` state and supersedes-chain is valid)
G7 fresh backup : pg_dump within ≤ 60 min, sha logged in KB
If any G fails: exit code 2 (REFUSED), no DB connection opened, no SQL run.
4. Transaction model (one atomic txn)
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- For each articles[]:
-- one fn_iu_compose call with pieces_json built from manifest.articles[i].pieces[]
-- - 'new_piece' branch for every piece (mints + attaches)
-- - returns iu_piece_collection.id + minted iu_ids
SELECT fn_iu_compose(
p_collection_kind => 'design_doc_section',
p_collection_key => '<doc_code>/<article_label>',
p_pieces => '<jsonb array>',
p_actor => 'dot_iu_cut_from_manifest/<run_id>',
p_idempotency_key => md5('<approval_doc_id>'||':'||'<article_label>'||':v1')
);
-- For each piece in each article:
-- if axis_b.legal_document / professional_tags present, INSERT iu_metadata_tag rows
-- If any sql_bridge present: INSERT iu_sql_link (validator must return resolved=true)
-- Audit row
INSERT INTO dot_iu_command_run (
command_name, run_id, actor, args_json, status, started_at, finished_at
) VALUES (
'dot_iu_cut_from_manifest', <uuid>, '<operator>', '<args>', 'in_progress', now(), null
);
COMMIT;
Single atomic transaction; ROLLBACK on any failure within.
5. Idempotency
idempotency_key_per_article : md5(approval_doc_id || ':' || article_label || ':' || manifest_version_tag)
fn_iu_compose : returns existing iu_piece_collection.id on replay
(see [[feedback-idempotency-key-for-event-driven-compose]])
Replaying the exact same --manifest + --approval-doc-id produces zero new rows and exits 0 with idempotent_replay: true in the execution log.
6. Outputs
out_dir/cut_execution_log.md # operator-readable timeline
out_dir/cut_sql_emitted.sql # the actual SQL that ran (or would have, under --no-apply)
out_dir/iu_ids_created.json # mapping { local_piece_id -> iu_id, article_label -> iu_piece_collection_id }
out_dir/rollback_plan.json # retire/supersede plan keyed on manifest_id
out_dir/verify_report.md # V1..V8 results (only when --verify)
Upload all artifacts to:
knowledge/dev/laws/<doc-folder>/cut-runs/<UTC-timestamp>-<manifest_id>/
After upload, update the manifest's cut_record and (if VERIFY passes) verify_record, then write the updated manifest back to the approved-manifests KB path with approval.status = verified.
7. Rollback
rollback_plan.json lists, in reverse order:
iu_sql_linkrows to marklifecycle_status='retired';iu_metadata_tagrows to delete (NOT retire — tag rows are de-references, not durable IU);iu_piece_membershiprows to deactivate;iu_piece_collectionrow(s) tolifecycle_status='retired';information_unitrows (newly minted pieces) tolifecycle_status='retired'withsuperseded_by=null.
Rollback is forward-compensation, not DELETE: rows remain visible in the lifecycle log with a retired status and an actor tag identifying this CUT run. This matches the existing 11-gate IU-core retire/supersede invariants.
Run rollback with:
python -m cutter_agent.cut_rollback \
--manifest <approved_manifest.json> \
--plan <out_dir/rollback_plan.json> \
--principal workflow_admin \
--reason "<one-line reason: verify failed | operator request | …>" \
--apply
8. Forbidden inside CUT
DELETEon any IU-core table (use lifecycle retire instead).TRUNCATE(ever).- DDL of any kind.
GRANT/REVOKE.- writes to
production_documents. - writes to Qdrant (vector_sync is a separate, gated path).
- writes to
directus_filesor other Directus app tables. - enabling or disabling any
iu_core.*gate inside the CUT txn (use a separate operator step with explicit sign-off). --no-verify/--no-reconstructshortcuts unless the operator explicitly accepts that VERIFY will run as a separate, later step (rare; requires KB record of the deferral).
9. Exit codes
0 : PASS (apply + reconstruct + verify all green)
1 : ATOMIC_ABORT (TX rolled back; no rows written; reason logged)
2 : REFUSED (G1..G7 gate failed before any DB connect)
3 : VERIFY_FAILED (CUT applied but V1..V8 found a violation; rollback_plan.json emitted)
4 : ROLLBACK_NEEDED_BUT_NOT_APPLIED (operator must run cut_rollback explicitly)
10. Audit invariants
- Exactly one
dot_iu_command_runrow per execution. dot_iu_command_run.command_name = 'dot_iu_cut_from_manifest'.dot_iu_command_run.args_jsonincludes--approval-doc-id,--expect-manifest-digest, and themanifest_id.- Every minted
information_unitrow hascreated_by = 'dot_iu_cut_from_manifest/<run_id>'. - Every minted
iu_piece_membershiprow'sactorcolumn matches.
11. Carry-forward to implementation
This contract is the spec. The code does not yet exist; it must be authored as a separately-gated micro-cycle. See 10-carry-forward-to-implementation.md for the build list and migration sketch.