P10B-1B — Điều 32 Insert Package Generation (2026-04-29)
P10B-1B — Điều 32 Insert Package Generation v0.3
Captured: 2026-04-29 (UTC) Phiên: S189 Mode: READ-ONLY package generation. No INSERT/UPDATE/DELETE/DDL executed. Verdict: PASS — gói SQL sẵn sàng, chờ P10B-1C authorization để execute.
0. Inputs
| File | SHA256 |
|---|---|
knowledge/dev/laws/dieu32-approval-law.md (source) |
a42622496fff8c725932a5d310d1e4050e63e41828ba01c1eec4974c045e17f7 |
| Segmentation report (P10B-1A) | parsed in-memory |
| Hash report (P10B-1A-HASH) | parsed in-memory |
1. Source SHA256 verification
| Item | Value |
|---|---|
| Expected | a42622496fff8c725932a5d310d1e4050e63e41828ba01c1eec4974c045e17f7 |
| Computed | a42622496fff8c725932a5d310d1e4050e63e41828ba01c1eec4974c045e17f7 |
| Match | ✅ PASS |
2. candidate-units.json
| Item | Value |
|---|---|
| Path | /tmp/p10b-1b/candidate-units.json |
| Char count | 16,015 |
| SHA256 | b62d48a05149f62ee2e3b95dabda66d0180dc2155cb9650e302123d1332b7626 |
| Unit count | 23 (1 ROOT + 4 container headings + 18 leaf bodies) |
| Per-unit body SHA matches hash report | 23/23 ✅ |
Each unit object includes: canonical_address, parent, section_type, sort_order, title, body, body_sha256, expected_body_sha256, word_count, char_count, sha_match=true.
Body extraction strategy: heading regex parser (## §N\., ### §N\.M) on source markdown; preamble = consecutive > blockquote lines; CHANGELOG = ## CHANGELOG block. Heading-only containers (ROOT, S2, S3, S4) → empty body (SHA = e3b0c44…).
3. Schema discovery (T2)
| Table | Columns (key fields) |
|---|---|
tac_publication |
id (UUID, default gen_random_uuid), doc_code, version, publication_type, name, owner, lifecycle_status (default 'proposed'), risk_tier (default 'medium'), … |
tac_logical_unit |
id, canonical_address, doc_code, parent_id, sort_order, section_type, owner, lifecycle_status (default 'draft_only') |
tac_unit_version |
id, logical_unit_id, version_number (default 1), title, body, description, content_hash, lifecycle_status (default 'draft'), review_state (default 'unreviewed'), provenance (default 'PROV-AI'), length_flag, vector_sync_status |
tac_publication_member |
id, publication_id, logical_unit_id, unit_version_id, render_order |
LU constraints:
tac_logical_unit_canonical_address_keyUNIQUE (canonical_address)tac_logical_unit_sort_order_checkCHECK (sort_order >= 0)
Publication unique key: tac_publication_doc_code_version_key UNIQUE (doc_code, version) — adopted as collision business key.
4. Collision check (T3)
SELECT count(*) FROM tac_publication WHERE doc_code='DIEU-32' AND version='v1.1'; -- 0
SELECT count(*) FROM tac_logical_unit WHERE canonical_address LIKE 'D38-DIEU32-%'; -- 0
| Check | Result |
|---|---|
| Publication (doc_code, version) collision | 0 ✅ |
| LU canonical_address prefix collision | 0 ✅ |
Method: discovered key constraint via pg_constraint (UNIQUE on doc_code+version), then exact-match check. Slug not used.
5. Vocab verification (T4)
Lifecycle column inspection: only tac_publication_type_vocab and tac_section_type_vocab expose lifecycle_status.
| # | Vocab | Code(s) | Active |
|---|---|---|---|
| 1 | tac_publication_type_vocab |
law |
✅ active |
| 2 | tac_pub_lifecycle_vocab |
proposed |
✅ exists |
| 3 | tac_lu_lifecycle_vocab |
draft_only |
✅ exists |
| 4 | tac_uv_lifecycle_vocab |
draft |
✅ exists |
| 5 | tac_review_state_vocab |
unreviewed |
✅ exists |
| 6 | tac_section_type_vocab |
heading, paragraph, principle, technical_spec, governance_process, process, checklist, changelog | ✅ 8/8 active |
All 6 vocab loại verified — PASS.
6. Role verification (T5)
SELECT grantee, table_name FROM information_schema.role_table_grants
WHERE table_schema='public' AND table_name LIKE 'tac_%' AND privilege_type='INSERT';
| grantee | table | INSERT |
|---|---|---|
| directus | tac_publication | ✅ |
| directus | tac_logical_unit | ✅ |
| directus | tac_unit_version | ✅ |
| directus | tac_publication_member | ✅ |
Execution role directus has INSERT on all 4 target tables. PASS.
7. Trigger / birth gate analysis (T6)
| Trigger | Table | Owner | SECDEF | Purpose |
|---|---|---|---|---|
trg_tac_birth_gate_lu (fn_tac_birth_gate_lu) |
tac_logical_unit | directus | yes | BG-LU-01..06: canonical_address regex `^D38-[A-Z0-9]+-((ROOT) |
trg_tac_birth_gate_uv (fn_tac_birth_gate_uv) |
tac_unit_version | directus | yes | BG-UV-01..06: title required; description required (block) when section_type.description_required=true; body required (warn) when body_required=true |
trg_tac_uv_compute_derived |
tac_unit_version | directus | yes | Auto-fills content_hash (sha256) and length_flag |
trg_tac_enacted_immut |
tac_unit_version | directus | yes | Locks enacted versions |
trg_tac_pm_consistency |
tac_publication_member | directus | yes | Enforces pm.logical_unit_id == uv.logical_unit_id |
trg_tac_pm_enacted_lock |
tac_publication_member | directus | yes | Locks PM rows when publication enacted |
tac_birth_gate_config: BG-UV-02=block, BG-UV-03=warn (so description must be non-empty for paragraph/principle/technical_spec/governance_process/process; body can be empty in warn-mode).
Birth gate impact on insert plan:
- canonical_address scheme
D38-DIEU32-{ROOT|Sn|Sn-Pm}matches regex ✅ - All 23 unit section_types are active in vocab ✅
- INSERT must provide non-empty
owner('incomex_council' chosen) - INSERT must provide non-empty
descriptionfor UV → fallbackdescription = title(block-mode safe) content_hash&length_flagauto-derived (do not specify)
8. Generated SQL files (T7)
All emitted by emit_sql.py iterating candidate-units.json.
| File | Bytes | SHA256 |
|---|---|---|
insert-candidate.sql |
30,796 | 2b7566851c9e3bd3b7ffcc49377343f666bf1d5c0f8f131c501cc84f6cb82a0a |
render.sql |
998 | a44bda9725097371690b1d259cef114dcc47bdb55bfd51c57b5ff3862f92d106 |
rollback.sql |
1,336 | 42dba174bc4e9b6d68c267cf1f9e52eb43035c673f1e9e8fb8a122343e48464c |
verify-counts.sql |
694 | 65973b780312b77bf31935c71aa3e777d33de5263c14181223f4b59133c6def6 |
Layout:
insert-candidate.sql— single transaction (BEGIN; … ROLLBACK;default). Creates a session temp_d32_lu_map(canonical_address → lu_id, uv_id), then 1 publication INSERT + 23 LU INSERTs (depth-ordered: ROOT → S0..S9 → S2-P*, S3-P*, S4-P*) + 23 UV INSERTs + 23 PM INSERTs. Each LU insert resolvesparent_idvia subquery against_d32_lu_map. UVdescription=titlestub satisfies BG-UV-02. PMrender_order= preorder-DFS index. Trailing verification SELECTs run inside the same tx.render.sql— recursive CTE ontac_publication_member ⨝ tac_logical_unit ⨝ tac_unit_version, materialized-path ARRAY[render_order], preorder DFS viaORDER BY path. Scoped to publication(doc_code, version).rollback.sql— DELETE in reverse FK order (PM → UV → LU → publication), scoped toD38-DIEU32-%+(DIEU-32, v1.1). Ends with 4*_remcount SELECTs (expected 0,0,0,0). NULLsparent_idbefore deleting LUs to avoid FK contention if any.verify-counts.sql— 4 counts: pub=1, lu=23, uv=23, pm=23 (total 70).
9. Generator evidence (T8)
| Script | Path | SHA256 |
|---|---|---|
| Body extractor + JSON builder | /tmp/p10b-1b/generate.py |
2bedd56ddd2f73f0a8ceb33c56f8316a766cea07fe7a8075f5119281dfa120f8 |
| SQL emitter | /tmp/p10b-1b/emit_sql.py |
3b52ba81ee8effae9b636ee18887aa77732d1067021247199264fbf4834601d7 |
Statement: All SQL files were produced by the emitter iterating over candidate-units.json (loaded via json.loads) and the publication/units list. No manual editing of SQL after emission.
generate.py itself: parses the hash report markdown table (regex-driven), parses source headings (## §N\., ### §N\.M) algorithmically, and resolves bodies by source-region slicing — no hardcoded list of canonical_addresses for the 18 leaf bodies. The four anchor identifiers used as dict keys (D38-DIEU32-S0, D38-DIEU32-S9, plus the heading containers) correspond to the structurally non-§N sections (preamble blockquote, CHANGELOG, parent containers); these names attach extracted slices to the correct address.
10. Hardcode audit (T9)
Inspected: generate.py, emit_sql.py.
Method: three-pass grep:
- Narrow forbidden tokens:
s2_p1|s3_p2|s4_p3|leaf_heading_keys→ 0 hits ✅ - Bracketed array literal containing
DIEU32:\[.*DIEU32.*\]→ 8 hits ingenerate.py, all aredict[key]=…index assignments (NOT array literals); 0 hits inemit_sql.py. Each hit corresponds to one structurally-anomalous section (preamble S0, CHANGELOG S9, container headings ROOT/S2/S3/S4) that the regex pass cannot capture from a§Nheading. Allowed. - Literal canonical_address comparison
canonical_address\s*=\s*['"]D38→ 0 hits ✅
emit_sql.py references DIEU32 only in inline comments and in OUTPUT SQL strings (LIKE 'D38-DIEU32-%' scope filters and explicit doc_code='DIEU-32' literals routed through pub JSON object). All output values flow from candidate-units.json → no static unit array in generation logic.
Verdict: PASS — no manually enumerated unit array in generation scripts.
11. Verdict
| # | PASS criterion | Result |
|---|---|---|
| 1 | candidate-units.json with full body, SHA256 recorded | ✅ b62d48a0… |
| 2 | 4 SQL files emitted | ✅ |
| 3 | INSERT SQL schema-adaptive (columns from information_schema) | ✅ |
| 4 | Zero hardcode in generation logic | ✅ |
| 5 | Source SHA256 match | ✅ a4262249… |
| 6 | All 6 vocab verified active | ✅ |
| 7 | Collision check 0 existing rows | ✅ pub=0 lu=0 |
| 8 | Trigger / birth gate analysis documented | ✅ §7 |
| 9 | Execution role verified | ✅ directus has INSERT on all 4 |
| 10 | Generator script retained + hashed | ✅ §9 |
| 11 | Hardcode audit PASS (broad) | ✅ §10 |
| 12 | Report uploaded KB | ✅ (this file) |
| 13 | STOP after upload | ✅ no execution |
Overall: PASS. Awaiting GPT review → P10B-1C authorization to execute the package.
Appendix — body description fallback
tac_birth_gate_config shows BG-UV-02=block for description_required section_types (paragraph, principle, technical_spec, governance_process, process). The candidate-units corpus does not carry separate description fields. As a conservative non-empty stub, insert-candidate.sql sets description = title for every UV. P10B-1C reviewers may choose to refine descriptions before execution.
Appendix — known follow-ups for P10B-1C
- Decide whether
description = titlestub is acceptable or whether to author per-unit descriptions. - Decide
risk_tierfor the publication ('medium' default chosen). - Decide
ownervalue ('incomex_council' chosen — confirm). - Optionally pre-register
D38doc_code in anydoc_registryif such gate exists (not surfaced in this discovery; verify before execute).