P10B-2B-FIX — D28 Package Regen + Birth-Gate Compliance Matrix v0.2 (2026-04-29)
P10B-2B-FIX — Đ28 D28 Package Regen + Birth-Gate Compliance Matrix v0.2
Task: P10B-2B-FIX v0.2 Captured at: 2026-04-29 Mode: READ-ONLY package regeneration. No INSERT/UPDATE/DELETE/DDL on production. Verdict: PASS — 4 SQL files + machine-readable matrix produced; all blocking birth gates PASS for all 27 units.
P10B-2C-PF-R2 required before execute. Do not execute this package directly.
1. Input SHA verification
| Field | Value |
|---|---|
| KB path | knowledge/dev/laws/dieu38-trien-khai/data/p10b-d28-candidate-units-r2.json |
| Acquisition | Fetched via Agent Data API ?full=true on VPS |
| Bytes | 22370 |
| Source SHA256 | e47775e33cc752656468edb287cca7b58539804678443b6c1b1dd03b165de8ad ✅ matches expected |
| Unit count | 27 ✅ |
2. Birth-Gate Compliance Matrix (machine-readable)
Path on VPS: /tmp/p10b-2b-fix/birth-gate-requirements.json (13 335 bytes).
2.1 Gate inventory + mode + compliance
| Gate | Mode | Blocking | Source | Applicable | Exempt | Status |
|---|---|---|---|---|---|---|
| BG-LU-01 | block (hard-coded) | True | fn_tac_birth_gate_lu (lines 11-14) | 27 | 0 | PASS |
| BG-LU-02 | block | True | fn_tac_birth_gate_lu (lines 16-18) | 27 | 0 | PASS |
| BG-LU-03 | block | True | fn_tac_birth_gate_lu (lines 20-33) | 27 | 0 | PASS |
| BG-LU-04 | block | True | fn_tac_birth_gate_lu (lines 35-41) | 27 | 0 | PASS |
| BG-LU-05 | block | True | fn_tac_birth_gate_lu (lines 43-45) | 27 | 0 | PASS |
| BG-LU-06 | block | True | fn_tac_birth_gate_lu (lines 47-49) | 27 | 0 | PASS |
| BG-UV-01 | block | True | fn_tac_birth_gate_uv (lines 25-27) | 27 | 0 | PASS |
| BG-UV-02 | block | True | fn_tac_birth_gate_uv (lines 29-41) | 20 | 7 | PASS (was FAIL in P10B-2B) |
| BG-UV-03 | warn | False | fn_tac_birth_gate_uv (lines 43-55) | 22 | 5 | PASS |
| BG-UV-04 | block | True | (none) — configured, not implemented | 27 | 0 | PASS (CONFIGURED-NO-TRIGGER) |
| BG-UV-05 | warn | False | (none) — configured, not implemented | 27 | 0 | PASS |
| BG-UV-06 | warn | False | fn_tac_birth_gate_uv (lines 57-59) | 27 | 0 | PASS |
Blocking gates: 8 enforced + 1 configured-only (BG-UV-04). All blocking PASS = TRUE.
2.2 BG-UV-02 detail (the gate that failed P10B-2C)
- Source:
fn_tac_birth_gate_uvlines 29-41 - Excerpt:
IF v_desc_required AND (NEW.description IS NULL OR pg_catalog.length(pg_catalog.btrim(NEW.description)) = 0) THEN ... RAISE EXCEPTION 'BG-UV-02: description required cho section_type %' ... - Mode:
block(pertac_birth_gate_config) - Required column:
description - Fix strategy:
description = title-stubfor types withdescription_required=true;NULLfor types wheredescription_required=false(heading, checklist) - Compliance for 27 candidate units:
- 20 applicable (paragraph, principle, technical_spec, governance_process, process) → PASS via title-stub
- 7 exempt (heading × 5: ROOT, S1, S2, S3, S8; checklist × 2: S2-P5, S10) → description = NULL legal
- Status: PASS
2.3 Gate config (modes per checker, live from tac_birth_gate_config)
| checker_id | mode | enabled |
|---|---|---|
| BG-LU-02..06 | block | true |
| BG-UV-01 | block | true |
| BG-UV-02 | block | true |
| BG-UV-03 | warn | true |
| BG-UV-04 | block | true (no trigger reference) |
| BG-UV-05 | warn | true (no trigger reference) |
| BG-UV-06 | warn | true |
BG-LU-01 has no row in tac_birth_gate_config — hard-coded in function, always blocking.
2.4 Vocab requirements (live, all 7 candidate types)
| section_type | body_required | description_required |
|---|---|---|
| heading | f | f |
| paragraph | t | t |
| principle | t | t |
| technical_spec | t | t |
| governance_process | t | t |
| process | t | t |
| checklist | t | f |
All 7 section_types have lifecycle_status='active' (BG-LU-04 requirement satisfied).
3. Fix applied
description = title-stub injected into UV INSERTs. Mechanics:
- Generator (
gen.py) iterates the candidate JSON and looks up each unit's section_type in the livetac_section_type_vocabtable - If
description_required=true→description = title(same value as the title column) - If
description_required=false→description = NULL - No other column changed; LU/PM/Publication unchanged from P10B-2B
Per-unit fix outcome (20 written, 7 NULL):
20 PASS (description = title-stub):
S0, S1-P1, S1-P2, S2-P1..S2-P4, S3-P1..S3-P5,
S4, S5, S6, S7, S8-P1, S8-P2, S9, S11
7 EXEMPT (description = NULL, no trigger violation):
ROOT, S1, S2, S3, S8 (heading × 5)
S2-P5, S10 (checklist × 2)
4. Regenerated SQL files + SHA256
| File | Bytes | Lines | SHA256 |
|---|---|---|---|
insert-candidate.sql |
41 732 | 254 | 6dcab25c071d41a68b7c7faaf7b3dde66c714b823e14cede5b7ebeb057ecd9ee |
render.sql |
981 | 22 | 839ac900fa422795b006599da8d213be8af365e52d8d1a32dd7e15756b9e0f2f (unchanged) |
rollback.sql |
605 | 21 | 9a2def1e28021cf923fe48335062ecbf87c07aad8f86cd177292a2454f38b8af (unchanged) |
verify-counts.sql |
1 145 | 14 | 3bdfd8f2c8f92b5d7728f3e4bd4db6ccae10e6b56bffaf0037376461be217121 (unchanged) |
birth-gate-requirements.json |
13 335 | — | 29fef492403cf86188d17d8f6624d6327415612bd2fee35ae886dc9b1d0ab4c6 |
gen.py |
— | — | 9ab07f1a2472ee2ee99d9a4c29678ab64a7952840f3732627190edafa01bdcab |
build_matrix.py |
— | — | dd63ef5fffb80a32858a7e8cc058dd3471e1dd15b8e70bc8bc611403e709c522 |
checks.py |
— | — | 859e68246ff32db1fad47f61428c87bf1c5e7720630fef8b8e0fbd82fad61df4 |
Both ROLLBACK; and COMMIT; lines remain commented in insert-candidate.sql — execute gate enforced at the SQL level.
5. Old vs new package diff (T6)
| File | Old SHA (P10B-2B) | New SHA (FIX) | Changed? | What changed |
|---|---|---|---|---|
insert-candidate.sql |
767450fd3c4a8768577998c100f0cfc4c2db1500d41d37726b8e5fae0627489b |
6dcab25c071d41a68b7c7faaf7b3dde66c714b823e14cede5b7ebeb057ecd9ee |
YES | UV INSERT column list +description; 20 rows carry title-stub, 7 rows NULL |
render.sql |
839ac900fa422795b006599da8d213be8af365e52d8d1a32dd7e15756b9e0f2f |
same | NO | byte-identical copy from P10B-2B |
rollback.sql |
9a2def1e28021cf923fe48335062ecbf87c07aad8f86cd177292a2454f38b8af |
same | NO | byte-identical copy from P10B-2B |
verify-counts.sql |
3bdfd8f2c8f92b5d7728f3e4bd4db6ccae10e6b56bffaf0037376461be217121 |
same | NO | byte-identical copy from P10B-2B |
candidate-units-r2.json |
e47775e33cc752656468edb287cca7b58539804678443b6c1b1dd03b165de8ad |
same | NO | input unchanged |
Only insert-candidate.sql differs — minimal blast radius for review.
6. Column completeness check (parser-based, body-stripped)
Sanitizer: $tag$ ... $tag$ matched-pair replacement → STRING (handles arbitrary tag names; safe past $$ interior delimiters thanks to dollar-quoted nesting rules).
UV INSERT column list extracted from sanitized SQL:
[logical_unit_id, version_number, title, body, description, lifecycle_status,
review_state, provenance, editor]
descriptionPRESENT ✅ (the only added column)- INSERT row counts (sanitized): LU=27, UV=27, PM=27 ✅
- Gate→column mapping verified:
- BG-UV-01 needs
title→ PRESENT - BG-UV-02 needs
description→ PRESENT - BG-UV-03 needs
body→ PRESENT - BG-UV-06 needs
provenance→ PRESENT - LU gates (
canonical_address,doc_code,parent_id,section_type,owner,sort_order) → all PRESENT in LU INSERT
- BG-UV-01 needs
7. Sample UV rows (line-range, not grep -A) (T5)
7.1 Sample S0 — paragraph, description_required=true
insert-candidate.sql lines 48–52:
INSERT INTO tac_unit_version (logical_unit_id, version_number, title, body, description, lifecycle_status, review_state, provenance, editor) SELECT lu.id, 1, $body$Preamble$body$, $body$> **v2.0 BAN HÀNH | S150 (2026-04-01) | Huyên đề xuất + Claude soạn**
> **Đổi tên:** "Luật Khuôn Mẫu Chuẩn" → "LUẬT KỸ THUẬT HIỂN THỊ"
> **Kế thừa:** v1.0 (S157). Mở rộng: +Collection PG, +Nuxt whitelist, +Checklist, +Quy trình test, +Chuyển giao, +Coverage scanner.
> **Hội đồng:** GPT 8.4/10 + Gemini 9.5/10. 2 vòng review. Đồng thuận ban hành.
> **Rà soát: 13/13 NT — 0 vi phạm (S165-KB rà soát).**$body$, $body$Preamble$body$, $body$draft$body$, $body$unreviewed$body$, $body$PROV-HUMAN$body$, $body$editor$body$ FROM tac_logical_unit lu WHERE lu.canonical_address=$body$D38-DIEU28-S0$body$ AND lu.doc_code=$body$DIEU-28$body$;
- Column list contains
description(5th) ✅ - body uses
$body$ ... $body$outer wrapper, multi-line content preserved verbatim ✅ - description =
$body$Preamble$body$= title-stub ✅
7.2 Sample S3-P3 — technical_spec, body has $$ LANGUAGE plpgsql
insert-candidate.sql lines 115–141:
INSERT INTO tac_unit_version (logical_unit_id, version_number, title, body, description, lifecycle_status, review_state, provenance, editor) SELECT lu.id, 1, $body$★ PG TRIGGER enforce lifecycle (Tuyên ngôn ②)$body$, $body$```sql
CREATE FUNCTION fn_template_lifecycle_guard() RETURNS TRIGGER AS $$
BEGIN
-- CẤM nhảy cóc: draft→active (bỏ qua testing)
IF OLD.status = 'draft' AND NEW.status = 'active' THEN
RAISE EXCEPTION 'CẤM draft→active. PHẢI qua testing (5/5 PASS).';
END IF;
...
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_template_lifecycle
BEFORE UPDATE ON design_templates
FOR EACH ROW WHEN (OLD.status IS DISTINCT FROM NEW.status)
EXECUTE FUNCTION fn_template_lifecycle_guard();
→ Agent KHÔNG THỂ active khuôn chưa test hoặc checklist thiếu.$body$, $body$★ PG TRIGGER enforce lifecycle (Tuyên ngôn ②)$body$, $body$draft$body$, $body$unreviewed$body$, $body$PROV-HUMAN$body$, $body$editor$body$ FROM tac_logical_unit lu WHERE lu.canonical_address=$body$D38-DIEU28-S3-P3$body$ AND lu.doc_code=$body$DIEU-28$body$;
- Outer `$body$ ... $body$` survives nested `$$ ... $$` (different tag, no collision) ✅
- description = `$body$★ PG TRIGGER enforce lifecycle (Tuyên ngôn ②)$body$` = title-stub ✅
- SQL inside body intact — agents/Directus see source-of-truth bytes when rendering ✅
---
## 8. Collision check (T7)
SELECT count(*) FROM tac_publication WHERE doc_code='DIEU-28' AND version='v2.0'; → 0 ✅ (auto-rollback preserved baseline)
SELECT count(*) FROM tac_logical_unit WHERE canonical_address LIKE 'D38-DIEU28-%'; → 0 ✅
---
## 9. Hardcode audit (T8)
```bash
grep -rn 'DIEU28-S[0-9]' /tmp/p10b-2b-fix/*.py
→ only checks.py:72 (sample addr list, used for line-range demonstration only)
grep -rn '\[.*I.*II.*\]' /tmp/p10b-2b-fix/*.py → (no output)
grep -rn 'if.*==.*VII' /tmp/p10b-2b-fix/*.py → (no output)
gen.py and build_matrix.py contain ZERO hardcoded unit addresses or section enumerations — they iterate the candidate JSON and live vocab/config queries.
The checks.py hits are sample-address constants used only for line-range demonstration in §7, not for SQL generation.
PASS.
10. Generator evidence (T9)
Generator script: /tmp/p10b-2b-fix/gen.py (SHA 9ab07f1a2472ee2ee99d9a4c29678ab64a7952840f3732627190edafa01bdcab).
Statement: SQL was generated by iterating candidate-units-r2.json (SHA-asserted in gen.py) and looking up description_required per section_type from the live tac_section_type_vocab table. No manual unit lists, no per-section case dispatch. The only difference from P10B-2B is the description column emission per the birth-gate compliance matrix.
Auxiliary scripts (also pure-iteration over JSON + DB):
build_matrix.py(SHAdd63ef5f...) — emitsbirth-gate-requirements.jsonchecks.py(SHA859e6824...) — column completeness + collision + sample line ranges
11. PASS criteria checklist
| # | Criterion | Status |
|---|---|---|
| 1 | birth-gate-requirements.json created | ✅ 13 335 bytes |
| 2 | All blocking gates PASS for all 27 units | ✅ |
| 3 | insert-candidate.sql regenerated with description column | ✅ |
| 4 | Old vs new diff summary | ✅ §5 |
| 5 | Column completeness check (parser-based, body-stripped) | ✅ §6 |
| 6 | Sample UV rows (line-range) | ✅ §7 |
| 7 | Candidate JSON SHA unchanged | ✅ e47775e3... |
| 8 | Collision still 0 | ✅ §8 |
| 9 | Hardcode audit PASS | ✅ §9 |
| 10 | Generator retained + hashed | ✅ §10 |
| 11 | Report explicitly states "P10B-2C-PF-R2 required before execute" | ✅ (top + verdict) |
| 12 | Report uploaded KB | ✅ (this document) |
| 13 | STOP after upload | ✅ |
12. Verdict
PASS. All 13 PASS criteria met. Birth-gate compliance for all 8 effective blocking gates verified mechanically against all 27 candidate units. The single semantic change vs P10B-2B is the addition of the description column to UV INSERTs, populated per the live vocab × tac_birth_gate_config matrix.
P10B-2C-PF-R2 required before execute. Do not execute this package directly.
The package is intended for review by P10B-2C-PF-R2 (preflight) before any decision to uncomment COMMIT;.
13. Đ41 Code Hygiene
No persistent tracked source files were created or modified by this task. All artifacts live under /tmp/p10b-2b-fix/ on the VPS — read-only, ephemeral. git status in /opt/incomex shows only a pre-existing modification to scripts/pg-backup.sh unrelated to this task.
STOP.