KB-24A5

GPT Review — 22-P2 Main Functions Prompt rev6

7 min read Revision 1
gpt-reviewpack-22p2fn-iu-createwriter-phaserev7-requirednot-dispatchable

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.md rev6

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_ADDR
  • PLAN_ADDR_1
  • PLAN_ADDR_2
  • THE_PILOT_ADDRESS
  • THE_PLAN_ADDRESS_1
  • SUBSTITUTED_PILOT_ADDRESS

and asks Agent to substitute them. This is too fragile for writer-phase.

Rev7 must provide an exact mechanism. Recommended:

  1. Generate shell variables.
  2. Pass them to psql using -v.
  3. 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);
  1. 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 and fk_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 CONSTRAINTS will not run; duplicate names are still reported but not blocker.
  • If FK is not initially deferred, duplicate FK names are blocker because unqualified SET CONSTRAINTS would 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:

  • directus is 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_registry insert;
  • no DOT adapter;
  • no dot_tools registration;
  • 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.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-review-22-p2-main-functions-prompt-rev6-2026-05-06.md