KB-50F0
C1 Staging Codex R3 Fixes — Codex-Style Hostile Self-Review
4 min read Revision 1
c1stagingcodex-r3-fixesready-for-r42026-06-23
08 — CODEX-STYLE HOSTILE SELF-REVIEW (A1–A12)
Each attack is refuted with code evidence and, where applicable, read-only empirical proof.
| # | Attack | Verdict | Evidence |
|---|---|---|---|
| A1 | P3 writes P3_DONE then fatal gate fails | REFUTED | p3 gate(70) < DONE(85) < COMMIT(86), one BEGIN(10); gate RAISE → txn rollback → no c1_vocab_build row. |
| A2 | P4 writes P4_DONE then fatal gate fails | REFUTED | p4 gate(27) < DONE(45) < COMMIT(46), one BEGIN(9). |
| A3 | P5 writes P5_DONE then fatal gate fails | REFUTED | p5 gate(54) < DONE(68) < COMMIT(69), one BEGIN(15). |
| A4 | P6 sees DONE rows but canonical set is wrong | REFUTED | P6 step 2: count=3 AND extra IS NULL AND missing IS NULL. Live proof: count=3 wrong-set flags extra=C1.WRONG + missing=C1.VERIFY_DIGEST. |
| A5 | P6 sees P5_DONE but harness rows missing | REFUTED | P6 step 5: total=9 + joined_n=9. Live F3 (case7 missing) → total=8 → RAISE. |
| A6 | P6 sees P5_DONE but bad case accepted | REFUTED | P6 step 5: accepted=0 + verdict requires outcome='rejected'. Live F1 → indep_pass=8, disagree=1. |
| A7 | P6 sees P4_DONE but P4 invariant rows missing | REFUTED | P6 steps 3+4 recompute nvalid=3, field+mode invariants from canonical_operation directly (CASE-guarded). |
| A8 | Digest excludes harness rows | REFUTED | c1_digest serializes c1_test_results → harness_md5 + harness segment of combined_md5. |
| A9 | Digest excludes P4 verification facts | REFUTED | vops now includes per-op evidence (P4 verify result) + status. |
| A10 | P6_DONE commits after partial upstream success | REFUTED | Fix A: partial success ⇒ a Pn DONE stamp is absent ⇒ P6 step 1 RAISE; gate+digest+ledger one txn — no commit on RAISE. |
| A11 | Ledger/stamp says DONE but no matching verified facts | REFUTED | Core Fix B: P6 re-derives all facts; stored pass not trusted. Live F2 (pass=true, wrong code) → P6_FATAL_PASS_TAMPER. |
| A12 | Failure after DONE leaves committed false success | REFUTED | DONE is last write before COMMIT (atomic); P6 verdict only post-gated-commit; bin prints P6_DONE only on psql exit 0; plan emits DRY_RUN_OK only after P2 RETIRED_OK + count=0. |
No attack left unrefuted. No HOLD.
Additional defects Claude found during self-review (beyond the literal Codex R3 blocker)
- OR /
jsonb_array_lengthnon-short-circuit reliance. The existing validation usesjsonb_typeof(x)<>'array' OR jsonb_array_length(x)<1; PostgreSQL does not guarantee OR short-circuit. Empirically PG16.13 short-circuits at runtime (so the existing trigger works — column ref, not const-folded), so the byte-identical trigger was left unchanged; but the NEW P6 field checks use documented-safe CASE guards sojsonb_array_lengthis never evaluated on a non-array. - Duplicate-key JSON forgery. A raw
--ownercan inject a duplicate"op"key producing valid-but-forged JSON that jq accepts (last-wins). So a jq-verify alone would not stop forgery — the escaping is essential. Both are applied (#4). - psql interpolation gotcha. Confirmed read-only that
:varis inert inside single-quoted and dollar-quoted strings, so the existing p5 JSON literals and the newDO $g$body are safe; the intended:'sbx'/:'operator'substitutions are all outside quotes.
Codex R3 required-fixes #3/#4 (not the headline blocker, but listed by Codex)
Both addressed (see 07) to ensure a clean R4 rather than a re-reject.