DOT-119 Repair P1 — Metadata DDL + Seed + PG Enforcement Report
DOT-119 Repair P1 — Metadata DDL + Seed + PG Enforcement Report
Date: 2026-05-05 Agent: Opus 4.7 (1M ctx) Controlling: 18b-P1 prompt rev 6 + 18a rev4 + 18b rev3 + GPT P1a decision Status: PASS — all gates green, COMMIT both transactions, fn_hash invariant preserved.
1. Bước 0 — Controlling docs read
Read on KB:
knowledge/dev/laws/dieu44-trien-khai/design/18a-dot119-metadata-driven-no-clobber-redesign.md(rev 4 FINAL)knowledge/dev/laws/dieu44-trien-khai/design/18b-dot119-repair-execution-pack.md(rev 3 PASS, umbrella)knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-review-dot119-p1a-schema-tool-inspection-and-p1-decision-2026-05-05.md(P1a + GPT P1 hybrid DDL decision: DOT-063 for fields)knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-review-p1-partial-stop-birth-registry-drift-and-restart-directive-2026-05-05.md(anti-hardcode note for live counts)- Prompt:
knowledge/dev/laws/dieu44-trien-khai/prompts/18b-p1-dot119-metadata-ddl-and-seed-prompt.md(rev 6)
Confirmed scope: 3 fields via DOT-063; metadata seed; PG enforcement. No DOT-119 execution, no script rewrite, no fn edit, no IU trigger/rows, no Pack 2B.
2. Bước 1 — Baselines (live)
| Check | Value | Gate |
|---|---|---|
| fields_existing (PG cols of 3 target names) | 0 | OK (≤0) |
| fn_birth_registry_auto md5 | 1f729b3571a74963089bb3ef388217f3 |
OK (matches expected) |
trigger_count (trg_birth_%) |
30 | baseline |
| birth_registry rows | 75469 | baseline |
3. Bước 2 — Env + path
- VPS: 38.242.240.89, postgres container
postgres, dbdirectus, userdirectus. set -a; . /opt/incomex/.env.local; set +a; . /opt/incomex/dot/config/environment.sh; init_environment --cloud→DIRECTUS_URL=https://directus.incomexsaigoncorp.vn, token length 64.dot-schema-applyresolved at/opt/incomex/dot/bin/dot-schema-apply(executable, 9440 bytes).
4. Bước 3 — DOT-063 field creation
4.1 Bước 3-pre — Inspect existing field template
GET /fields/collection_registry/collection_name returned meta with these boolean fields:
readonly: falsehidden: falserequired: truesearchable: true
sortable and filterable are not present in this Directus 11.x field meta schema. Spec written with the 4 detected booleans only (all set to false for new fields).
4.2 Bước 3a — Spec
File: /opt/incomex/dot/specs/collection_registry_birth_identity_fields.json
md5sum: 3a5a7b545258f8c544d2047870c726ea
3 fields, all string is_nullable: true:
birth_code_strategy—select-dropdownwith 6 choices (column/synthetic_id/legacy_id_single_colon/subordinate/disabled/unclassified)birth_code_column—inputtextbirth_identity_source—select-dropdownwith 5 choices (inferred_from_existing_trigger/manual/migration_seed/system_default/unclassified)
Boolean meta on each: readonly=false, hidden=false, required=false, searchable=false.
4.3 Bước 3b — Dry-run
DOT SCHEMA APPLY v1.0.0 — Mode: DRY RUN
Would create: birth_code_strategy
Would create: birth_code_column
Would create: birth_identity_source
Summary: Created 3, Skipped 0, Failed 0.
4.4 Bước 3c — Live
DOT SCHEMA APPLY v1.0.0 — Mode: LIVE
✅ Created: birth_code_strategy
✅ Created: birth_code_column
✅ Created: birth_identity_source
Summary: Created 3, Skipped 0, Failed 0.
4.5 Bước 3d — Verify
| Verify | Value | Gate |
|---|---|---|
| PG cols (information_schema) | 3 (all character varying, is_nullable=YES) |
OK |
| directus_fields rows | 3 (interfaces match: select-dropdown, input, select-dropdown) | OK |
| fn_birth_registry_auto md5 | 1f729b3571a74963089bb3ef388217f3 |
OK (unchanged) |
| birth_registry rows | 75472 | live drift (+3 vs baseline; live writes — anti-hardcode note applies) |
5. Bước 4 — Metadata seed
Pre-seed total collection_registry rows: 166 (matches expected denominator).
B4.before_birth_count = 75472.
Single transaction. UPDATE counts:
| Group | Rows |
|---|---|
column strategy + 20 names with code |
20 |
column law_catalog → law_code |
1 |
column measurement_registry → measurement_id |
1 |
column table_registry → table_id |
1 |
column pivot_results → pivot_code |
1 |
column workflows → process_code |
1 |
legacy_id_single_colon (3 names) |
3 |
synthetic_id information_unit |
1 |
subordinate unit_version |
1 |
disabled excluded role + NULL/unclassified |
60 |
disabled views/birth_registry sweep |
3 |
NULL→unclassified strategy |
73 |
NULL→unclassified source |
73 |
Post-seed distribution (must equal expected exactly):
| birth_code_strategy | count |
|---|---|
| column | 25 ✓ |
| disabled | 63 ✓ |
| legacy_id_single_colon | 3 ✓ |
| subordinate | 1 ✓ |
| synthetic_id | 1 ✓ |
| unclassified | 73 ✓ |
| Total | 166 ✓ |
Other gates:
birth_code_strategy IS NULL→ 0 ✓birth_identity_source IS NULL→ 0 ✓fn_birth_registry_automd5 =1f729b3571a74963089bb3ef388217f3✓trg_birth_%trigger count = 30 ✓ (unchanged)B4.after_birth_count= 75472 (no drift inside txn)
COMMIT succeeded.
6. Bước 5 — PG enforcement
B5.before_birth_count = 75472.
Single transaction:
ALTER COLUMN birth_code_strategy SET DEFAULT 'unclassified'✓ALTER COLUMN birth_identity_source SET DEFAULT 'unclassified'✓ALTER COLUMN birth_code_strategy SET NOT NULL✓ALTER COLUMN birth_identity_source SET NOT NULL✓ADD CONSTRAINT collection_registry_birth_code_strategy_check CHECK (...)✓ADD CONSTRAINT collection_registry_birth_identity_source_check CHECK (...)✓
Verify:
collection_registry_birth_code_strategy_check
CHECK (birth_code_strategy = ANY ARRAY['column','synthetic_id',
'legacy_id_single_colon','subordinate','disabled','unclassified'])
collection_registry_birth_identity_source_check
CHECK (birth_identity_source = ANY ARRAY['inferred_from_existing_trigger',
'manual','migration_seed','system_default','unclassified'])
Column states post-commit:
| Column | Nullable | Default |
|---|---|---|
| birth_code_strategy | NO | 'unclassified'::varchar |
| birth_code_column | YES | NULL |
| birth_identity_source | NO | 'unclassified'::varchar |
fn_birth_registry_automd5 =1f729b3571a74963089bb3ef388217f3✓B5.after_birth_count = 75472✓ (no drift)
COMMIT succeeded.
7. Final invariants
| Invariant | Value | Status |
|---|---|---|
| fn_birth_registry_auto md5 | 1f729b3571a74963089bb3ef388217f3 |
UNCHANGED through B1→B3d→B4→B5 |
| trg_birth_% triggers | 30 | UNCHANGED |
| collection_registry rows | 166 | UNCHANGED |
| birth_registry live drift | 75469 → 75472 (B1 → B5) | live operational drift only (+3); anti-hardcode acknowledged |
| 3 new fields | birth_code_strategy, birth_code_column, birth_identity_source |
CREATED in PG + Directus |
| 2 new CHECK constraints | strategy + source enums | INSTALLED |
| NOT NULL + DEFAULT | strategy + source | INSTALLED |
8. Anomalies / notes
- First seed-transaction attempt failed at the verify SELECT (
'B4.dist:' || s || '=' || count(*)triggered Postgresaggregate functions are not allowed in GROUP BYbecause GROUP BY 1 referenced the composite expression including count).ON_ERROR_STOP=1triggered ROLLBACK; pre-state preserved (verified: NULL=166). Verify SELECT was rewritten to use a subquery; second transaction COMMITted clean. No drift, no partial state. dot-schema-applyis a bash wrapper to Directus REST/fields/{collection}POST; created Directus + PG columns atomically via Directus schema engine.- Sortable/filterable boolean meta fields are NOT part of this Directus 11.x version's field-meta schema for
collection_registry/collection_name— spec deliberately omitted them per "include exactly the boolean meta fields detected" rule.
9. Out of scope (explicitly NOT performed)
Per 18b-P1 rev 6 boundary:
- ✗ DOT-119 execution / script rewrite
- ✗
fn_birth_registry_autoedit - ✗ IU trigger install / IU rows
- ✗ Pack 2B steps
10. Verdict
P1 PASS. All gates green; both transactions COMMITted; fn_hash invariant preserved; trigger count preserved; constraint + default + NOT-NULL installed; Directus + PG fields registered. Ready for next phase per 18b umbrella.
P1 report | 2026-05-05 | Opus 4.7 (1M ctx) | HARD STOP after this upload.