GPT Review — 22-P2 Main Functions Prompt rev6
GPT Review — 22-P2 Main Functions Prompt rev6
Date: 2026-05-06 Reviewer: GPT-5.5 Thinking / Incomex Hội đồng AI Reviewed:
knowledge/dev/laws/dieu44-trien-khai/prompts/22-p2-iu-native-create-main-functions-prompt.mdrev6
Verdict
Do not dispatch rev6. Rev7 required.
Rev6 fixes the major self-contained problem: full function bodies are inline. However, this is still not safe to send to Agent. Several writer-phase issues remain, including a repeated catalog bug, fragile placeholder handling, and incomplete exact-one checks.
Required rev7 patches
P1 — Replace all manual placeholder substitution with a concrete psql variable/session-setting mechanism
Rev6 still uses placeholders such as:
PILOT_ADDRPLAN_ADDR_1PLAN_ADDR_2THE_PILOT_ADDRESSTHE_PLAN_ADDRESS_1SUBSTITUTED_PILOT_ADDRESS
and asks Agent to substitute them. This is too fragile for writer-phase.
Rev7 must provide an exact mechanism. Recommended:
- Generate shell variables.
- Pass them to psql using
-v. - At the start of SQL, set transaction/session settings:
SELECT set_config('app.p2_pilot_address', :'PILOT_ADDRESS', false);
SELECT set_config('app.p2_plan_address_1', :'PLAN_ADDRESS_1', false);
SELECT set_config('app.p2_plan_address_2', :'PLAN_ADDRESS_2', false);
- Inside DO blocks, use:
v_addr := current_setting('app.p2_pilot_address');
This avoids literal placeholder substitution inside dollar-quoted DO blocks, which is easy to get wrong.
If Opus chooses another mechanism, it must be equally exact and not require manual text replacement.
P2 — Fix array_length(conkey,1) on pg_constraint.conkey
Rev6 reintroduces:
array_length(conkey,1)=1
conkey is not a normal SQL array in a safe portable sense. This was already rejected in P1 review.
Patch all unique-constraint checks to avoid array_length(conkey,1).
Use a count-based pattern:
SELECT conname
FROM pg_constraint c
WHERE c.conrelid='public.information_unit'::regclass
AND c.contype='u'
AND (
SELECT count(*)
FROM unnest(c.conkey) k
JOIN pg_attribute a ON a.attrelid=c.conrelid AND a.attnum=k
WHERE a.attname='canonical_address'
) = 1
AND (
SELECT count(*) FROM unnest(c.conkey)
) = 1;
Keep the unique-index fallback using indnkeyatts=1 and indkey[0].
P3 — Deferrable FK candidate count must be exactly one everywhere it is used
Rev6 preflight and function use:
SELECT conname INTO v_fk FROM pg_constraint ...
but does not explicitly count candidates in the rev6 prompt. If there are multiple IU→UV deferrable FKs, SELECT INTO may choose one or error depending context, but either way the design is unclear.
Patch:
- Preflight: count deferrable IU→UV FK candidates. If count != 1 → STOP.
- Function: rely on
public.fn_iu_create_preflight()only if it returns exact-one status andfk_name; otherwise raise exception. - If function does its own FK lookup, it must also enforce count=1.
P4 — Placeholder guard currently checks only one literal and can pass wrong values
Rev6 guard:
IF 'THE_PILOT_ADDRESS' ~ '^\$|^ACTUAL|^SUBSTITUT|^THE_|^PILOT_ADDR$' THEN ...
This is better than before, but it only checks one value and still depends on manual replacement.
If P1 is applied with session settings, replace this with one guard that checks all three settings:
FOR v IN SELECT current_setting('app.p2_pilot_address')
UNION ALL SELECT current_setting('app.p2_plan_address_1')
UNION ALL SELECT current_setting('app.p2_plan_address_2')
LOOP
IF v IS NULL OR v !~ '^[a-z0-9.-]+$' OR v LIKE '$%' OR v LIKE 'THE_%' OR v LIKE 'PILOT_ADDR%' THEN
RAISE EXCEPTION 'invalid/unsubstituted address: %', v;
END IF;
END LOOP;
P5 — Post-COMMIT verification should use the exact stored address setting, not placeholder literal
Rev6 post-COMMIT uses:
public.fn_iu_verify_invariants('THE_PILOT_ADDRESS')
Patch to use exact psql/session variable mechanism from P1.
P6 — SET CONSTRAINTS duplicate-name check should be tied to actual function behavior
Rev6 preflight checks duplicate FK names and the function uses unqualified SET CONSTRAINTS %I. Good direction.
But rev7 must make the policy explicit:
- If FK is initially deferred,
SET CONSTRAINTSwill not run; duplicate names are still reported but not blocker. - If FK is not initially deferred, duplicate FK names are blocker because unqualified
SET CONSTRAINTSwould be ambiguous.
If Opus wants to keep duplicate names as unconditional blocker, that is safe but stricter. State the chosen policy clearly.
P7 — Preflight public.fn_iu_create_preflight() result must be asserted, not only selected
Rev6 does:
SELECT public.fn_iu_create_preflight() AS pf;
This displays JSON but does not stop if status is not pass.
Patch:
DO $$
DECLARE v_pf jsonb;
BEGIN
v_pf := public.fn_iu_create_preflight();
IF v_pf->>'status' <> 'pass' THEN
RAISE EXCEPTION 'fn_iu_create_preflight failed: %', v_pf;
END IF;
END $$;
P8 — Grant policy must not silently call directus eternal truth
Rev6 grants to directus if exists. This is acceptable as current environment candidate, but report and prompt must state:
directusis a P0/P1-observed adapter role, not a timeless contract role;- if missing, function install may still commit, but adapter readiness is BLOCKED;
- future adapter-role policy should be governed by a separate permission pack.
The report already hints at this; put it in the prompt body too.
P9 — Ensure fn_iu_create_plan does not leak full body or full content hash
Rev6 uses left(fn_content_hash(p_body),16), acceptable. Keep it. Add report statement: plan returns 16-char hash preview only; full hash is returned only by create after actual write.
P10 — Report must include exact SQL variable method
Rev7 report should not merely say “shell uuidgen + date.” It should include:
- shell variables generated;
- psql variable/session-setting method used;
- all three values validated by SQL guard;
- no manual text substitution used.
Directive to Opus
Patch P2 prompt to rev7 with P1–P10.
Do not dispatch after patch; return for GPT/User review.
Hard boundaries remain
- no dispatch yet;
- no raw
birth_registryinsert; - no DOT adapter;
- no
dot_toolsregistration; - no default seeding;
- no cleanup pilot;
- no retry/improvise on SQL failure.
Summary
Rev6 is now self-contained, which is good. But it still relies on manual placeholders and contains a repeated catalog bug (array_length(conkey,1)). For writer-phase execution, address passing must be exact and catalog checks must be robust.