18b-P2 — DOT-119 Script Rewrite + Smoke Tests (Rev 6)
18b-P2 — DOT-119 Script Rewrite + Smoke Tests
Controlling: 18a rev4 + 18b rev3 + P1 PASS + GPT P2 directive Rev 6: Post-install rollback nếu smoke fail. Script KB rev 4 (không đổi).
Bước 0: Đọc controlling docs
Đọc trên KB: 18a rev4, 18b rev3, P1 report, GPT P2 directive. Xác nhận.
Bước 1: Preflight
SELECT column_name, is_nullable, column_default FROM information_schema.columns
WHERE table_name='collection_registry'
AND column_name IN ('birth_code_strategy','birth_code_column','birth_identity_source');
-- Must: 3 rows.
SELECT conname FROM pg_constraint
WHERE conrelid='collection_registry'::regclass AND conname LIKE '%birth%';
-- Must: 2 CHECK.
SELECT md5(pg_get_functiondef('fn_birth_registry_auto'::regproc)) AS fn_hash_baseline;
SELECT count(*) AS trigger_count_baseline FROM pg_trigger
WHERE tgname LIKE 'trg_birth_%' AND NOT tgisinternal;
SELECT count(*) AS birth_count_baseline FROM birth_registry;
SELECT count(*) FROM collection_registry WHERE birth_code_strategy IS NULL;
SELECT count(*) FROM collection_registry WHERE birth_identity_source IS NULL;
-- Both = 0.
Mismatch → STOP + partial report.
Smoke samples
SELECT collection_name FROM collection_registry WHERE birth_code_strategy='column' AND birth_code_column='code' ORDER BY collection_name LIMIT 1;
SELECT collection_name FROM collection_registry WHERE birth_code_strategy='column' AND birth_code_column <> 'code' ORDER BY collection_name LIMIT 1;
SELECT collection_name FROM collection_registry WHERE birth_code_strategy='unclassified' ORDER BY collection_name LIMIT 1;
SELECT collection_name FROM collection_registry WHERE birth_code_strategy='disabled' ORDER BY collection_name LIMIT 1;
Capture → SAMPLE_CODE, SAMPLE_NONCODE, SAMPLE_UNCLASSIFIED, SAMPLE_DISABLED. Absent → STOP.
Bước 2: Backup v1
DOT119=/opt/incomex/dot/bin/dot-birth-trigger-setup
ls -la "$DOT119"; md5sum "$DOT119"
BACKUP_PATH="/opt/incomex/backups/dot-birth-trigger-setup.v1.bak.$(date +%Y%m%d%H%M%S)"
cp "$DOT119" "$BACKUP_PATH"
md5sum "$BACKUP_PATH"
Bước 3: Install v2 (atomic)
3a: Read script from KB
Đọc: knowledge/dev/laws/dieu44-trien-khai/design/dot119-v2-script-content.sh
Ghi TOÀN BỘ nội dung vào temp file (heredoc).
3b–3d: Integrity → syntax → no-clobber → atomic install
md5sum /tmp/dot-birth-trigger-setup.v2.$$
bash -n /tmp/dot-birth-trigger-setup.v2.$$
# Fail → rm + STOP.
grep -cF 'CREATE OR REPLACE FUNCTION fn_birth_registry_auto' /tmp/dot-birth-trigger-setup.v2.$$
# Must: 0. Non-zero → rm + STOP.
chmod 755 /tmp/dot-birth-trigger-setup.v2.$$
mv /tmp/dot-birth-trigger-setup.v2.$$ "$DOT119"
ls -la "$DOT119"; md5sum "$DOT119"; wc -l "$DOT119"
Bước 4: Smoke tests (18 tests) + ★ Rev 6 rollback logic
Setup
DOT119=/opt/incomex/dot/bin/dot-birth-trigger-setup
SMOKE_FAILED=0
run_expect() {
local expected="$1"; shift
set +e
"$@" 2>&1
local rc=$?
set -e
if [ "$rc" -eq "$expected" ]; then
echo "PASS (exit=$rc expected=$expected)"
else
echo "FAIL (exit=$rc expected=$expected)"
SMOKE_FAILED=1
fi
}
run_pass() {
set +e
"$@" 2>&1
local rc=$?
set -e
if [ "$rc" -eq 0 ]; then
echo "PASS (exit=0)"
else
echo "FAIL (exit=$rc expected=0)"
SMOKE_FAILED=1
fi
}
Tests
| # | Command |
|---|---|
| 1 | run_expect 1 "$DOT119" |
| 2 | run_pass "$DOT119" --help |
| 3 | run_expect 1 "$DOT119" --collection=dot_tools --dry-run --execute |
| 4 | run_pass "$DOT119" --collection=$SAMPLE_CODE --dry-run --json |
| 5 | run_pass "$DOT119" --collection=$SAMPLE_NONCODE --dry-run --json |
| 6 | run_pass "$DOT119" --collection=information_unit --dry-run --json (verify synthetic_capability=pass in output) |
| 7 | run_expect 10 "$DOT119" --collection=$SAMPLE_UNCLASSIFIED --dry-run |
| 8 | run_pass "$DOT119" --collection=$SAMPLE_DISABLED --dry-run |
| 9 | run_pass "$DOT119" --collection=unit_version --dry-run |
| 10 | run_pass "$DOT119" --collection=$SAMPLE_CODE --verify --json |
| 11 | run_pass "$DOT119" --collection=$SAMPLE_DISABLED --verify --json |
| 12 | run_expect 14 "$DOT119" --collection=information_unit --verify --json |
| 13 | grep -cF 'CREATE OR REPLACE FUNCTION fn_birth_registry_auto' "$DOT119" → must 0, else SMOKE_FAILED=1 |
| 14 | fn hash audit: SQL → must = fn_hash_baseline, else SMOKE_FAILED=1 |
| 15 | trigger count: SQL → must = trigger_count_baseline, else SMOKE_FAILED=1 |
| 16 | birth count: SQL → run-local capture |
| 17 | run_expect 30 "$DOT119" --collection=dot_tools --drop |
| 18 | grep -c 'KNOWN_V2_FN_HASH' "$DOT119" → must 0, else SMOKE_FAILED=1 |
★ Rev 6: Post-smoke rollback decision
if [ "$SMOKE_FAILED" -eq 1 ]; then
echo "═══ SMOKE FAILED — ROLLING BACK TO v1 ═══"
cp "$BACKUP_PATH" "$DOT119"
chmod 755 "$DOT119"
md5sum "$DOT119"
echo "ROLLBACK: restored from $BACKUP_PATH"
# Upload partial P2 report with:
# - failed tests listed
# - rollback happened = yes
# - final installed = v1 restored
# - HARD STOP
else
echo "═══ ALL SMOKE PASS — v2 ACTIVE ═══"
# Continue to report
fi
Bước 5: Upload P2 report
Path: knowledge/dev/laws/dieu44-trien-khai/reports/dot119-repair-p2-script-rewrite-report.md
Report PHẢI gồm:
- Backup path + md5
- Temp file md5
- Installed file md5 + lines
- bash -n + no-clobber
- 18 smoke tests (PASS/FAIL each)
- fn hash audit trail
- synthetic_capability output
- Trigger + birth count trails
- No-hardcode confirmation
- ★ Rev 6:
rollback_happened: yes/nofinal_installed_script: v2 active / v1 restoredfinal_installed_md5: <hash>
- TDs
Any STOP → partial report. Smoke fail → restore v1 + partial report.
Bước 6: HARD STOP
No fn edit. No IU trigger. No IU rows. No Pack 2B. No DDL.
18b-P2 rev 6 | 2026-05-05 | Opus 4.6 | Smoke fail → auto-restore v1. Report ghi rollback status.