P2B-P1 — IU Pilot INSERT + Birth Fire Verification Prompt
P2B-P1 — IU Pilot INSERT + Birth Fire Verification Prompt
Date: 2026-05-05 | Status: PROMPT rev2 — chờ GPT/User approve trước dispatch Controlling: P2B-P0 report + GPT P2B-P0 review + GPT P2B-P1 rev1 review (6 patches) + Pack 2B design (file 19) Scope: 1 IU row + 1 UV row trong 1 transaction. Verify birth fire. HARD STOP.
§0. Mission
Tạo đúng 1 pilot IU row + 1 unit_version row. Verify birth trigger fire. Upload report. HARD STOP.
§1. Connection
docker exec -i postgres psql -U directus -d directus
§2. Preflight — chạy TRƯỚC mọi mutation
2.1 Baselines
SELECT 'iu' AS tbl, count(*) FROM information_unit
UNION ALL SELECT 'uv', count(*) FROM unit_version
UNION ALL SELECT 'iu_birth', count(*) FROM birth_registry WHERE collection_name='information_unit'
UNION ALL SELECT 'uv_birth', count(*) FROM birth_registry WHERE collection_name='unit_version';
Expected: IU=0, IU_birth=0. UV và UV_birth capture baseline. Nếu IU hoặc IU_birth ≠ 0 → STOP, report anomaly.
2.2 Trigger exists
SELECT tgname FROM pg_trigger
WHERE tgrelid='information_unit'::regclass AND tgname='trg_birth_information_unit' AND NOT tgisinternal;
Expected: 1 row. Nếu 0 → STOP.
2.3 Audit baselines
SELECT md5(pg_get_functiondef('fn_birth_registry_auto'::regproc)) AS fn_hash;
SELECT count(*) AS birth_trigger_count FROM pg_trigger WHERE tgname LIKE 'trg_birth_%' AND NOT tgisinternal;
SELECT count(*) AS total_birth_count FROM birth_registry;
Ghi nhận fn_hash, birth_trigger_count, total_birth_count. Dùng so sánh sau INSERT.
2.4 Vocab values — QUAN TRỌNG
SELECT key, value,
CASE
WHEN key LIKE 'vocab.unit_kind.%' THEN replace(key, 'vocab.unit_kind.', '')
WHEN key LIKE 'vocab.section_type.%' THEN replace(key, 'vocab.section_type.', '')
WHEN key LIKE 'vocab.publication_type.%' THEN replace(key, 'vocab.publication_type.', '')
END AS vocab_token
FROM dot_config
WHERE key LIKE 'vocab.unit_kind.%'
OR key LIKE 'vocab.section_type.%'
OR key LIKE 'vocab.publication_type.%'
ORDER BY key;
Agent phải dùng vocab_token (key suffix) cho unit_kind và primary_section_type_ref.
Không dùng value column. Không tự tạo vocab.
2.5 Canonical address absent
SELECT count(*) FROM information_unit WHERE canonical_address='pilot.iu0.test-001';
Expected: 0. Nếu non-zero → STOP. Không tự tăng số.
2.6 Hash function availability
SELECT to_regprocedure('digest(text,text)') AS digest_text,
to_regprocedure('digest(bytea,text)') AS digest_bytea,
to_regprocedure('sha256(bytea)') AS sha256_bytea;
Ưu tiên dùng:
encode(digest(v_body, 'sha256'), 'hex')nếudigestcóencode(sha256(v_body::bytea), 'hex')nếu chỉ cósha256(bytea)- Nếu không có function nào → STOP, report. Không dùng md5 thay thế.
§3. Execute — single transaction
Thay <UNIT_KIND> và <SECTION_TYPE> bằng giá trị thật từ §2.4.
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- Step 1: Generate UUIDs
DO $$
DECLARE
v_iu_id uuid := gen_random_uuid();
v_uv_id uuid := gen_random_uuid();
v_body text := 'Pilot content for information unit test 001. This is a controlled test row created by Pack 2B-P1.';
v_hash text;
BEGIN
-- Compute content_hash from body (dùng function từ §2.6 preflight)
-- Nếu digest() có: v_hash := encode(digest(v_body, 'sha256'), 'hex');
-- Nếu sha256() có: v_hash := encode(sha256(v_body::bytea), 'hex');
v_hash := encode(digest(v_body, 'sha256'), 'hex'); -- ADJUST theo §2.6 result
-- Step 2: INSERT information_unit
INSERT INTO information_unit (
id, canonical_address, unit_kind, owner_ref,
created_by, updated_by, identity_profile
) VALUES (
v_iu_id,
'pilot.iu0.test-001',
'<UNIT_KIND>',
'pilot.owner.iu0',
'agent:p2b-p1',
'agent:p2b-p1',
jsonb_build_object(
'title', 'Pilot IU Test 001',
'owner_lookup_ref', 'pilot.owner.iu0',
'primary_section_type_ref', '<SECTION_TYPE>'
)
);
-- Step 3: INSERT unit_version
INSERT INTO unit_version (
id, unit_id, body, content_hash, version_seq, created_by
) VALUES (
v_uv_id,
v_iu_id,
v_body,
v_hash,
1,
'agent:p2b-p1'
);
-- Step 4: UPDATE anchors
UPDATE information_unit
SET version_anchor_ref = v_uv_id,
content_anchor_ref = v_uv_id::text
WHERE id = v_iu_id;
-- Step 5: Pre-commit sanity check (L2 fires at COMMIT, this is extra safety)
PERFORM 1 FROM information_unit WHERE id = v_iu_id AND version_anchor_ref = v_uv_id;
IF NOT FOUND THEN RAISE EXCEPTION 'Pre-commit: anchor link failed'; END IF;
PERFORM 1 FROM unit_version WHERE id = v_uv_id AND unit_id = v_iu_id;
IF NOT FOUND THEN RAISE EXCEPTION 'Pre-commit: UV link failed'; END IF;
-- Output IDs for post-verify
RAISE NOTICE 'IU_ID=%', v_iu_id;
RAISE NOTICE 'UV_ID=%', v_uv_id;
RAISE NOTICE 'CONTENT_HASH=%', v_hash;
END $$;
COMMIT;
Nếu transaction FAIL → no state persists. Ghi nguyên error vào report. STOP. Nếu COMMIT success nhưng post-verify fail → STOP ngay. Upload state snapshot + cleanup draft. Không insert lần 2, không sửa tay, không cleanup tự động.
§4. Post-verify — chạy SAU COMMIT thành công
4.1 IU row exists
SELECT id, canonical_address, unit_kind, owner_ref, lifecycle_status,
conformance_status, version_anchor_ref, content_anchor_ref,
identity_profile, created_by
FROM information_unit
WHERE canonical_address = 'pilot.iu0.test-001';
4.2 UV row linked
SELECT uv.id, uv.unit_id, uv.body, uv.content_hash, uv.version_seq, uv.lifecycle_status
FROM unit_version uv
JOIN information_unit iu ON uv.unit_id = iu.id
WHERE iu.canonical_address = 'pilot.iu0.test-001';
4.3 Birth fire verification
SELECT entity_code, collection_name, born_at, created_at
FROM birth_registry
WHERE collection_name = 'information_unit'
ORDER BY born_at DESC LIMIT 5;
4.3b Birth entity_code join verify (chứng minh IU id thật khớp birth row)
SELECT iu.id,
br.entity_code,
('information_unit::' || iu.id::text) AS expected_entity_code,
br.entity_code = ('information_unit::' || iu.id::text) AS entity_code_ok
FROM information_unit iu
JOIN birth_registry br
ON br.collection_name='information_unit'
AND br.entity_code = 'information_unit::' || iu.id::text
WHERE iu.canonical_address='pilot.iu0.test-001';
Expected: exactly 1 row, entity_code_ok = true.
4.4 UV birth check (subordinate = no birth)
SELECT count(*) AS uv_birth_count
FROM birth_registry WHERE collection_name = 'unit_version';
Expected: 0 (UV is subordinate, no birth trigger).
4.5 Invariants unchanged
SELECT md5(pg_get_functiondef('fn_birth_registry_auto'::regproc)) AS fn_hash;
SELECT count(*) AS birth_trigger_count FROM pg_trigger WHERE tgname LIKE 'trg_birth_%' AND NOT tgisinternal;
So sánh với baselines §2.3:
- fn_hash PHẢI giống
- birth_trigger_count PHẢI giống (31)
4.6 Counts delta
SELECT 'iu' AS tbl, count(*) FROM information_unit
UNION ALL SELECT 'uv', count(*) FROM unit_version
UNION ALL SELECT 'iu_birth', count(*) FROM birth_registry WHERE collection_name='information_unit'
UNION ALL SELECT 'uv_birth', count(*) FROM birth_registry WHERE collection_name='unit_version'
UNION ALL SELECT 'total_birth', count(*) FROM birth_registry;
Expected deltas vs baselines:
- IU: 0→1 (hard invariant)
- UV: baseline→baseline+1 (hard invariant)
- IU_birth: 0→1 (hard invariant)
- UV_birth: unchanged (hard invariant)
- total_birth: capture, audit/drift only — KHÔNG dùng làm hard gate
§5. Report format
Upload tại:
knowledge/dev/laws/dieu44-trien-khai/reports/19-p2b-p1-iu-pilot-insert-and-birth-fire-report.md
Report sections:
- Preflight results — baselines, vocab values chọn, canonical check
- Transaction result — SUCCESS hoặc FAIL + error
- IU row snapshot — full row
- UV row snapshot — full row
- Birth registry snapshot — entity_code, born_at
- Invariant comparison — fn_hash before/after, trigger count before/after
- Counts delta table — before/after cho mỗi bảng
- Pass/Fail summary — checklist:
- IU row exists with correct canonical_address
- UV row exists with unit_id = IU.id
- IU.version_anchor_ref = UV.id
- IU.content_anchor_ref = UV.id::text
- Birth registry has 1 new row for information_unit
- entity_code = information_unit::<iu_uuid>
- UV birth count unchanged
- fn_hash unchanged
- birth_trigger_count unchanged
- Cleanup SQL draft (chỉ draft, KHÔNG execute):
-- CLEANUP (DO NOT RUN unless approved)
BEGIN;
UPDATE information_unit
SET version_anchor_ref=NULL, content_anchor_ref=NULL
WHERE canonical_address='pilot.iu0.test-001';
DELETE FROM unit_version
WHERE unit_id IN (
SELECT id FROM information_unit WHERE canonical_address='pilot.iu0.test-001'
);
DELETE FROM birth_registry
WHERE collection_name='information_unit'
AND entity_code IN (
SELECT 'information_unit::' || id::text
FROM information_unit
WHERE canonical_address='pilot.iu0.test-001'
);
DELETE FROM information_unit
WHERE canonical_address='pilot.iu0.test-001';
COMMIT;
- Hard-stop confirmation: "P2B-P1 COMPLETE. HARD STOP. Chờ GPT/User review."
§6. Hard boundaries — TUYỆT ĐỐI
- ❌ NO schema changes (no ALTER, no CREATE)
- ❌ NO trigger/function changes
- ❌ NO DOT-119 changes
- ❌ NO raw birth_registry insert
- ❌ NO unit_version birth trigger creation
- ❌ NO Pack 2C/vector/outbox/Qdrant
- ❌ NO Directus exposure
- ❌ NO P3/HC
- ❌ NO cleanup execution (draft only)
- ❌ NO second IU row — chỉ 1 pilot row
- ❌ NO vocab creation — dùng vocab có sẵn
Nếu bất kỳ bước nào fail → ghi nguyên lỗi, STOP. Không tự sửa.
§7. Sau report
Upload report → DỪNG. Không tạo IU row thứ 2. Không cleanup. Không tiếp Pack 2C. Chờ review.
P2B-P1 prompt rev2 | 2026-05-05 | Opus 4.6 + GPT review 6 patches | 1 IU + 1 UV pilot. Birth fire verify. HARD STOP.