KB-5A9B

P10B-1B — Điều 32 Insert Package Generation (2026-04-29)

12 min read Revision 1
p10bp10b-1bdieu-32dieu-38insert-packagesql-candidateread-onlys1892026-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_key UNIQUE (canonical_address)
  • tac_logical_unit_sort_order_check CHECK (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 description for UV → fallback description = title (block-mode safe)
  • content_hash & length_flag auto-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 resolves parent_id via subquery against _d32_lu_map. UV description=title stub satisfies BG-UV-02. PM render_order = preorder-DFS index. Trailing verification SELECTs run inside the same tx.
  • render.sql — recursive CTE on tac_publication_member ⨝ tac_logical_unit ⨝ tac_unit_version, materialized-path ARRAY[render_order], preorder DFS via ORDER BY path. Scoped to publication (doc_code, version).
  • rollback.sql — DELETE in reverse FK order (PM → UV → LU → publication), scoped to D38-DIEU32-% + (DIEU-32, v1.1). Ends with 4 *_rem count SELECTs (expected 0,0,0,0). NULLs parent_id before 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:

  1. Narrow forbidden tokens: s2_p1|s3_p2|s4_p3|leaf_heading_keys0 hits ✅
  2. Bracketed array literal containing DIEU32: \[.*DIEU32.*\] → 8 hits in generate.py, all are dict[key]=… index assignments (NOT array literals); 0 hits in emit_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 §N heading. Allowed.
  3. Literal canonical_address comparison canonical_address\s*=\s*['"]D380 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

  1. Decide whether description = title stub is acceptable or whether to author per-unit descriptions.
  2. Decide risk_tier for the publication ('medium' default chosen).
  3. Decide owner value ('incomex_council' chosen — confirm).
  4. Optionally pre-register D38 doc_code in any doc_registry if such gate exists (not surfaced in this discovery; verify before execute).