GPT Review — 22-P3-P2 Trigger Guard Prompt rev2
GPT Review — 22-P3-P2 Trigger Guard Prompt rev2
Date: 2026-05-06
Reviewer: GPT-5.5 Thinking / Incomex Hội đồng AI
Reviewed:knowledge/dev/laws/dieu44-trien-khai/prompts/22-p3-p2-iu-gateway-trigger-guard-prompt.mdrev2
Verdict
Do not dispatch rev2. Rev3 required, but fixes are small and copy-ready.
Rev2 fixed the main blocker: direct-block tests are now isolated from the canonical marker. The overall structure is correct.
Remaining issues are practical execution bugs and final-verdict hardening. Apply the patches below directly; do not redesign.
Required rev3 patches
P1 — Initialize CAN_EXIT, BLOCK_EXIT, and MODE_EXIT
Rev2 uses these variables after commands, but they are not initialized at the top. Under set -u, failure paths could abort the report.
Patch near variable initialization:
CAN_EXIT=0
BLOCK_EXIT=0
MODE_EXIT=0
P2 — MODE_UPDATE exit code must be captured and required in verdict
Rev2 runs:
"${PSQL_CMD[@]}" -c "UPDATE ..."
but does not capture the exit status. If mode update fails, GW_MODE may remain prepared and verdict fails later, but the failure reason is less clear.
Patch:
MODE_EXIT=0
if [ "$ALL_TESTS_PASS" = true ]; then
set +e
"${PSQL_CMD[@]}" -c "UPDATE public.dot_config SET value='enforced', updated_at=now() WHERE key='iu_create.gateway.mode';" >> "$LOG_PATH" 2>&1
MODE_EXIT=$?
set -uo pipefail
fi
Echo mode_exit=$MODE_EXIT in final verdict and require MODE_EXIT=0.
P3 — If canonical test fails, do not run block tests using missing pilot
Rev2 always runs block tests even if canonical create failed. UV INSERT and UPDATE tests depend on the pilot. This can produce confusing failures.
Patch:
if [ "$CANONICAL_STATUS" = "PASS" ]; then
# run block tests
else
IU_INSERT_BLOCK="NOT_RUN"
UV_INSERT_BLOCK="NOT_RUN"
IU_UPDATE_BLOCK="NOT_RUN"
UV_UPDATE_BLOCK="NOT_RUN"
fi
P4 — Direct-block error checks should include README/canonical path for UPDATE too
Rev2 checks strong message for INSERT tests but only %IU Gateway blocked% for UPDATE tests. Patch UPDATE tests to require the same guidance:
IF v_msg LIKE '%IU Gateway blocked%'
AND (v_msg LIKE '%fn_iu_create%' OR v_msg LIKE '%canonical%')
AND (v_msg LIKE '%README%' OR v_msg LIKE '%readme%') THEN
v_ok := true;
ELSE ...
END IF;
Apply to IU UPDATE and UV UPDATE.
P5 — Direct INSERT tests should also check README explicitly
Rev2 INSERT tests check IU Gateway blocked and fn_iu_create/canonical, but not README. Add README/readme condition to IU and UV INSERT checks too.
P6 — Post-deploy metadata should verify trigger enabled state O
Rev2 verifies function metadata and trigger event bits, but not enabled state. Add:
DO $$ DECLARE v_bad int; BEGIN
SELECT count(*) INTO v_bad
FROM pg_trigger
WHERE tgname IN ('trg_iu_gateway_write_guard','trg_uv_gateway_write_guard')
AND tgenabled <> 'O';
IF v_bad <> 0 THEN RAISE EXCEPTION 'gateway trigger not enabled ordinary: %', v_bad; END IF;
END $$;
P7 — Trigger event-bit check should be replaced with decoded pg_get_triggerdef or correct bit assertion
Rev2 uses (v_type & 20) != 20. PostgreSQL tgtype bit meanings are easy to misread. To avoid a false fail/pass, use pg_get_triggerdef text check:
DO $$ DECLARE v_def text; BEGIN
SELECT pg_get_triggerdef(oid) INTO v_def FROM pg_trigger WHERE tgname='trg_iu_gateway_write_guard';
IF v_def NOT LIKE '%BEFORE INSERT OR UPDATE%' AND v_def NOT LIKE '%BEFORE UPDATE OR INSERT%' THEN
RAISE EXCEPTION 'IU guard trigger def unexpected: %', v_def;
END IF;
SELECT pg_get_triggerdef(oid) INTO v_def FROM pg_trigger WHERE tgname='trg_uv_gateway_write_guard';
IF v_def NOT LIKE '%BEFORE INSERT OR UPDATE%' AND v_def NOT LIKE '%BEFORE UPDATE OR INSERT%' THEN
RAISE EXCEPTION 'UV guard trigger def unexpected: %', v_def;
END IF;
END $$;
Or use a correct bit check if Opus is certain. Text check is clearer for Agent review.
P8 — Preflight existing guard trigger detection should be exact names, not %gateway%
Rev2 blocks if any trigger name LIKE %gateway%. This could false-stop on future unrelated gateway trigger. Use exact target names:
SELECT count(*) FROM pg_trigger WHERE NOT tgisinternal
AND ((tgrelid='public.information_unit'::regclass AND tgname='trg_iu_gateway_write_guard')
OR (tgrelid='public.unit_version'::regclass AND tgname='trg_uv_gateway_write_guard'));
P9 — Guard function existence detection should handle invalid output
If the to_regprocedure query errors or returns empty, early_stop should trigger. Normalize:
if [ "$GUARD_FN" != "t" ] && [ "$GUARD_FN" != "f" ]; then early_stop "invalid guard_fn_exists=$GUARD_FN"; fi
Same for GUARD_TRG: require numeric.
P10 — Final verdict should echo and require CAN_EXIT and BLOCK_EXIT
Add to final verdict:
echo "canonical_exit=$CAN_EXIT"
echo "block_exit=$BLOCK_EXIT"
echo "mode_exit=$MODE_EXIT"
Final condition should require:
[ $CAN_EXIT -eq 0 ] && [ $BLOCK_EXIT -eq 0 ] && [ $MODE_EXIT -eq 0 ]
If block tests are skipped because canonical failed, BLOCK_EXIT may remain 0; the *_BLOCK=NOT_RUN statuses already fail. Still echoing exits helps debug.
P11 — POST_EXIT should be initialized and final verify should run under set +e
POST_EXIT is initialized, good. But final verify commands currently run without set +e around all of them. Because no global set -e, this is less dangerous, but consistency matters.
Patch lightly: wrap final verify command block with set +e before and set -uo pipefail after, and capture only critical command statuses. Do not overdo.
Do not change
- Keep separate sessions.
- Keep SECURITY DEFINER guard.
- Keep no GRANT/REVOKE.
- Keep no cleanup.
- Keep no detector/adapter/DOT.
- Keep compact structure.
Directive to Opus
Patch P3-P2 prompt to rev3 with P1–P11. Use the copy-ready snippets above. Do not add new design scope. Return for GPT/User review; do not dispatch.
Expected result
If rev3 applies these fixes without expanding scope, it should be ready for final approval.
Summary
Rev2 solved the conceptual blocker. Rev3 is shell/test hardening: capture mode update, avoid block tests when pilot missing, require guidance content in all block errors, use exact trigger names, verify enabled state, and make final verdict stricter.