Fix R2-3 — P6 Digest Includes Harness Rows (Atomic)
05 — FIX R2-3: P6 DIGEST SPANS HARNESS ROWS, ATOMIC
File: sql/p6-evidence-readback.sql (sha256 212ebc0e23c6f8996d76411f4f1e09a78b901dae1eb5bf1fd8f6c3da977c4118).
Requirement
Digest must include verified canonical_operation rows AND the P5 bad-input harness rows; gate + ledger + digest in one transaction (or under locks); no digest/P6_DONE on failure.
Code — digest spans BOTH tables
CREATE OR REPLACE FUNCTION c1_digest() RETURNS jsonb LANGUAGE plpgsql AS $f$
DECLARE vops text; vharness text; BEGIN
SELECT string_agg(operation_code||'|'||operation_title||'|'||operation_group||'|'||required_inputs::text||'|'||expected_outputs::text||'|'||allowed_modes::text||'|'||status, E'\n' ORDER BY operation_code)
INTO vops FROM canonical_operation;
SELECT string_agg(case_no::text||'|'||COALESCE(expect_code,'')||'|'||COALESCE(expect_state,'')||'|'||outcome||'|'||COALESCE(reject_code,'')||'|'||COALESCE(sqlstate,'')||'|'||pass::text, E'\n' ORDER BY case_no)
INTO vharness FROM c1_test_results WHERE phase='bad';
RETURN jsonb_build_object(
'vocab_row_count',(SELECT count(*) FROM canonical_operation),
'vocab_md5',md5(COALESCE(vops,'')),
'harness_row_count',(SELECT count(*) FROM c1_test_results WHERE phase='bad'),
'harness_md5',md5(COALESCE(vharness,'')),
'combined_md5',md5(COALESCE(vops,'')||E'\n##C1_HARNESS##\n'||COALESCE(vharness,'')),
'generated_at',now()); END;$f$;
Harness fields hashed: case_no, expect_code, expect_state, outcome, reject_code, sqlstate, pass — exactly the nine case expectations/outcomes/reject signals.
Code — gate + ledger + digest in ONE SHARE-locked txn (no TOCTOU); digest persisted in-txn
BEGIN;
LOCK TABLE canonical_operation, c1_test_results IN SHARE MODE;
DO $g$ ... (P3/P4/P5 evidence; 3 validated ops; 9/9 bad pass/0 fail/0 accepted;
case-8 42P01 isolation proof; 0 orphan) -- RAISES on any failure ... $g$;
INSERT INTO sbx_meta.dot_manage_ledger(sandbox_id,op,actor,detail)
VALUES (:'sbx','c1_evidence_readback',:'operator',
jsonb_build_object('gate','C1_STAGING_FAST_DRY_RUN_PASS','digest',c1_digest()));
COMMIT;
-- readback the PERSISTED digest (authenticated inside the gated txn; NOT recomputed post-hoc)
SELECT jsonb_pretty(detail->'digest') FROM sbx_meta.dot_manage_ledger
WHERE op='c1_evidence_readback' AND sandbox_id=:'sbx' ORDER BY seq DESC LIMIT 1;
Why the proofs hold
- Digest cannot be emitted before upstream checks: the digest is computed inside the same txn, AFTER the
DOgate, and only the persisted value is read back. If the gateRAISEs, the txn aborts; withON_ERROR_STOP=1psql exits at theDOstatement, theINSERT/COMMITnever run, nothing commits, and the readback statements are never reached. - Digest spans harness rows: the gate guarantees exactly 9 harness rows and 3 validated ops are present and frozen (SHARE locks) when
c1_digest()runs, socombined_md5/harness_md5authenticate that exact snapshot. P6_DONEcannot appear without the digest: the bin wrapper printsP6_DONEonly onpsqlexit 0, which requires the gated txn (digest persisted) + readback to succeed.
Validation (static, no execution)
Dollar-quote tags balanced ($f$=2, $g$=2, $d$=0); BEGIN/COMMIT 2/2; LOCK TABLE … IN SHARE MODE present; digest references c1_test_results; combined_md5+harness_md5 present; persisted-digest INSERT present. Harness column names match the P5 c1_test_results schema. SQL was NOT executed against any DB (no sandbox created; official runtime read-only).