KB-1BE6
dot-iu-cutter v0.5 — S2 Planner Commit & Writer Design Bridge · Production Writer Mapping Design Brief (doc 3)
9 min read Revision 1
dot-iu-cutterv0.5s2-planner-commit-and-writer-design-bridgewriter-mapping-design-briefinformation-unitunit-versionbirth-gatevocabdieu442026-05-19
dot-iu-cutter v0.5 — Production Writer Mapping Design Brief
doc 3 of 5 · 2026-05-19 ·
design / doc only — NO writer code authored this phaseSchema + vocab re-verified live, READ-ONLY. This brief is the hand-off so a separately gated code-authoring phase can build the writer. Nothing here authorizes a production write.
1. Verified production target (read-only re-confirmation)
public.information_unit: PK id uuid · UNIQUE(canonical_address) · FK version_anchor_ref ->
unit_version(id) DEFERRABLE INITIALLY DEFERRED · constraint trigger trg_iu_birth_gate_layer2.
cols incl: canonical_address, unit_kind, lifecycle_status, owner_ref, conformance_status,
identity_profile jsonb, content_anchor_ref, version_anchor_ref, parent_or_container_ref,
doc_code, section_type, section_code, sort_order, created_by, updated_by.
public.unit_version: id uuid · unit_id uuid NOT NULL (-> IU) · body text NOT NULL ·
content_hash text NOT NULL · version_seq int NOT NULL · lifecycle_status text NOT NULL ·
content_profile jsonb NOT NULL · created_by NOT NULL · title? description? review_state?
provenance? editor? enacted_at? updated_at?
birth_gate_L1 (BEFORE INSERT, fn_iu_birth_gate_layer1): requires non-empty
canonical_address, unit_kind, lifecycle_status, owner_ref, conformance_status;
unit_kind ∈ dot_config 'vocab.unit_kind.<v>'; identity_profile.title,
.owner_lookup_ref, .primary_section_type_ref (∈ 'vocab.section_type.<v>') required;
.publication_type_ref (if set) ∈ 'vocab.publication_type.<v>';
.publication_authority_ref / .publication_type_ref: currently RAISE WARNING
'PILOT-ONLY … production sẽ BLOCK' ⇒ TREAT AS MANDATORY for the Constitution prod CUT.
birth_gate_L2 (DEFERRED @ COMMIT, fn_iu_birth_gate_layer2): content_anchor_ref non-empty;
version_anchor_ref NOT NULL; a unit_version row WHERE id=version_anchor_ref AND
unit_id=IU.id; content_anchor_ref == version_anchor_ref::text.
existing_state: 98 IU rows (unit_kind: law_unit=86, design_doc_section=12);
0 ICX-CONST rows ⇒ the 60 Constitution IUs are a CLEAN insert today.
2. dot_config vocab — CURRENTLY SEEDED (read-only, 18 keys) → GAP-W3 largely RESOLVED
vocab.unit_kind.*: law_unit, design_doc_section
vocab.section_type.*: appendix, article, changelog, checklist, definition,
governance_process, heading, instruction_block, paragraph,
principle, process, section, technical_spec
vocab.publication_type.*: law, design_doc
vocab.publication_authority.*: incomex_council
implication: the internal Constitution is law → the mapping below uses ONLY already-seeded
vocab (law_unit / article|principle|section / law / incomex_council). NO new dot_config
seeding is required for the recommended mapping ⇒ GAP-W3 reduces to a one-line
CONFIRMATION precheck, not a seeding sub-phase. (If GPT picks a different unit_kind/
section_type not in the lists above, THEN a separately gated vocab seed is needed.)
3. Minimal recommended mapping: cut-plan row → information_unit + unit_version
For each of the 60 accepted candidates (from cutplan iu_mapping / idempotency_keys):
information_unit:
id: new uuid (writer-generated)
canonical_address: candidate.canonical_address VERBATIM (ICX-CONST/<path>; N-4: no
renumber/normalise). UNIQUE ⇒ doubles as collision guard.
unit_kind: "law_unit" # in vocab; matches 86 existing law rows
lifecycle_status: "enacted" # scope is enacted_only; map effective_status
# (NGUYEN_TAC/KT/DIEU all 'enacted' here)
owner_ref: "incomex_council"
conformance_status: "open" # matches existing IU convention
doc_code: "ICX-CONST"
section_type / section_code: from level (see §4 N-2) / candidate number
parent_or_container_ref: per the hierarchy in §4 (NGUYEN_TAC/KIEN_TRUC_SECTION → DIEU)
identity_profile (jsonb):
title: candidate human title (from manifest unit heading)
owner_lookup_ref: "incomex_council"
primary_section_type_ref: NGUYEN_TAC→"principle" · KIEN_TRUC_SECTION→"section" ·
DIEU→"article" # all in vocab
publication_type_ref: "law"
publication_authority_ref: "incomex_council"
provenance: { source_document_version_id: icxconst-008a06ace23a96ea6cd456146e805c97,
manifest_digest: 9d908a62…, span_sha256: <candidate.content_hash>,
snapshot_region_sha256: 17660443… }
unit_version:
id: new uuid ; unit_id = IU.id ; version_seq = 1
body: the candidate's source text slice (from the pinned snapshot region by
source_span line_start..line_end) — deterministic, byte-pinned
content_hash: candidate.content_hash (== manifest span_sha256)
lifecycle_status: "enacted"
content_profile (jsonb): { level, source_span, source_document_version_id,
manifest_digest }
created_by/provenance: cutter_exec principal + DOT-991 (when credential cycle exists)
post_anchor (same txn, sanctioned birth pattern, NOT v0.4 append-only):
UPDATE information_unit SET version_anchor_ref = unit_version.id,
content_anchor_ref = unit_version.id::text WHERE id = IU.id
4. The N-2 granularity decision (RECOMMENDATION; GPT/User to rule — see doc 4)
recommended: emit ALL 3 levels as information_unit rows (NOT drop NGUYEN_TAC/KIEN_TRUC):
- keeps cardinality == 60 == manifest candidate_count (invariant I-4) exact;
- preserves the proven reconstruction closure (229+10+69=308);
- unit_kind = law_unit for all 60; differentiate by primary_section_type_ref
(principle / section / article) + parent_or_container_ref hierarchy:
NGUYEN_TAC → top-level principle units (no parent or doc-root parent)
KIEN_TRUC_SECTION → section containers (parent = doc root)
DIEU → article units, parent_or_container_ref → owning KIEN_TRUC_SECTION
(or doc root if structurally top-level), per the manifest's address path
alternative (if GPT rules NGUYEN_TAC/KIEN_TRUC are pure containers): then either still
create them as container IU rows (recommended, keeps 60 + reconstruction) OR exclude
them from IU and only cut 42 DIEU — the latter CHANGES the pinned candidate_count and
MUST be an explicit GPT ruling (it contradicts I-4 as currently pinned). Recommended:
keep all 60 as IU rows.
5. Idempotency / collision / transaction / rollback model for the writer
idempotency_key: reuse the committed cutplan OD-1 key
= sha256(canon(source_document_version_id, canonical_address, content_hash));
the writer persists a per-IU idempotency ledger and checks it + UNIQUE(canonical_address)
BEFORE insert. Re-CUT of the same manifest digest ⇒ no-op (G-CUT-ONCE), never duplicate.
collision_guard: UNIQUE(canonical_address) is the hard DB backstop; the writer must
pre-check existence (by manifest_digest + address) and treat any pre-existing ICX-CONST
row set as "already cut" ⇒ STOP/no-op, never blind INSERT.
transaction: ONE atomic transaction for the whole 60 (or a documented batched-but-atomic
scheme); deferred constraint trigger L2 fires at COMMIT; any L1/L2 RAISE ⇒ full abort,
zero rows (clean all-or-nothing). No partial cut.
rollback: pre-commit = transaction abort (zero rows). post-commit correction =
governed forward-compensation (superseding unit_version / lifecycle_status change),
never physical DELETE. Source/snapshot immutable & pinned.
6. What this brief deliberately does NOT do
- NO writer code authored (design/doc only, per the phase nature + GPT W-track ruling).
- NO production command invented; NO CUT/VERIFY; NO DB/IU write; NO vocab seed executed.
- The mapping above is a PROPOSAL; §4 + doc 4 list the decisions GPT/User must rule
before code-authoring (W-3) may begin.
doc 3 of 5. Design only. No production mutation. Self-advance PROHIBITED.