23-P3 — IU Edit Draft / Comment / Apply Implementation Design (rev5)
23-P3 — IU Edit Draft / Comment / Apply Implementation Design (rev5)
Date: 2026-05-06 Author: Opus (Claude) Status: DESIGN rev5 — chờ GPT/User review. Không implement. Model: PG-native editorial workflow — draft → comment → apply → official version. Supersedes: rev4 (foundation map), rev3 (8 patches), rev2, rev1. Rev5 patch: §15 Existing Implementation Compatibility / No-Duplicate Rule.
Framing
PG-native editorial workflow, không phải GitHub clone.
| Cũ (Git/PR) | Mới (Editorial) | Ghi chú |
|---|---|---|
| proposal | draft | Bản nháp sửa |
| merge | apply | Áp dụng draft thành bản chính |
| commit | official version | Bản unit_version đã apply |
| PR discussion | comment/review | Ghi chú, góp ý trên draft |
| branch | — | Không có. Draft = flat, không branch |
| 3-way merge | — | Không có Phase 1. Stale base = từ chối |
Nôm na: Sổ biên tập. Ai muốn sửa bài → viết bản nháp. Đồng nghiệp ghi chú góp ý. Tổng biên tập duyệt → bản chính tự cập nhật. Agent chỉ gọi hàm, PG lo mọi thứ bên dưới.
§1. Current Runtime Truth (từ 23-P2)
- information_unit: 15 cols. canonical_address UNIQUE NOT NULL, version_anchor_ref FK→UV (DEFERRABLE), identity_profile JSONB (GIN), lifecycle_status default 'draft'.
- unit_version: 9 cols. version_seq integer NOT NULL, UNIQUE(unit_id, version_seq), lifecycle_status default 'draft', content_profile JSONB (NO GIN).
- Gateway: exact match fn_iu_create. 9 dot_config keys.
- Data: 5 IU, 5 UV, all version_seq=1. Greenfield.
§2. Minimal Schema Design
2.1 unit_edit_draft
| Column | Type | Null | Default | Mục đích |
|---|---|---|---|---|
| id | uuid | NO | gen_random_uuid() | PK |
| unit_id | uuid | NO | — | FK → information_unit(id) |
| base_version_ref | uuid | NO | — | FK → unit_version(id) |
| base_content_hash | text | NO | — | Fast stale detect |
| draft_body | text | NO | — | Full replacement |
| draft_content_hash | text | NO | — | SHA-256 via fn_content_hash |
| draft_title | text | YES | NULL | NULL = giữ nguyên |
| draft_status | text | NO | 'open' | open / applied / stale_base / withdrawn |
| author_ref | text | NO | — | |
| reason | text | YES | NULL | Changelog |
| metadata | jsonb | NO | '{}' | |
| created_at | timestamptz | NO | now() | |
| applied_at | timestamptz | YES | NULL | |
| applied_by | text | YES | NULL | |
| applied_version_ref | uuid | YES | NULL | FK → UV tạo ra khi apply |
Constraints: PK, FK(unit_id→IU), FK(base_version_ref→UV), FK(applied_version_ref→UV), CHECK(draft_status). Indexes: btree(unit_id, draft_status), btree(base_version_ref).
2.2 unit_edit_comment
| Column | Type | Null | Default |
|---|---|---|---|
| id | uuid | NO | gen_random_uuid() |
| draft_id | uuid | NO | — |
| author_ref | text | NO | — |
| author_type | text | NO | 'agent' |
| comment_body | text | NO | — |
| comment_kind | text | NO | 'general' |
| target_path | text | YES | NULL |
| metadata | jsonb | NO | '{}' |
| created_at | timestamptz | NO | now() |
Constraints: PK, FK(draft_id→draft), CHECK(author_type), CHECK(comment_kind). Append-only.
2.3 sort_order
Core column trên information_unit. Gap numbering (10, 20, 30). Partial index WHERE parent IS NOT NULL.
2.4 Canonical path
Agent PHẢI dùng functions. Không direct INSERT draft/comment. Phase 1 convention, Phase 2 hardening.
§3. Function Surface
3.0 Security & Transaction
Atomic trong caller transaction. SECURITY DEFINER tất cả. search_path=pg_catalog,public. REVOKE PUBLIC. GRANT intended role.
3.0.1 Validation
Non-empty after trim cho address/body/actor/comment. Allow-listed enums cho author_type/comment_kind. Return JSON, không RAISE.
3.1 fn_iu_edit_plan — dry-run, read-only, no marker
3.2 fn_iu_create_edit_draft — INSERT draft only, no marker
3.3 fn_iu_comment_edit_draft — append-only comment, no marker
3.4 fn_iu_apply_edit_draft — core write, marker fn_iu_apply_edit_draft
Steps: validate → load draft → lock IU FOR UPDATE → stale check → no-change check → next seq → set marker → determine UV lifecycle (inspect at P3C) → INSERT UV → UPDATE IU anchors → title update → mark draft applied → mark others stale → system comment → verify invariants → return.
3.5 fn_iu_edit — wrapper, no own marker
Read policy → create_draft → auto_apply: apply → return. require_review: return draft_created.
3.6 fn_iu_withdraw_edit_draft — Phase 1.5 roadmap
Status catalog
edit_plan: plan_ok, iu_not_found, no_head_version, no_change, invalid_input. create_edit_draft: draft_created, iu_not_found, no_head_version, no_change, invalid_input. comment_edit_draft: comment_added, draft_not_found, invalid_input. apply_edit_draft: applied, stale_base, no_change, draft_not_found, draft_not_open, invariant_fail, invalid_input. edit: applied (auto), draft_created (require_review), + all above.
§4. Gateway Allow-list
2 markers: fn_iu_create + fn_iu_apply_edit_draft. fn_iu_edit = orchestrator, no marker. Patch: dot_config allowed_marker_values + ANY check. Fallback exact match.
§5–§8. Title / Stale Policy / Comments / Policy Model
(Unchanged from rev3–rev4. draft_title nullable + jsonb_set. Stale = mark_stale. Comments append-only + mandatory system comment on apply. Policy: dot_config + per-IU override.)
§9. Metadata Evolution Guardrails
Hot-path → column. Experimental → JSONB. GIN on demand. No hardcoded field lists. Governance Phase 2.
§10. Multi-Axis Composition
4 trục: document assembly (parent/child + sort_order), workflow assembly (parent/child + unit_kind), domain traceability (universal_edges UPPERCASE), release/render (deferred).
Parent/child = structural containment ONLY. Child edit ≠ parent version. Render = read-time assembly. Release snapshot = trục 4.
§11. Phase Plan
Near-term: P3A gateway → P3B schema → P3C functions → P3D edit pilot → P3E parent/child render pilot. Foundation hooks: P4 traceability, P5 release bundle, P6 semantic lint. Chưa execution. Next step: P3A.
§12. Risks / Open Decisions
(1–14 unchanged from rev4. All deferred risks non-blocking.)
§13. Text-as-Code Foundation Map
(Unchanged from rev4. 3 bảng: đã có, đang thêm, deferred.)
§14. Agent UX / Natural Operation Principle
Address-first. Agent chỉ cần: create/edit/comment/apply/read. Agent KHÔNG cần: version_seq, hash, anchor, marker, birth, direct writes.
§15. Existing Implementation Compatibility / No-Duplicate Rule
15.1 Current implemented assets — MUST NOT duplicate
| Asset | Type | Pack | Status |
|---|---|---|---|
| information_unit | Table | 22 | Production |
| unit_version | Table | 22 | Production |
| fn_iu_create | Function | 22 | Production, SECURITY DEFINER |
| fn_iu_create_plan | Function | 22 | Production, SECURITY DEFINER |
| fn_iu_verify_invariants | Function | 22 | Production, called by create + will be called by apply |
| fn_content_hash | Function | 22 | Production, called by create + will be called by draft |
| fn_iu_gateway_write_guard | Trigger function | 22 | Production, WILL BE PATCHED by P3A (allow-list) |
| trg_aa_iu_gateway_write_guard | Trigger on IU | 22 | Production, BEFORE INSERT OR UPDATE |
| trg_aa_uv_gateway_write_guard | Trigger on UV | 22 | Production, BEFORE INSERT OR UPDATE |
| trg_birth_information_unit | Trigger on IU | DOT-119 | Production, birth auto-fire |
| birth_registry | Table | Core | Production |
| collection_registry | Table | Core | Production |
| dot_config | Table | Core | Production, 9 iu_create.gateway.* keys |
| universal_edges | Table | Core | Production, 2199+ edges |
| Pilot IU/UV rows | Data | 22 | 5 IU, 5 UV, retained |
Rule: Pack 23 extends these. Pack 23 does NOT replace, rewrite, or create parallel versions of any of the above.
15.2 Execution preflight checklist
Trước MỖI execution prompt (P3A, P3B, P3C), Agent PHẢI chạy preflight và STOP nếu bất kỳ check nào fail:
PREFLIGHT CHECKLIST — copy vào mọi execution prompt:
□ TABLE CHECK: SELECT tablename FROM pg_tables WHERE tablename IN
('unit_edit_draft','unit_edit_comment');
→ Nếu tồn tại → STOP. Reconcile, không tạo mới.
□ FUNCTION CHECK: SELECT proname, pg_get_function_arguments(oid)
FROM pg_proc WHERE proname IN
('fn_iu_edit_plan','fn_iu_create_edit_draft',
'fn_iu_comment_edit_draft','fn_iu_apply_edit_draft','fn_iu_edit');
→ Nếu tồn tại với signature khác → STOP. Reconcile.
□ COLUMN CHECK: SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name='information_unit' AND column_name='sort_order';
→ Nếu tồn tại với type khác int4 → STOP.
□ DOT_CONFIG CHECK: SELECT key, value FROM dot_config
WHERE key IN ('iu_create.gateway.allowed_marker_values',
'iu_edit.default_apply_policy',
'iu_edit.stale_draft_action');
→ Nếu tồn tại với semantics khác → STOP. Reconcile.
□ GUARD SOURCE CHECK: SELECT md5(prosrc) FROM pg_proc
WHERE proname='fn_iu_gateway_write_guard';
→ Record hash BEFORE patch. Compare AFTER. Rollback nếu unexpected.
□ TRIGGER CHECK: SELECT tgname FROM pg_trigger
WHERE tgrelid='unit_edit_draft'::regclass;
→ Nếu trigger lạ tồn tại → STOP. Investigate.
(table chưa tồn tại thì skip check này)
□ CONSTRAINT CHECK: Verify proposed constraints không conflict
với existing constraints trên IU/UV.
Nếu tất cả PASS → proceed. Nếu bất kỳ FAIL → report, không execute.
15.3 No second edit system
Pack 23 KHÔNG tạo parallel system nếu runtime đã có primitive tương đương.
Cụ thể:
- Nếu phát hiện đã có bảng draft/edit/proposal trên schema → reconcile, không tạo bảng mới song song.
- Nếu phát hiện đã có function edit/merge/apply → reconcile hoặc extend, không viết function duplicate.
- Nếu phát hiện đã có comment/review table → evaluate reuse trước khi tạo mới.
Greenfield hiện tại (23-P2 confirmed) = không có primitive nào tương đương. Nhưng quy tắc này bảo vệ khi Agent chạy trong tương lai — nếu ai đó đã tạo trước, Agent không tạo thêm.
15.4 Compatibility with Pack 22 gateway
P3A PHẢI preserve:
| Behavior | Requirement |
|---|---|
| fn_iu_create qua gateway | Không break. fn_iu_create vẫn set marker, gateway vẫn accept. |
| Wrong-door blocking | Direct INSERT/UPDATE IU/UV vẫn bị chặn. |
| README guidance | Update README thêm edit/apply path, giữ wrong-door guidance. |
| Fallback | Nếu allowed_marker_values key bị xóa/missing → guard fallback exact match marker_value cũ → fn_iu_create vẫn hoạt động. |
| No half-enforced state | Patch phải atomic: key + guard logic cùng transaction. Nếu guard patch fail → không seed key. Nếu key seed fail → không patch guard. |
15.5 Compatibility with current schema conventions
P3B/P3C PHẢI discover và follow conventions hiện tại:
| Convention | Discover how | Apply to |
|---|---|---|
| UV lifecycle_status values | Inspect fn_iu_create source: giá trị nào set cho UV.lifecycle_status? | fn_iu_apply_edit_draft: match convention, không hard-decide |
| Naming/casing | Inspect existing table/column/function names | Tất cả new objects: snake_case, lowercase, fn_ prefix |
| Role/owner/grant | Inspect fn_iu_create owner + grants | Tất cả new functions: same owner, same grant pattern |
| Trigger naming | Inspect trg_aa_ prefix convention | Nếu thêm trigger trên draft/comment: follow convention |
| JSONB profile patterns | Inspect identity_profile keys trên pilot IU | draft metadata JSONB follow tương tự |
| Function return pattern | Inspect fn_iu_create return JSON structure | All new functions return consistent JSON |
15.6 Migration discipline
IU hiện greenfield nhưng non-empty (5 IU, 5 UV, 5 births):
| Rule | Lý do |
|---|---|
| Không cleanup pilot rows | Pilot data = evidence. Retain. |
| Không rewrite existing IU/UV rows | Pack 23 = additive, không retroactive. |
| DDL Phase 1 = additive only | CREATE TABLE, ALTER TABLE ADD COLUMN. Không DROP, không ALTER TYPE. |
| CREATE for new objects | unit_edit_draft, unit_edit_comment, new functions = CREATE. |
| CREATE OR REPLACE for patching existing functions | fn_iu_gateway_write_guard đã tồn tại, cần patch → CREATE OR REPLACE. Record source hash before + after. Rollback path = restore original source. |
| Nếu patch function: hash tracking | SELECT md5(prosrc) FROM pg_proc WHERE proname=... trước và sau. Report both. Rollback = restore nếu unexpected. |
| Không dùng OR REPLACE cho function MỚI | fn_iu_edit, fn_iu_create_edit_draft, etc. = CREATE (không OR REPLACE). Nếu đã tồn tại → preflight catch → STOP. |
15.7 Text-as-Code layer mapping — no duplication
| Layer | Đã có (Pack 22 + Core) | Pack 23 thêm | Rule |
|---|---|---|---|
| Identity | canonical_address, birth_registry, §0-AY | — | KHÔNG duplicate. Draft dùng FK → IU. |
| Versioning | unit_version, version_seq, content_hash | — | KHÔNG duplicate. Apply tạo UV qua existing table. |
| Registry | collection_registry, dot_config, birth_registry | Thêm dot_config keys cho edit policy | Extend dot_config, không tạo registry mới. |
| Gateway | fn_iu_gateway_write_guard, triggers | Patch guard → allow-list | Patch function cũ, không tạo guard mới. |
| Validation | fn_iu_verify_invariants, fn_content_hash | Gọi cả hai từ apply function | Reuse, không viết lại. |
| Graph | universal_edges | — Phase 1 | KHÔNG duplicate. Future traceability dùng existing edges. |
| Governance | GPT/User/Opus review cycle | Comment table = structured audit | Bổ sung, không thay thế review cycle. |
| Editorial edit | — (chưa có) | draft + comment + apply + wrapper | Layer MỚI. Đây là phần Pack 23 thực sự xây. |
Tóm lại: Pack 23 chỉ xây 1 layer mới (editorial edit). 7 layers còn lại = reuse/extend, không rebuild.
Hard boundaries toàn Pack 23
- Không DDL/DML trong design doc này
- Không runtime mutation
- Không function/trigger changes
- Không vector mutation
- Không cleanup
- Không Pack 2C
23-P3 rev5 | IU Edit Draft / Comment / Apply | 2026-05-06 | PG-native editorial workflow + text-as-code foundation + compatibility rule | Chờ GPT/User review