dot-iu-cutter v0.4 PG-backed Dry-run RERUN — EXECUTION FAIL: CUT signing-body UUID-not-JSON-serializable (2026-05-17)
dot-iu-cutter v0.4 — PG-backed Dry-run RERUN: EXECUTION FAIL (honest)
Date: 2026-05-17 · execution_status: FAIL (honest). Rerun on the txn-fix commit 6060e1ae8b958fcb8a61ed45b597dc553b8688be. The transaction-lifecycle fix is validated (the previously-fatal S4 now passes with real writes); a new, distinct accepted-code defect was found at S6 CUT. Orchestrator STOPped at the failing gate, tore down the isolated env exact-name, did not improvise, did not mark PASS. Production untouched.
1. Progress vs prior FAIL (txn-lifecycle fix confirmed working)
| Scenario | Result |
|---|---|
| S1 config load (no connect) | PASS |
| S2 missing key fail-closed | PASS |
| S3-neg current_user mismatch → ConfigMismatch | PASS |
| S4 MARK | PASS ← was the fatal failure before the fix; now writes real rows |
| SWEEP | PASS (promote + sweep_log) |
| S5 REVIEW | PASS (envelope + unit_block + review_decision + history) |
| S6 CUT | FAIL (new defect, §2) |
| S7 VERIFY … S12 | not reached |
SQL trace verbs observed: {SET, SELECT, INSERT, UPDATE} — real MARK/SWEEP/REVIEW writes occurred (proving commit 6060e1a resolved the RealPostgresAdapter find()/_begin transaction-lifecycle defect). No forbidden verb (no DELETE/TRUNCATE/DROP/ALTER/GRANT/CREATE/COPY).
2. New root cause — accepted-code: CUT/VERIFY signing-body json.dumps over psycopg3 UUID (NOT harness / NOT r3 / NOT txn-fix / NOT schema-binding-logic)
cutter_agent/phases.py cut() builds the DOT executor signing body:
body = json.dumps({"entry": entry_id, "manifest": manifest_id},
sort_keys=True).encode("utf-8")
manifest_id is obtained from self._reviews_for_entry(entry_id) → adapter.find("review_decision", …), i.e. read back from the real Postgres uuid column. psycopg3 returns SQL uuid as a Python uuid.UUID object, which json.dumps cannot serialize → TypeError: Object of type UUID is not JSON serializable. verify() has the same shape (json.dumps({"entry": entry_id, "manifest": cs["manifest_id"]})).
This was latent because the InMemory adapter stores/returns the ids as the str the ledger inserted, so json.dumps worked; the real psycopg3 driver returns uuid.UUID. It is a genuine accepted-code defect surfaced only by a real PostgreSQL connection — exactly the class of latent gap the PG-backed dry-run exists to catch (third such finding: structural schema mismatch → txn lifecycle → now UUID/JSON typing).
- Not a harness defect: the failure raises inside
cutter_agent.phases.cut()'sjson.dumps, accepted code, when fed real-psycopg UUID values; the harness only drove the accepted pipeline. - Not an r3 defect: counting never reached.
- Not the txn-fix:
6060e1ais validated working (S4/SWEEP/S5 now pass with real writes). - Not the schema-binding logic per se: the SB-DEC-1 real-schema lineage read is correct by design; it merely surfaced that
cut()/verify()json.dumpsDB-sourced UUIDs.
3. Required output
| Field | Value |
|---|---|
| execution_status | FAIL (honest; accepted-code CUT/VERIFY UUID-JSON defect) |
| accepted commit | 6060e1ae8b958fcb8a61ed45b597dc553b8688be (mounted RO; txn-fix validated) |
| dry-run env / sysid | pg-dry-run-v0.4-db-adapter-2026-05-17 / DR sysid 7640819868740706349 |
| production sysid pre/post | 7611578671664259111 / 7611578671664259111 (unchanged) |
| backup path + sha | …/.dryrun-v0.4-2026-05-17/prod-directus-20260517T112308Z.sql · sha256 e14089005192085b8766d64243e5e8de8fdb3897fc36059bb3517d04440dc3a3 · 680,066,849 B (read-only pg_dump -U workflow_admin; plain-format ⇒ per-run sha) |
| SQL/harness artefact shas | roles+matrix 2a409696dc3f60cb6328a77afd345e7638685f8d70cb5c0995b40f5841a57584 · harness ddf14a94438a6b8ed621329d2f3b62ca7da2b58724d6fd363136a0f1c8d3aa96 (sha-gated, unchanged across runs) · orchestrator iterated for env-readiness robustness (throwaway tooling) |
| psycopg3 install scope | ephemeral python:3.12-slim --rm container only (pip install "psycopg[binary]>=3.1,<3.4"); never host/incomex-*; gone with container |
| scenario S1→S12 | S1/S2/S3-neg/S4-MARK/SWEEP/S5-REVIEW PASS; S6 CUT FAIL; S7…S12 not reached |
| 12-table matrix | not asserted — fail at S6 before baseline checkpoint (rows written by MARK/SWEEP/REVIEW were discarded with the env teardown) |
| final 15-row baseline | not reached |
| negative Δ0 | not reached |
| no forbidden SQL | ✓ trace verbs {SET,SELECT,INSERT,UPDATE} only |
| no secret leakage | ✓ openssl dry-run-only passwords; dr.env/dr.harness.env 0600 then shredded at teardown; orchestrator/harness never echo secrets |
| teardown | DR container+network removed exact-name (DR_GONE); secrets shredded |
| protected envs untouched | ✓ all 3 (…v0.2-p0-2…, …v0.2-phase-alpha…, …hb05…) running, unchanged |
| production untouched | ✓ only read-only pg_dump; prod postgres StartedAt 2026-04-17T05:35:18.48439927Z unchanged; prod sysid pre==post; no adapter/secret/.env/CUT/VERIFY |
| git SSOT | branch main; HEAD 6060e1ae8b958fcb8a61ed45b597dc553b8688be (unchanged); git status --short -- iu-cutter clean (throwaway WD excluded); no code change, no commit |
| hardcode/scale control | no literal IP/DSN/password/container/vector collection introduced; no label/key/metadata-schema change; dry-run config from dry-run-only env; no hardcode/label finding |
4. Honest-FAIL discipline
Orchestrator STOPped at G_HARNESS_HAPPY, ran teardown of the exact DR env only, did not improvise (I did not patch phases.py/db_adapter.py to str() the ids, nor patch the harness to mask it — that is a code change forbidden in this dry-run cycle and would hide a real defect), reported honest FAIL, did not mark PASS. Two earlier interim STOPs this rerun were orchestrator-artefact robustness bugs (a stale set -u $PORTS fixed previously; the postgres-image bootstrap transient-ready race in the readiness gate — hardened to require the target DB to answer a real query twice consecutively); both with prod/protected untouched and the isolated env removed exact-name. Those are tooling false-negatives, distinct from this substantive S6 accepted-code defect, which is reported as a true FAIL and not worked around.
5. Remediation (NOT self-applied — needs GPT authorisation)
A separate GPT-gated code-authoring cycle. Candidate minimal fix (design to be reviewed): make the DOT signing-body construction UUID-safe — e.g. json.dumps({"entry": str(entry_id), "manifest": str(manifest_id)}, sort_keys=True) in phases.py cut() and verify(); or normalise uuid.UUID → str in RealPostgresAdapter.find() row mapping (db_adapter.py) so all DB-sourced ids are JSON/equality-stable. Add a real-psycopg (or UUID-returning fake) regression test so the unit suite catches it. Then re-author the PG-backed dry-run (command-review r1 / verification-plan r3 unchanged; binding still count-invariant). No self-advance.
6. Next gate
GPT review of this honest-FAIL report + adjudication of the CUT/VERIFY UUID-JSON remediation cycle. PG-backed dry-run remains blocked/failed until that fix lands under a separate GPT-gated cycle and is re-authorised. The txn-lifecycle fix (6060e1a) is independently validated by this run (S4/SWEEP/S5 PASS with real writes). No production action; no PASS claimed.