From db64500a12a64206e1bb7fd0c9a0a21bca755c3d Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 03:59:47 +0200 Subject: [PATCH 01/11] feat: rehearse approved proposal apply and rollback --- .../proposal-apply-clone-rollback-current.sql | 120 + ...oposal-apply-lifecycle-canary-current.json | 3324 +++++++++++++++++ ...posal-apply-lifecycle-receipt-current.json | 217 ++ ...ly-production-target-readback-current.json | 32 + pyproject.toml | 1 + scripts/apply_proposal.py | 369 +- scripts/apply_worker.py | 200 +- .../finalize_approve_claim_isolated_canary.py | 230 ++ scripts/kb_apply_replay_receipt.py | 35 + scripts/proposal_apply_lifecycle.py | 1513 ++++++++ scripts/run_approve_claim_clone_canary.py | 857 ++--- ...approve_claim_isolated_container_canary.sh | 268 +- tests/test_apply_proposal.py | 42 +- tests/test_apply_worker.py | 312 +- tests/test_proposal_apply_lifecycle.py | 846 +++++ ...n_approve_claim_clone_canary_macos_path.py | 82 +- 16 files changed, 7507 insertions(+), 941 deletions(-) create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json create mode 100644 scripts/finalize_approve_claim_isolated_canary.py create mode 100644 scripts/proposal_apply_lifecycle.py create mode 100644 tests/test_proposal_apply_lifecycle.py diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql new file mode 100644 index 0000000..299b52b --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql @@ -0,0 +1,120 @@ +begin; +set local standard_conforming_strings = on; +set local lock_timeout = '5s'; +select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946', 0)); +do $rollback$ +declare + affected integer; + approval_now jsonb; +begin + perform 1 from kb_stage.kb_proposals + where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + for update; + if not found then + raise exception 'proposal rollback: proposal row missing'; + end if; + if not exists ( + select 1 from kb_stage.kb_proposals + where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + and proposal_type = 'approve_claim' + and status = 'applied' + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and reviewed_by_handle is not distinct from E'm3ta' + and reviewed_by_agent_id is not distinct from E'11111111-1111-4111-8111-111111111111'::uuid + and reviewed_at is not distinct from E'2026-07-15 01:59:03.105846+00'::timestamptz + and review_note is not distinct from E'Reviewed exact strict payload inside the disposable clone.' + and applied_by_handle is not distinct from E'kb-apply' + and applied_by_agent_id is not distinct from E'44444444-4444-4444-4444-444444444444'::uuid + and applied_at is not distinct from E'2026-07-15 01:59:04.449051+00'::timestamptz + ) then + raise exception 'proposal rollback: applied ledger does not match apply receipt'; + end if; + select jsonb_build_object( + 'proposal_id', proposal_id::text, + 'proposal_type', proposal_type, + 'payload', payload, + 'reviewed_by_handle', reviewed_by_handle, + 'reviewed_by_agent_id', reviewed_by_agent_id::text, + 'reviewed_by_db_role', reviewed_by_db_role::text, + 'reviewed_at', reviewed_at::text, + 'review_note', review_note + ) into approval_now + from kb_stage.kb_proposal_approvals + where proposal_id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid; + if approval_now is distinct from E'{"payload":{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}},"proposal_id":"9b2b5fa4-0e0d-5db0-aa4d-6fd102889946","proposal_type":"approve_claim","review_note":"Reviewed exact strict payload inside the disposable clone.","reviewed_at":"2026-07-15 01:59:03.105846+00","reviewed_by_agent_id":"11111111-1111-4111-8111-111111111111","reviewed_by_db_role":"kb_review","reviewed_by_handle":"m3ta"}'::jsonb then + raise exception 'proposal rollback: immutable approval snapshot drifted'; + end if; + if (select count(*) from public.claim_evidence t + where t.id = E'dac3934f-b7ad-5205-8efe-a00163370a54'::uuid and to_jsonb(t) = E'{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"dac3934f-b7ad-5205-8efe-a00163370a54","role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: claim_evidence[0] row does not match apply receipt'; + end if; + if (select count(*) from public.claim_evidence t + where t.id = E'13e580c5-458d-5146-aef3-8c74ffc43b7c'::uuid and to_jsonb(t) = E'{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"13e580c5-458d-5146-aef3-8c74ffc43b7c","role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: claim_evidence[1] row does not match apply receipt'; + end if; + if (select count(*) from public.claim_edges t + where t.id = E'b28d8770-9ac9-5b5f-bfe2-7280d7422a21'::uuid and to_jsonb(t) = E'{"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","id":"b28d8770-9ac9-5b5f-bfe2-7280d7422a21","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: claim_edges[0] row does not match apply receipt'; + end if; + if (select count(*) from public.reasoning_tools t + where t.id = E'2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0'::uuid and to_jsonb(t) = E'{"agent_id":null,"category":"verification","created_at":"2026-07-15T01:59:04.44165+00:00","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: reasoning_tools[0] row does not match apply receipt'; + end if; + if (select count(*) from public.sources t + where t.id = E'ed9da5f1-846e-5298-8689-15027a7ce56d'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: sources[0] row does not match apply receipt'; + end if; + if (select count(*) from public.sources t + where t.id = E'a86f55dc-5058-585d-b492-a4f1d932670f'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: sources[1] row does not match apply receipt'; + end if; + if (select count(*) from public.claims t + where t.id = E'71a3331b-fb75-5e18-aa61-b256bc38af36'::uuid and to_jsonb(t) = E'{"confidence":0.85,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept","updated_at":"2026-07-15T01:59:04.44165+00:00"}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: claims[0] row does not match apply receipt'; + end if; + if (select count(*) from public.claims t + where t.id = E'38dead14-6b1d-5909-99c4-3c45ad2dd21f'::uuid and to_jsonb(t) = E'{"confidence":0.9,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural","updated_at":"2026-07-15T01:59:04.44165+00:00"}'::jsonb) <> 1 then + raise exception 'proposal rollback drift: claims[1] row does not match apply receipt'; + end if; + delete from public.claim_evidence where id in (E'dac3934f-b7ad-5205-8efe-a00163370a54'::uuid, E'13e580c5-458d-5146-aef3-8c74ffc43b7c'::uuid); + get diagnostics affected = row_count; + if affected <> 2 then + raise exception 'proposal rollback count mismatch for claim_evidence: expected 2, got %', affected; + end if; + delete from public.claim_edges where id in (E'b28d8770-9ac9-5b5f-bfe2-7280d7422a21'::uuid); + get diagnostics affected = row_count; + if affected <> 1 then + raise exception 'proposal rollback count mismatch for claim_edges: expected 1, got %', affected; + end if; + delete from public.reasoning_tools where id in (E'2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0'::uuid); + get diagnostics affected = row_count; + if affected <> 1 then + raise exception 'proposal rollback count mismatch for reasoning_tools: expected 1, got %', affected; + end if; + delete from public.sources where id in (E'ed9da5f1-846e-5298-8689-15027a7ce56d'::uuid, E'a86f55dc-5058-585d-b492-a4f1d932670f'::uuid); + get diagnostics affected = row_count; + if affected <> 2 then + raise exception 'proposal rollback count mismatch for sources: expected 2, got %', affected; + end if; + delete from public.claims where id in (E'71a3331b-fb75-5e18-aa61-b256bc38af36'::uuid, E'38dead14-6b1d-5909-99c4-3c45ad2dd21f'::uuid); + get diagnostics affected = row_count; + if affected <> 2 then + raise exception 'proposal rollback count mismatch for claims: expected 2, got %', affected; + end if; + update kb_stage.kb_proposals + set status = 'approved', + applied_by_handle = null, + applied_by_agent_id = null, + applied_at = null, + updated_at = now() + where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + and status = 'applied' + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and applied_at is not distinct from E'2026-07-15 01:59:04.449051+00'::timestamptz; + get diagnostics affected = row_count; + if affected <> 1 then + raise exception 'proposal rollback: expected one applied ledger row, got %', affected; + end if; +end +$rollback$; +commit; diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json new file mode 100644 index 0000000..d494493 --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json @@ -0,0 +1,3324 @@ +{ + "applied_rollback_receipt": { + "applied_row_ids": { + "claim_edges": [ + "b28d8770-9ac9-5b5f-bfe2-7280d7422a21" + ], + "claim_evidence": [ + "13e580c5-458d-5146-aef3-8c74ffc43b7c", + "dac3934f-b7ad-5205-8efe-a00163370a54" + ], + "claims": [ + "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "71a3331b-fb75-5e18-aa61-b256bc38af36" + ], + "reasoning_tools": [ + "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + ], + "sources": [ + "a86f55dc-5058-585d-b492-a4f1d932670f", + "ed9da5f1-846e-5298-8689-15027a7ce56d" + ] + }, + "applied_row_sha256": { + "claim_edges": [ + "60d14cbc45d424fa1eb62db6478f185bf2c2d86559e57ffa77474e8d0b3c527c" + ], + "claim_evidence": [ + "e97de162c0730da69b357e1350f0da7e5843c4e67d498c12d731a0f04a8868d7", + "3054718195abe3f78e08cfcacd59902d41eb91c7153c6c63f9bcb3bc7c6902ac" + ], + "claims": [ + "e593b9cf7b0bc9267f3e48d8173129b84b09c028f290f1abc97ccb73940b31dc", + "24280b5159cbbf75e00eb24ae50ab69994397a583f347a241a5e262cf0c03179" + ], + "reasoning_tools": [ + "257924b236c3c27289b9ae2314687be0e96779415fc6ff87faada22893b757ba" + ], + "sources": [ + "d7a690c2b18701db5b48e8189b1621c8025c1ed75889a4d0a3a4c9761c03dc3b", + "bee048794799006bd00bf4bb02ae57998e670f5bcdfb140dff871dcb042d0198" + ] + }, + "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", + "apply_receipt_sha256": "2aa65fe4509c6699af34e418de27c0225efe751223aaebf3f9b545fa159c754e", + "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", + "approval_snapshot_sha256": "310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9", + "artifact": "proposal_apply_lifecycle_receipt", + "checks": { + "apply_receipt_replay_ready": true, + "apply_rows_have_exact_ids": true, + "fresh_owned_targets": true, + "immutable_approval_unchanged": true, + "rollback_counts_restored": true, + "rollback_ledger_restored_to_approved": true, + "rollback_replay_refused_without_mutation": true, + "rollback_sql_exact_for_bound_rows": true, + "rollback_target_rows_absent": true, + "unrelated_rows_unchanged": true + }, + "current_tier": "T2_runtime", + "fresh_preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", + "fresh_preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", + "generated_at_utc": "2026-07-15T01:59:05.526171+00:00", + "lifecycle_receipt_sha256": "8e74cf1f5c372633f9b6f15363ff759ba6ce9bf42df51288bb9be70ddabe49b3", + "pass": true, + "production_apply_authorization_present": false, + "production_apply_executed": false, + "proposal_before_apply": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "status": "approved" + }, + "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "required_tier": "T2_runtime", + "rollback": { + "counts_after_rollback": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "counts_before_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "delete_order": [ + "claim_evidence", + "claim_edges", + "reasoning_tools", + "sources", + "claims" + ], + "proposal_after": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "status": "approved" + }, + "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", + "schema": "livingip.proposalApplyRollback.v1", + "target_rows_after": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + } + }, + "schema": "livingip.proposalApplyLifecycleReceipt.v1", + "strongest_claim_allowed": "deterministic disposable-clone apply and compensating rollback" + }, + "apply_transition": { + "applied_readback": { + "applied_at": "2026-07-15 01:59:04.449051+00", + "applied_by_agent_id": "44444444-4444-4444-4444-444444444444", + "applied_by_handle": "kb-apply", + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "applied" + }, + "approved_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "exact_transition": true, + "immutable_approval_matches_applied_ledger": true, + "immutable_approval_readback": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + } + }, + "checks": { + "apply_transition_exact": true, + "claim_evidence_exact_after_permission_probe": true, + "clone_apply_table_deltas_exact": true, + "clone_cleanup_complete": true, + "clone_prerequisites_omit_cluster_role_ddl": true, + "compensating_rollback_receipt_passes": true, + "conflict_review_separate_and_exact": true, + "conflict_transaction_rolled_back_exactly": true, + "first_apply_succeeded": true, + "fresh_owned_preflight_exact": true, + "gateway_process_unchanged": null, + "idempotent_replay_refused": true, + "kb_apply_cannot_mutate_immutable_approval": true, + "kb_apply_cannot_mutate_proposal_approval": true, + "kb_apply_cannot_mutate_proposal_payload": true, + "kb_apply_cannot_update_existing_claim_evidence": true, + "kb_review_approval_succeeded": true, + "kb_review_used_security_definer": true, + "mutation_between_build_and_execute_refused": true, + "outer_container_absent_independent_readback": true, + "outer_container_has_no_docker_volumes": true, + "outer_container_lifecycle_labeled": true, + "outer_container_network_disabled": true, + "outer_isolation_complete": true, + "outer_labeled_container_absent_independent_readback": true, + "outer_live_counts_exactly_unchanged": true, + "outer_live_table_deltas_exactly_zero": true, + "outer_service_observed_if_required": true, + "outer_service_stable_if_observed": true, + "outer_source_tier_enforced": true, + "outer_workdir_absent_independent_readback": true, + "payload_agents_seeded_exactly": true, + "payload_projection_exact": true, + "proposal_exact_after_permission_probes": true, + "review_transition_exact": true, + "reviewer_agent_seeded_exactly": true, + "rollback_replay_refused_without_mutation": true, + "security_definer_dependencies_ready": true, + "source_binding_independently_verified": true, + "source_cluster_roles_preexisting": true, + "source_cluster_roles_unchanged": true, + "source_files_unchanged_during_run": true, + "source_hash_conflict_refused": true, + "source_table_deltas_exactly_zero": true, + "source_target_rows_unchanged": true, + "stale_ephemeral_paths_absent": true + }, + "cleanup_readback": { + "drop_attempted": true, + "leftover_clone_database_count": 0, + "returncode": 0, + "stderr": "", + "stdout": "pg_terminate_backend \n----------------------\n(0 rows)\n\nDROP DATABASE" + }, + "cleanup_returncode": 0, + "clone_apply_table_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 1, + "public.claim_evidence": 2, + "public.claims": 2, + "public.reasoning_tools": 1, + "public.sources": 2 + }, + "clone_counts_after_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 1, + "public.claim_evidence": 3, + "public.claims": 3, + "public.reasoning_tools": 1, + "public.sources": 3 + }, + "clone_counts_before_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "clone_created": true, + "clone_database": "teleo_approve_claim_isolated_08c2358330", + "clone_dropped": true, + "clone_prerequisite_sanitization": { + "clone_sql_sha256": "a02a03a704954058745d8cee4d25597bb8eaeee2ae211d4f9be4fe055f3d98ec", + "cluster_role_ddl_removed": true, + "removed_alter_role_statements": 3, + "removed_create_role_statements": 2, + "source_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa" + }, + "conflict_apply": { + "returncode": 1, + "source_hash_collision_refusal": true, + "stderr": "psql failed (3)\nSTDOUT:\n\n\nSTDERR:\nERROR: approve_claim: source hash collision for source 980ac481-1fa3-508f-b093-95de4ff4f8bc\nCONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE" + }, + "conflict_readback": { + "canonical_rows": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + }, + "canonical_rows_absent": true, + "immutable_approval": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.5, + "created_by": null, + "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "status": "open", + "superseded_by": null, + "tags": [ + "conflict-canary" + ], + "text": "This row must roll back with the conflicting source.", + "type": "structural" + } + ], + "contract_version": 2, + "edges": [], + "evidence": [], + "reasoning_tools": [], + "sources": [ + { + "created_by": null, + "excerpt": "Conflicting source id.", + "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", + "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:06.046049+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_unchanged": true, + "proposal": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.5, + "created_by": null, + "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "status": "open", + "superseded_by": null, + "tags": [ + "conflict-canary" + ], + "text": "This row must roll back with the conflicting source.", + "type": "structural" + } + ], + "contract_version": 2, + "edges": [], + "evidence": [], + "reasoning_tools": [], + "sources": [ + { + "created_by": null, + "excerpt": "Conflicting source id.", + "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", + "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:06.046049+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-conflict-canary", + "status": "approved" + }, + "proposal_approval_unchanged": true + }, + "conflict_review_transition": { + "approved_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.5, + "created_by": null, + "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "status": "open", + "superseded_by": null, + "tags": [ + "conflict-canary" + ], + "text": "This row must roll back with the conflicting source.", + "type": "structural" + } + ], + "contract_version": 2, + "edges": [], + "evidence": [], + "reasoning_tools": [], + "sources": [ + { + "created_by": null, + "excerpt": "Conflicting source id.", + "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", + "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:06.046049+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-conflict-canary", + "status": "approved" + }, + "exact_transition": true, + "immutable_approval_matches_ledger": true, + "immutable_approval_readback": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.5, + "created_by": null, + "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "status": "open", + "superseded_by": null, + "tags": [ + "conflict-canary" + ], + "text": "This row must roll back with the conflicting source.", + "type": "structural" + } + ], + "contract_version": 2, + "edges": [], + "evidence": [], + "reasoning_tools": [], + "sources": [ + { + "created_by": null, + "excerpt": "Conflicting source id.", + "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", + "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:06.046049+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "pending_immutable_approval": null, + "pending_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.5, + "created_by": null, + "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "status": "open", + "superseded_by": null, + "tags": [ + "conflict-canary" + ], + "text": "This row must roll back with the conflicting source.", + "type": "structural" + } + ], + "contract_version": 2, + "edges": [], + "evidence": [], + "reasoning_tools": [], + "sources": [ + { + "created_by": null, + "excerpt": "Conflicting source id.", + "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", + "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": null, + "reviewed_at": null, + "reviewed_by_agent_id": null, + "reviewed_by_handle": null, + "source_ref": "working-leo:approve-claim-conflict-canary", + "status": "pending_review" + }, + "review_apply": { + "returncode": 0, + "stderr": "", + "stdout": "{\"id\": \"7cb1468f-861c-5a85-ae32-470d891af133\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 01:59:06.046049+00\", \"reviewed_by_agent_id\": \"11111111-1111-4111-8111-111111111111\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + } + }, + "current_tier": "T2_runtime", + "dependencies": { + "apply_role": "kb_apply", + "apply_script": "scripts/apply_proposal.py", + "approve_script": "scripts/approve_proposal.py", + "credential_files": { + "apply": { + "present_at_start": true, + "runtime_location": "ephemeral_or_operator_managed" + }, + "review": { + "present_at_start": true, + "runtime_location": "ephemeral_or_operator_managed" + } + }, + "gate_owner_role": "kb_gate_owner", + "immutable_approval_table": "kb_stage.kb_proposal_approvals", + "prerequisites_sql": "scripts/kb_apply_prereqs.sql", + "review_role": "kb_review", + "reviewer_handle": "m3ta", + "security_definer_argument_types": { + "kb_stage.approve_strict_proposal": "uuid, text, jsonb, text, text", + "kb_stage.assert_approved_proposal": "uuid, text, jsonb, text, uuid, timestamp with time zone, text", + "kb_stage.finish_approved_proposal": "uuid, text, jsonb, text, uuid, timestamp with time zone, text, text" + }, + "security_definer_functions": [ + "kb_stage.approve_strict_proposal", + "kb_stage.assert_approved_proposal", + "kb_stage.finish_approved_proposal" + ] + }, + "external_claim_seed": { + "clone_rows": [], + "exact_clone_copy": true, + "required_ids": [], + "source_rows": [] + }, + "first_apply": { + "result": { + "applied": true, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "replay_material_sha256": "767fe35fc91b4cd9b82287e828d6a6a86521bd82f23b651e9a91db977c55af59", + "replay_ready": true + }, + "returncode": 0, + "stderr": "" + }, + "fixture_ids": { + "conflict_claim_id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "conflict_proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", + "conflict_source_id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "permission_claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", + "permission_source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946" + }, + "fresh_owned_preflight": { + "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", + "artifact": "proposal_apply_fresh_preflight", + "captured_at_utc": "2026-07-15T01:59:04.091167+00:00", + "fresh_owned_targets": true, + "preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", + "preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "proposal_type": "approve_claim", + "schema": "livingip.proposalApplyFreshPreflight.v1", + "target_rows_before": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + } + }, + "gateway_process_observable": false, + "generated_at_utc": "2026-07-15T01:59:02.013207+00:00", + "idempotent_replay": { + "already_applied_refusal": true, + "returncode": 1, + "stderr": "proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 is already applied (idempotent no-op)" + }, + "kb_apply_claim_evidence_update_probe": { + "after": { + "claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", + "created_by": null, + "role": "grounds", + "source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", + "weight": 0.42 + }, + "attempt": { + "refused": true, + "returncode": 3, + "stderr": "ERROR: permission denied for table claim_evidence", + "stdout": "" + }, + "before": { + "claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", + "created_by": null, + "role": "grounds", + "source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", + "weight": 0.42 + }, + "exact_row_unchanged": true + }, + "kb_apply_proposal_mutation_probes": { + "after": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "approval_fields": { + "refused": true, + "returncode": 3, + "stderr": "ERROR: permission denied for table kb_proposals", + "stdout": "" + }, + "before": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "exact_row_unchanged": true, + "immutable_approval_after": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_before": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_exactly_unchanged": true, + "immutable_approval_payload": { + "refused": true, + "returncode": 3, + "stderr": "ERROR: permission denied for table kb_proposal_approvals", + "stdout": "" + }, + "payload": { + "refused": true, + "returncode": 3, + "stderr": "ERROR: permission denied for table kb_proposals", + "stdout": "" + } + }, + "leftover_clone_count": 0, + "mutation_between_build_and_execute": { + "approval_restored_exactly": true, + "approved_before_mutation": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "build_returncode": 0, + "built_sql_sha256": "19f5dd6c27f293bfdc89adee59ffa99beb4503dba5aaa6291c9808ff16769ee7", + "built_sql_uses_assert_approved_proposal": true, + "built_sql_uses_finish_approved_proposal": true, + "canonical_rows_unchanged": true, + "immutable_approval_after_ledger_mutation": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_after_stale_execute": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_before_mutation": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "immutable_approval_never_changed": true, + "mutated_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + }, + "mutation_after_build": true + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "proposal_after_stale_execute": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + }, + "mutation_after_build": true + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "restored_immutable_approval": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "restored_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "rows_after_stale_execute": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + }, + "stale_apply_refused": true, + "stale_execute": { + "returncode": 3, + "stderr": "ERROR: assert_approved_proposal: proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 is not the exact immutable approved snapshot\nCONTEXT: PL/pgSQL function kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamp with time zone,text) line 22 at RAISE", + "stdout": "" + } + }, + "outer_isolation": { + "canonical_table_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 0, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "cleanup_readback": { + "container_name_query_returncode": 0, + "container_name_query_stdout": "", + "container_remove_returncode": 0, + "label_scoped_orphan_count": 0, + "label_scoped_query_returncode": 0, + "label_scoped_query_stdout": "", + "label_scoped_temporary_container_absent": true, + "temporary_container_absent": true, + "temporary_workdir_absent": true, + "workdir_lexists_after_cleanup": false, + "workdir_remove_returncode": 0 + }, + "container_isolation": { + "canary_label": "proposal-apply-lifecycle", + "instance_label": "working-leo-approve-claim-6715-44544", + "lifecycle_labeled": true, + "network_disabled": true, + "network_mode": "none", + "no_docker_volumes": true, + "volume_mounts": [] + }, + "service_after": { + "Available": "false", + "Reason": "systemctl_unavailable" + }, + "service_before": { + "Available": "false", + "Reason": "systemctl_unavailable" + }, + "service_gate_passes": true, + "service_observable": false, + "service_required": false, + "service_stable": null, + "source_boundary": { + "canary_label": "working-leo-approved-source", + "network_mode": "none", + "source_tier": "isolated-local", + "tier_enforced": true + }, + "source_container": "leo-proposal-lifecycle-source-20260715", + "source_counts_after": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 2, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "source_counts_before": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 2, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "source_counts_unchanged": true, + "source_database": "teleo" + }, + "payload_agent_seed": { + "clone_rows": [], + "exact_clone_copy": true, + "required_ids": [], + "source_rows": [] + }, + "payload_projection": { + "expected_rows": { + "claim_edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "claim_evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + }, + "expected_table_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 1, + "public.claim_evidence": 2, + "public.claims": 2, + "public.reasoning_tools": 1, + "public.sources": 2 + }, + "payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684" + }, + "post_run_cleanup": { + "gateway_active_state": null, + "gateway_main_pid": null, + "gateway_process_observable": false, + "gateway_restart_count": null, + "gateway_sub_state": null, + "leftover_clone_database_count": 0 + }, + "required_tier": "T2_runtime", + "required_tiers": [ + "T2_runtime" + ], + "review_transition": { + "approved_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "approved" + }, + "exact_transition": true, + "immutable_approval_matches_ledger": true, + "immutable_approval_readback": { + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_db_role": "kb_review", + "reviewed_by_handle": "m3ta" + }, + "pending_immutable_approval": null, + "pending_readback": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "channel": "clone_canary", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "rationale": "Exercise strict canonical bundle review and apply lifecycle.", + "review_note": null, + "reviewed_at": null, + "reviewed_by_agent_id": null, + "reviewed_by_handle": null, + "source_ref": "working-leo:approve-claim-clone-canary", + "status": "pending_review" + }, + "review_apply": { + "returncode": 0, + "stderr": "", + "stdout": "{\"id\": \"9b2b5fa4-0e0d-5db0-aa4d-6fd102889946\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 01:59:03.105846+00\", \"reviewed_by_agent_id\": \"11111111-1111-4111-8111-111111111111\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + }, + "review_dry_run": { + "returncode": 0, + "stderr": "", + "uses_approve_strict_proposal": true + } + }, + "reviewer_agent_seed": { + "clone_row": { + "handle": "m3ta", + "id": "11111111-1111-4111-8111-111111111111", + "kind": "human" + }, + "exact_clone_copy": true, + "reviewer_handle": "m3ta", + "source_row": { + "handle": "m3ta", + "id": "11111111-1111-4111-8111-111111111111", + "kind": "human" + } + }, + "rollback_plan": { + "execution_authority": "disposable_clone_admin_only", + "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", + "schema": "livingip.proposalApplyRollback.v1" + }, + "rollback_replay": { + "refused": true, + "returncode": 3, + "state_unchanged": true, + "stderr": "ERROR: proposal rollback: applied ledger does not match apply receipt\nCONTEXT: PL/pgSQL function inline_code_block line 26 at RAISE" + }, + "row_readback": { + "claim_edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "claim_evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + }, + "runtime_scope": "isolated_postgres_container_from_readonly_local_fixture", + "schema": "working-leo.approve-claim-clone-canary.v3", + "security_definer_readback": { + "functions": [ + { + "argument_types": "uuid, text, jsonb, text, text", + "expected_role": "kb_review", + "expected_role_execute": true, + "function": "kb_stage.approve_strict_proposal", + "identity_arguments": "p_proposal_id uuid, p_expected_proposal_type text, p_expected_payload jsonb, p_expected_reviewed_by_handle text, p_review_note text", + "other_runtime_role_execute": false, + "owner": "kb_gate_owner", + "present": true, + "public_execute": false, + "security_definer": true + }, + { + "argument_types": "uuid, text, jsonb, text, uuid, timestamp with time zone, text", + "expected_role": "kb_apply", + "expected_role_execute": true, + "function": "kb_stage.assert_approved_proposal", + "identity_arguments": "p_proposal_id uuid, p_proposal_type text, p_payload jsonb, p_reviewed_by_handle text, p_reviewed_by_agent_id uuid, p_reviewed_at timestamp with time zone, p_review_note text", + "other_runtime_role_execute": false, + "owner": "kb_gate_owner", + "present": true, + "public_execute": false, + "security_definer": true + }, + { + "argument_types": "uuid, text, jsonb, text, uuid, timestamp with time zone, text, text", + "expected_role": "kb_apply", + "expected_role_execute": true, + "function": "kb_stage.finish_approved_proposal", + "identity_arguments": "p_proposal_id uuid, p_proposal_type text, p_payload jsonb, p_reviewed_by_handle text, p_reviewed_by_agent_id uuid, p_reviewed_at timestamp with time zone, p_review_note text, p_applied_by_handle text", + "other_runtime_role_execute": false, + "owner": "kb_gate_owner", + "present": true, + "public_execute": false, + "security_definer": true + } + ], + "login_role_owned_objects": [], + "protected_role_memberships": [], + "role_privileges": { + "kb_apply_approval_snapshot_select": false, + "kb_apply_approval_snapshot_update": false, + "kb_apply_claim_evidence_insert": true, + "kb_apply_claim_evidence_update": false, + "kb_apply_proposal_select": true, + "kb_apply_proposal_update": false, + "kb_review_approval_snapshot_select": false, + "kb_review_approval_snapshot_update": false, + "kb_review_proposal_select": true, + "kb_review_proposal_update": false + }, + "unexpected_overloads": [] + }, + "service_after": { + "available": false, + "reason": "systemctl_unavailable", + "returncode": 127 + }, + "service_before": { + "available": false, + "reason": "systemctl_unavailable", + "returncode": 127 + }, + "service_restarted": null, + "source_binding": { + "files": [ + { + "repo_relative_path": "scripts/apply_proposal.py", + "sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "size_bytes": 47270 + }, + { + "repo_relative_path": "scripts/approve_proposal.py", + "sha256": "e991498264bd0f49755dfef809212fa7151a668ce479b100d830e447775a9fe0", + "size_bytes": 7323 + }, + { + "repo_relative_path": "scripts/finalize_approve_claim_isolated_canary.py", + "sha256": "d5dbd250a9fc28a22ab0880a57c330b3c95119b95d96c5df95cbaf49648bccb5", + "size_bytes": 10684 + }, + { + "repo_relative_path": "scripts/kb_apply_prereqs.sql", + "sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "size_bytes": 42602 + }, + { + "repo_relative_path": "scripts/proposal_apply_lifecycle.py", + "sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", + "size_bytes": 71314 + }, + { + "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", + "sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", + "size_bytes": 88340 + }, + { + "repo_relative_path": "scripts/run_approve_claim_isolated_container_canary.sh", + "sha256": "ed81a8f8c05d516809bb54c80d82786ed941dc1cf87150f25addc935685c72bb", + "size_bytes": 9239 + } + ], + "independent_post_cleanup_verification": { + "all_match": true, + "files": [ + { + "actual_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "expected_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "matches": true, + "repo_relative_path": "scripts/apply_proposal.py", + "size_bytes": 47270 + }, + { + "actual_sha256": "e991498264bd0f49755dfef809212fa7151a668ce479b100d830e447775a9fe0", + "expected_sha256": "e991498264bd0f49755dfef809212fa7151a668ce479b100d830e447775a9fe0", + "matches": true, + "repo_relative_path": "scripts/approve_proposal.py", + "size_bytes": 7323 + }, + { + "actual_sha256": "d5dbd250a9fc28a22ab0880a57c330b3c95119b95d96c5df95cbaf49648bccb5", + "expected_sha256": "d5dbd250a9fc28a22ab0880a57c330b3c95119b95d96c5df95cbaf49648bccb5", + "matches": true, + "repo_relative_path": "scripts/finalize_approve_claim_isolated_canary.py", + "size_bytes": 10684 + }, + { + "actual_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "expected_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "matches": true, + "repo_relative_path": "scripts/kb_apply_prereqs.sql", + "size_bytes": 42602 + }, + { + "actual_sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", + "expected_sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", + "matches": true, + "repo_relative_path": "scripts/proposal_apply_lifecycle.py", + "size_bytes": 71314 + }, + { + "actual_sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", + "expected_sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", + "matches": true, + "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", + "size_bytes": 88340 + }, + { + "actual_sha256": "ed81a8f8c05d516809bb54c80d82786ed941dc1cf87150f25addc935685c72bb", + "expected_sha256": "ed81a8f8c05d516809bb54c80d82786ed941dc1cf87150f25addc935685c72bb", + "matches": true, + "repo_relative_path": "scripts/run_approve_claim_isolated_container_canary.sh", + "size_bytes": 9239 + } + ] + }, + "post_run_files": [ + { + "repo_relative_path": "scripts/apply_proposal.py", + "sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "size_bytes": 47270 + }, + { + "repo_relative_path": "scripts/approve_proposal.py", + "sha256": "e991498264bd0f49755dfef809212fa7151a668ce479b100d830e447775a9fe0", + "size_bytes": 7323 + }, + { + "repo_relative_path": "scripts/finalize_approve_claim_isolated_canary.py", + "sha256": "d5dbd250a9fc28a22ab0880a57c330b3c95119b95d96c5df95cbaf49648bccb5", + "size_bytes": 10684 + }, + { + "repo_relative_path": "scripts/kb_apply_prereqs.sql", + "sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "size_bytes": 42602 + }, + { + "repo_relative_path": "scripts/proposal_apply_lifecycle.py", + "sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", + "size_bytes": 71314 + }, + { + "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", + "sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", + "size_bytes": 88340 + }, + { + "repo_relative_path": "scripts/run_approve_claim_isolated_container_canary.sh", + "sha256": "ed81a8f8c05d516809bb54c80d82786ed941dc1cf87150f25addc935685c72bb", + "size_bytes": 9239 + } + ], + "unchanged_during_run": true + }, + "source_cluster_roles_after": [ + { + "rolbypassrls": false, + "rolcanlogin": true, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_apply", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + }, + { + "rolbypassrls": false, + "rolcanlogin": false, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_gate_owner", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + }, + { + "rolbypassrls": false, + "rolcanlogin": true, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_review", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + } + ], + "source_cluster_roles_before": [ + { + "rolbypassrls": false, + "rolcanlogin": true, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_apply", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + }, + { + "rolbypassrls": false, + "rolcanlogin": false, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_gate_owner", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + }, + { + "rolbypassrls": false, + "rolcanlogin": true, + "rolconnlimit": -1, + "rolcreatedb": false, + "rolcreaterole": false, + "rolinherit": false, + "rolname": "kb_review", + "rolreplication": false, + "rolsuper": false, + "rolvaliduntil": null + } + ], + "source_counts_after": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 2, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "source_counts_before": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 2, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "source_counts_observed_unchanged": true, + "source_database": "teleo", + "source_database_mutated": false, + "source_table_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 0, + "public.claim_evidence": 0, + "public.claims": 0, + "public.reasoning_tools": 0, + "public.sources": 0 + }, + "source_target_rows_after": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + }, + "source_target_rows_before": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + }, + "status": "pass", + "strict_receipt": { + "canonical_row_keys": { + "actual": { + "public.claim_edges": [ + { + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36" + } + ], + "public.claim_evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d" + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f" + } + ], + "public.claims": [ + "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "71a3331b-fb75-5e18-aa61-b256bc38af36" + ], + "public.reasoning_tools": [ + "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + ], + "public.sources": [ + "a86f55dc-5058-585d-b492-a4f1d932670f", + "ed9da5f1-846e-5298-8689-15027a7ce56d" + ] + }, + "expected": { + "public.claim_edges": [ + { + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36" + } + ], + "public.claim_evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d" + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f" + } + ], + "public.claims": [ + "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "71a3331b-fb75-5e18-aa61-b256bc38af36" + ], + "public.reasoning_tools": [ + "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + ], + "public.sources": [ + "a86f55dc-5058-585d-b492-a4f1d932670f", + "ed9da5f1-846e-5298-8689-15027a7ce56d" + ] + } + }, + "checks": { + "before_after_counts_present": true, + "canonical_row_keys_exact": true, + "canonical_rows_exact": true, + "clone_database_removed": true, + "conflict_transaction_rolled_back": true, + "proposal_applied_at_present": true, + "proposal_id_exact": true, + "proposal_status_applied": true, + "source_database_unchanged": true, + "table_deltas_exact": true + }, + "pass": true, + "proposal": { + "applied_at": "2026-07-15 01:59:04.449051+00", + "applied_by_handle": "kb-apply", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "status": "applied" + }, + "rollback_cleanup": { + "clone_database_removed": true, + "conflict_transaction_rolled_back": true, + "leftover_clone_database_count": 0, + "source_database_unchanged": true + }, + "row_counts": { + "actual_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 1, + "public.claim_evidence": 2, + "public.claims": 2, + "public.reasoning_tools": 1, + "public.sources": 2 + }, + "after_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 1, + "public.claim_evidence": 3, + "public.claims": 3, + "public.reasoning_tools": 1, + "public.sources": 3 + }, + "before_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "expected_deltas": { + "kb_stage.kb_proposals": 0, + "public.claim_edges": 1, + "public.claim_evidence": 2, + "public.claims": 2, + "public.reasoning_tools": 1, + "public.sources": 2 + } + }, + "schema": "working-leo.approved-change-strict-receipt.v1" + }, + "target_rows_before_apply": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + }, + "telegram_messages_sent": false, + "unrelated_fingerprint_before_apply": { + "kb_stage.kb_proposal_approvals": { + "content_md5": "d41d8cd98f00b204e9800998ecf8427e", + "row_count": 0 + }, + "kb_stage.kb_proposals": { + "content_md5": "d41d8cd98f00b204e9800998ecf8427e", + "row_count": 0 + }, + "public.agents": { + "content_md5": "56bbdd947ace3bd545744a2995795702", + "row_count": 2 + }, + "public.claim_edges": { + "content_md5": "d41d8cd98f00b204e9800998ecf8427e", + "row_count": 0 + }, + "public.claim_evidence": { + "content_md5": "bc66b511bcc4926bb9065f98b41ce8ae", + "row_count": 1 + }, + "public.claims": { + "content_md5": "5cfbe5bd4ed3dc24adab29cb39f0b594", + "row_count": 1 + }, + "public.reasoning_tools": { + "content_md5": "d41d8cd98f00b204e9800998ecf8427e", + "row_count": 0 + }, + "public.sources": { + "content_md5": "592f899d41dfeeecdb449402eb97ebd3", + "row_count": 1 + } + } +} diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json new file mode 100644 index 0000000..e5a2a3d --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json @@ -0,0 +1,217 @@ +{ + "applied_row_ids": { + "claim_edges": [ + "b28d8770-9ac9-5b5f-bfe2-7280d7422a21" + ], + "claim_evidence": [ + "13e580c5-458d-5146-aef3-8c74ffc43b7c", + "dac3934f-b7ad-5205-8efe-a00163370a54" + ], + "claims": [ + "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "71a3331b-fb75-5e18-aa61-b256bc38af36" + ], + "reasoning_tools": [ + "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + ], + "sources": [ + "a86f55dc-5058-585d-b492-a4f1d932670f", + "ed9da5f1-846e-5298-8689-15027a7ce56d" + ] + }, + "applied_row_sha256": { + "claim_edges": [ + "60d14cbc45d424fa1eb62db6478f185bf2c2d86559e57ffa77474e8d0b3c527c" + ], + "claim_evidence": [ + "e97de162c0730da69b357e1350f0da7e5843c4e67d498c12d731a0f04a8868d7", + "3054718195abe3f78e08cfcacd59902d41eb91c7153c6c63f9bcb3bc7c6902ac" + ], + "claims": [ + "e593b9cf7b0bc9267f3e48d8173129b84b09c028f290f1abc97ccb73940b31dc", + "24280b5159cbbf75e00eb24ae50ab69994397a583f347a241a5e262cf0c03179" + ], + "reasoning_tools": [ + "257924b236c3c27289b9ae2314687be0e96779415fc6ff87faada22893b757ba" + ], + "sources": [ + "d7a690c2b18701db5b48e8189b1621c8025c1ed75889a4d0a3a4c9761c03dc3b", + "bee048794799006bd00bf4bb02ae57998e670f5bcdfb140dff871dcb042d0198" + ] + }, + "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", + "apply_receipt_sha256": "2aa65fe4509c6699af34e418de27c0225efe751223aaebf3f9b545fa159c754e", + "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", + "approval_snapshot_sha256": "310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9", + "artifact": "proposal_apply_lifecycle_receipt", + "checks": { + "apply_receipt_replay_ready": true, + "apply_rows_have_exact_ids": true, + "fresh_owned_targets": true, + "immutable_approval_unchanged": true, + "rollback_counts_restored": true, + "rollback_ledger_restored_to_approved": true, + "rollback_replay_refused_without_mutation": true, + "rollback_sql_exact_for_bound_rows": true, + "rollback_target_rows_absent": true, + "unrelated_rows_unchanged": true + }, + "current_tier": "T2_runtime", + "fresh_preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", + "fresh_preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", + "generated_at_utc": "2026-07-15T01:59:05.526171+00:00", + "lifecycle_receipt_sha256": "8e74cf1f5c372633f9b6f15363ff759ba6ce9bf42df51288bb9be70ddabe49b3", + "pass": true, + "production_apply_authorization_present": false, + "production_apply_executed": false, + "proposal_before_apply": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "status": "approved" + }, + "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "required_tier": "T2_runtime", + "rollback": { + "counts_after_rollback": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "counts_before_apply": { + "kb_stage.kb_proposals": 1, + "public.claim_edges": 0, + "public.claim_evidence": 1, + "public.claims": 1, + "public.reasoning_tools": 0, + "public.sources": 1 + }, + "delete_order": [ + "claim_evidence", + "claim_edges", + "reasoning_tools", + "sources", + "claims" + ], + "proposal_after": { + "applied_at": null, + "applied_by_agent_id": null, + "applied_by_handle": null, + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_type": "approve_claim", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta", + "status": "approved" + }, + "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", + "schema": "livingip.proposalApplyRollback.v1", + "target_rows_after": { + "claim_edges": [], + "claim_evidence": [], + "claims": [], + "reasoning_tools": [], + "sources": [] + } + }, + "schema": "livingip.proposalApplyLifecycleReceipt.v1", + "strongest_claim_allowed": "deterministic disposable-clone apply and compensating rollback" +} diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json new file mode 100644 index 0000000..c56352f --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json @@ -0,0 +1,32 @@ +{ + "artifact": "proposal_apply_production_target_readback", + "schema": "livingip.proposalApplyProductionTargetReadback.v1", + "observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "transport": "ssh_readonly_transaction", + "read_only_transaction": true, + "read_only_setting": "on", + "container": "teleo-pg", + "database": "teleo", + "system_identifier": "7649789040005668902", + "server_version_num": "160014", + "approval_gate": { + "immutable_approval_table_present": false, + "approve_function_present": false, + "assert_function_present": false, + "finish_function_present": false, + "review_role_present": false, + "apply_role_present": true + }, + "approved_strict_candidate_count": 0, + "approved_strict_candidates": [], + "attempted_recovery": { + "strict_immutable_approval_join_attempted": true, + "strict_join_failed": true, + "strict_join_exact_gate": "relation kb_stage.kb_proposal_approvals does not exist", + "fallback_read_only_gate_and_candidate_count_succeeded": true + }, + "production_mutated": false, + "production_apply_authorization_present": false, + "production_apply_executed": false, + "claim_ceiling": "Fresh T3 live read-only identity and gate readback only. The immutable approval gate is absent and there are zero approved strict approve_claim candidates; production apply is neither authorized nor executed." +} diff --git a/pyproject.toml b/pyproject.toml index e264213..70fc9ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ dependencies = [ [project.optional-dependencies] dev = [ + "hypothesis>=6,<7", "pytest>=8", "pytest-asyncio>=0.23", "ruff>=0.3", diff --git a/scripts/apply_proposal.py b/scripts/apply_proposal.py index 7fd4bd3..88c3c65 100644 --- a/scripts/apply_proposal.py +++ b/scripts/apply_proposal.py @@ -111,8 +111,17 @@ CLAIM_TYPES = {"empirical", "structural", "normative", "meta", "concept"} SOURCE_TYPES = {"paper", "article", "transcript", "observation", "dataset", "post", "dm", "other"} EVIDENCE_ROLES = {"grounds", "illustrates", "contradicts"} EDGE_TYPES = { - "supports", "challenges", "requires", "relates", "contradicts", - "supersedes", "derives_from", "cites", "causes", "constrains", "accelerates", + "supports", + "challenges", + "requires", + "relates", + "contradicts", + "supersedes", + "derives_from", + "cites", + "causes", + "constrains", + "accelerates", } MAX_BUNDLE_ROWS = { @@ -143,6 +152,21 @@ def _jsonb(value: Any) -> str: return sql_literal(json.dumps(value, sort_keys=True)) + "::jsonb" +def deterministic_row_uuid(proposal_id: str, row_kind: str, *semantic_key: Any) -> str: + """Derive a stable persisted row id from the proposal and semantic key. + + Evidence and edge ids are not part of the reviewed v2 payload. Deriving + them here makes clone/production receipts and a pre-authorized rollback + packet bind the same exact ids instead of relying on database randomness. + """ + material = json.dumps( + ["livingip", "kb-apply", str(proposal_id), row_kind, *semantic_key], + ensure_ascii=True, + separators=(",", ":"), + ) + return str(uuid.uuid5(uuid.NAMESPACE_URL, material)) + + def _text_array(values: list[str]) -> str: if not values: return "'{}'::text[]" @@ -196,9 +220,7 @@ def _reject_unknown(mapping: dict[str, Any], allowed: set[str], path: str) -> No raise ValueError(f"{path} contains unknown fields: {unknown}") -def _validate_approval_meta( - approval: dict[str, Any], proposal_type: str, apply_payload: dict[str, Any] -) -> None: +def _validate_approval_meta(approval: dict[str, Any], proposal_type: str, apply_payload: dict[str, Any]) -> None: if not isinstance(approval, dict): raise ValueError("approved proposal metadata is required") if approval.get("proposal_type") != proposal_type: @@ -222,12 +244,12 @@ def _validate_approval_meta( def _approval_guard_sql(proposal_id: str, approval: dict[str, Any]) -> str: return f"""select kb_stage.assert_approved_proposal( {sql_literal(proposal_id)}::uuid, - {sql_literal(approval['proposal_type'])}, - {_jsonb(approval['payload'])}, - {sql_literal(approval['reviewed_by_handle'])}, - {sql_literal(approval.get('reviewed_by_agent_id'))}::uuid, - {sql_literal(approval['reviewed_at'])}::timestamptz, - {sql_literal(approval['review_note'])} + {sql_literal(approval["proposal_type"])}, + {_jsonb(approval["payload"])}, + {sql_literal(approval["reviewed_by_handle"])}, + {sql_literal(approval.get("reviewed_by_agent_id"))}::uuid, + {sql_literal(approval["reviewed_at"])}::timestamptz, + {sql_literal(approval["review_note"])} );""" @@ -245,12 +267,12 @@ end $verify$;""" finish_sql = f"""select kb_stage.finish_approved_proposal( {sql_literal(proposal_id)}::uuid, - {sql_literal(approval['proposal_type'])}, - {_jsonb(approval['payload'])}, - {sql_literal(approval['reviewed_by_handle'])}, - {sql_literal(approval.get('reviewed_by_agent_id'))}::uuid, - {sql_literal(approval['reviewed_at'])}::timestamptz, - {sql_literal(approval['review_note'])}, + {sql_literal(approval["proposal_type"])}, + {_jsonb(approval["payload"])}, + {sql_literal(approval["reviewed_by_handle"])}, + {sql_literal(approval.get("reviewed_by_agent_id"))}::uuid, + {sql_literal(approval["reviewed_at"])}::timestamptz, + {sql_literal(approval["review_note"])}, {sql_literal(applied_by)} );""" return checks_sql + "\n" + finish_sql @@ -301,9 +323,9 @@ update public.strategies insert into public.strategies (agent_id, diagnosis, guiding_policy, proximate_objectives, version, active) select {sql_literal(agent_id)}::uuid, - {sql_literal(strategy['diagnosis'])}, - {sql_literal(strategy['guiding_policy'])}, - {_jsonb(strategy['proximate_objectives'])}, + {sql_literal(strategy["diagnosis"])}, + {sql_literal(strategy["guiding_policy"])}, + {_jsonb(strategy["proximate_objectives"])}, coalesce(max(version), 0) + 1, true from public.strategies @@ -325,9 +347,7 @@ values raise exception 'apply_proposal: expected exactly one active strategy for agent %', {sql_literal(agent_id)}; end if;""" - ledger = _ledger_and_verify( - proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval - ) + ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval) return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval)) @@ -338,14 +358,16 @@ def build_add_edge_sql( approval: dict[str, Any], ) -> str: _validate_approval_meta(approval, "add_edge", apply_payload) - f = apply_payload.get("from_claim") - t = apply_payload.get("to_claim") + _reject_unknown(apply_payload, {"from_claim", "to_claim", "edge_type", "weight"}, "add_edge apply_payload") + f = _uuid(apply_payload.get("from_claim"), "add_edge.from_claim") + t = _uuid(apply_payload.get("to_claim"), "add_edge.to_claim") et = apply_payload.get("edge_type") - w = apply_payload.get("weight") - if not (f and t and et): - raise ValueError("add_edge apply_payload requires 'from_claim', 'to_claim', 'edge_type'") + if et not in EDGE_TYPES: + raise ValueError(f"add_edge.edge_type must be one of {sorted(EDGE_TYPES)}") + w = _weight(apply_payload.get("weight"), "add_edge.weight") if f == t: raise ValueError("add_edge from_claim and to_claim must differ") + row_id = deterministic_row_uuid(proposal_id, "claim_edge", f, t, et) edge_lock_key = f"claim_edge:{f}:{t}:{et}" canonical = f""" @@ -354,8 +376,8 @@ def build_add_edge_sql( select pg_advisory_xact_lock(hashtextextended({sql_literal(edge_lock_key)}, 0)); -- insert the edge unless an identical (from,to,type) edge already exists -insert into public.claim_edges (from_claim, to_claim, edge_type, weight) -select {sql_literal(f)}::uuid, {sql_literal(t)}::uuid, +insert into public.claim_edges (id, from_claim, to_claim, edge_type, weight) +select {sql_literal(row_id)}::uuid, {sql_literal(f)}::uuid, {sql_literal(t)}::uuid, {sql_literal(et)}::edge_type, {sql_literal(w)} where not exists ( select 1 from public.claim_edges @@ -364,7 +386,15 @@ select {sql_literal(f)}::uuid, {sql_literal(t)}::uuid, and edge_type = {sql_literal(et)}::edge_type); """.rstrip() - checks = f""" if exists (select 1 from public.claim_edges + checks = f""" -- Historical replay receipts can carry a pre-deterministic row id. + -- Require one exact semantic row; fresh applies still insert row_id above. + if (select count(*) from public.claim_edges + where from_claim = {sql_literal(f)}::uuid + and to_claim = {sql_literal(t)}::uuid + and edge_type = {sql_literal(et)}::edge_type) <> 1 then + raise exception 'apply_proposal: claim_edge row does not match strict apply payload'; + end if; + if exists (select 1 from public.claim_edges where from_claim = {sql_literal(f)}::uuid and to_claim = {sql_literal(t)}::uuid and edge_type = {sql_literal(et)}::edge_type @@ -379,9 +409,7 @@ select {sql_literal(f)}::uuid, {sql_literal(t)}::uuid, raise exception 'apply_proposal: claim_edge row does not match strict apply payload'; end if;""" - ledger = _ledger_and_verify( - proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval - ) + ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval) return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval)) @@ -392,6 +420,7 @@ def build_attach_evidence_sql( approval: dict[str, Any], ) -> str: _validate_approval_meta(approval, "attach_evidence", apply_payload) + _reject_unknown(apply_payload, {"evidence"}, "attach_evidence apply_payload") evidence: list[dict[str, Any]] = apply_payload.get("evidence") or [] if not evidence: raise ValueError("attach_evidence apply_payload requires non-empty 'evidence'") @@ -399,25 +428,33 @@ def build_attach_evidence_sql( statements = [] checks = [] for i, ev in enumerate(evidence): - claim_id = ev.get("claim_id") - source_id = ev.get("source_id") + _reject_unknown( + ev, + {"claim_id", "source_id", "role", "weight"}, + f"attach_evidence.evidence[{i}]", + ) + claim_id = _uuid(ev.get("claim_id"), f"attach_evidence.evidence[{i}].claim_id") + source_id = _uuid(ev.get("source_id"), f"attach_evidence.evidence[{i}].source_id") role = ev.get("role") or "grounds" - weight = ev.get("weight") - if not claim_id: - raise ValueError(f"evidence[{i}] requires 'claim_id'") - if not source_id: - raise ValueError( - f"evidence[{i}] requires an existing 'source_id'. " - "kb_apply cannot create public.sources; mint the source upstream first." - ) + if role not in EVIDENCE_ROLES: + raise ValueError(f"attach_evidence.evidence[{i}].role must be one of {sorted(EVIDENCE_ROLES)}") + weight = _weight(ev.get("weight"), f"attach_evidence.evidence[{i}].weight") + row_id = deterministic_row_uuid(proposal_id, "claim_evidence", claim_id, source_id, role) statements.append( - f"""insert into public.claim_evidence (claim_id, source_id, role, weight) -select {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid, + f"""insert into public.claim_evidence (id, claim_id, source_id, role, weight) +select {sql_literal(row_id)}::uuid, {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid, {sql_literal(role)}::evidence_role, {sql_literal(weight)} on conflict (claim_id, source_id, role) do nothing;""" ) checks.append( - f""" if exists (select 1 from public.claim_evidence + f""" -- Accept a legacy receipt id only when exactly one semantic row matches. + if (select count(*) from public.claim_evidence + where claim_id = {sql_literal(claim_id)}::uuid + and source_id = {sql_literal(source_id)}::uuid + and role = {sql_literal(role)}::evidence_role) <> 1 then + raise exception 'apply_proposal: evidence row % does not match strict apply payload', {i}; + end if; + if exists (select 1 from public.claim_evidence where claim_id = {sql_literal(claim_id)}::uuid and source_id = {sql_literal(source_id)}::uuid and role = {sql_literal(role)}::evidence_role @@ -434,9 +471,7 @@ on conflict (claim_id, source_id, role) do nothing;""" ) canonical = "\n".join(statements) - ledger = _ledger_and_verify( - proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval - ) + ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval) return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval)) @@ -509,12 +544,8 @@ def build_approve_claim_sql( "status": status, "confidence": _weight(row.get("confidence"), f"{path}.confidence"), "tags": tags, - "created_by": _uuid( - row.get("created_by", agent_id), f"{path}.created_by", nullable=True - ), - "superseded_by": _uuid( - row.get("superseded_by"), f"{path}.superseded_by", nullable=True - ), + "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True), + "superseded_by": _uuid(row.get("superseded_by"), f"{path}.superseded_by", nullable=True), } ) @@ -543,9 +574,7 @@ def build_approve_claim_sql( "storage_path": row.get("storage_path"), "excerpt": row.get("excerpt"), "hash": source_hash, - "created_by": _uuid( - row.get("created_by", agent_id), f"{path}.created_by", nullable=True - ), + "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True), } ) @@ -562,13 +591,18 @@ def build_approve_claim_sql( raise ValueError(f"{path}.role must be one of {sorted(EVIDENCE_ROLES)}") evidence.append( { + "id": deterministic_row_uuid( + proposal_id, + "claim_evidence", + _uuid(row.get("claim_id"), f"{path}.claim_id"), + _uuid(row.get("source_id"), f"{path}.source_id"), + role, + ), "claim_id": _uuid(row.get("claim_id"), f"{path}.claim_id"), "source_id": _uuid(row.get("source_id"), f"{path}.source_id"), "role": role, "weight": _weight(row.get("weight"), f"{path}.weight"), - "created_by": _uuid( - row.get("created_by", agent_id), f"{path}.created_by", nullable=True - ), + "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True), } ) @@ -589,13 +623,12 @@ def build_approve_claim_sql( raise ValueError(f"{path} cannot be a self-edge") edges.append( { + "id": deterministic_row_uuid(proposal_id, "claim_edge", from_claim, to_claim, edge_type), "from_claim": from_claim, "to_claim": to_claim, "edge_type": edge_type, "weight": _weight(row.get("weight"), f"{path}.weight"), - "created_by": _uuid( - row.get("created_by", agent_id), f"{path}.created_by", nullable=True - ), + "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True), } ) @@ -647,150 +680,156 @@ def build_approve_claim_sql( for row in sources: collision_checks.append( f""" if exists (select 1 from public.sources - where hash = {sql_literal(row['hash'])} - and id <> {sql_literal(row['id'])}::uuid) then - raise exception 'approve_claim: source hash collision for source %', {sql_literal(row['id'])}; + where hash = {sql_literal(row["hash"])} + and id <> {sql_literal(row["id"])}::uuid) then + raise exception 'approve_claim: source hash collision for source %', {sql_literal(row["id"])}; end if;""" ) - statements.append( - "do $source_conflicts$\nbegin\n" - + "\n".join(collision_checks) - + "\nend\n$source_conflicts$;" - ) + statements.append("do $source_conflicts$\nbegin\n" + "\n".join(collision_checks) + "\nend\n$source_conflicts$;") for row in claims: tags = _text_array(row["tags"]) statements.append( f"""insert into public.claims (id, type, text, status, confidence, tags, created_by, superseded_by) -select {sql_literal(row['id'])}::uuid, {sql_literal(row['type'])}, {sql_literal(row['text'])}, - {sql_literal(row['status'])}, {sql_literal(row['confidence'])}, {tags}, - {sql_literal(row['created_by'])}::uuid, {sql_literal(row['superseded_by'])}::uuid +select {sql_literal(row["id"])}::uuid, {sql_literal(row["type"])}, {sql_literal(row["text"])}, + {sql_literal(row["status"])}, {sql_literal(row["confidence"])}, {tags}, + {sql_literal(row["created_by"])}::uuid, {sql_literal(row["superseded_by"])}::uuid on conflict (id) do nothing;""" ) checks.append( f""" if not exists (select 1 from public.claims - where id = {sql_literal(row['id'])}::uuid - and type = {sql_literal(row['type'])} - and text = {sql_literal(row['text'])} - and status = {sql_literal(row['status'])} - and confidence is not distinct from {sql_literal(row['confidence'])} + where id = {sql_literal(row["id"])}::uuid + and type = {sql_literal(row["type"])} + and text = {sql_literal(row["text"])} + and status = {sql_literal(row["status"])} + and confidence is not distinct from {sql_literal(row["confidence"])} and tags is not distinct from {tags} - and created_by is not distinct from {sql_literal(row['created_by'])}::uuid - and superseded_by is not distinct from {sql_literal(row['superseded_by'])}::uuid) then - raise exception 'approve_claim: claim row does not match strict apply payload: %', {sql_literal(row['id'])}; + and created_by is not distinct from {sql_literal(row["created_by"])}::uuid + and superseded_by is not distinct from {sql_literal(row["superseded_by"])}::uuid) then + raise exception 'approve_claim: claim row does not match strict apply payload: %', {sql_literal(row["id"])}; end if;""" ) for row in sources: statements.append( f"""insert into public.sources (id, source_type, url, storage_path, excerpt, hash, created_by) -select {sql_literal(row['id'])}::uuid, {sql_literal(row['source_type'])}, {sql_literal(row['url'])}, - {sql_literal(row['storage_path'])}, {sql_literal(row['excerpt'])}, {sql_literal(row['hash'])}, - {sql_literal(row['created_by'])}::uuid +select {sql_literal(row["id"])}::uuid, {sql_literal(row["source_type"])}, {sql_literal(row["url"])}, + {sql_literal(row["storage_path"])}, {sql_literal(row["excerpt"])}, {sql_literal(row["hash"])}, + {sql_literal(row["created_by"])}::uuid on conflict do nothing;""" ) checks.append( f""" if exists (select 1 from public.sources - where hash = {sql_literal(row['hash'])} - and id <> {sql_literal(row['id'])}::uuid) then - raise exception 'approve_claim: source hash collision for source %', {sql_literal(row['id'])}; + where hash = {sql_literal(row["hash"])} + and id <> {sql_literal(row["id"])}::uuid) then + raise exception 'approve_claim: source hash collision for source %', {sql_literal(row["id"])}; end if; if not exists (select 1 from public.sources - where id = {sql_literal(row['id'])}::uuid - and source_type = {sql_literal(row['source_type'])} - and url is not distinct from {sql_literal(row['url'])} - and storage_path is not distinct from {sql_literal(row['storage_path'])} - and excerpt is not distinct from {sql_literal(row['excerpt'])} - and hash = {sql_literal(row['hash'])} - and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then - raise exception 'approve_claim: source row does not match strict apply payload: %', {sql_literal(row['id'])}; + where id = {sql_literal(row["id"])}::uuid + and source_type = {sql_literal(row["source_type"])} + and url is not distinct from {sql_literal(row["url"])} + and storage_path is not distinct from {sql_literal(row["storage_path"])} + and excerpt is not distinct from {sql_literal(row["excerpt"])} + and hash = {sql_literal(row["hash"])} + and created_by is not distinct from {sql_literal(row["created_by"])}::uuid) then + raise exception 'approve_claim: source row does not match strict apply payload: %', {sql_literal(row["id"])}; end if;""" ) for row in reasoning_tools: statements.append( f"""insert into public.reasoning_tools (id, agent_id, name, description, category) -select {sql_literal(row['id'])}::uuid, {sql_literal(row['agent_id'])}::uuid, - {sql_literal(row['name'])}, {sql_literal(row['description'])}, {sql_literal(row['category'])} +select {sql_literal(row["id"])}::uuid, {sql_literal(row["agent_id"])}::uuid, + {sql_literal(row["name"])}, {sql_literal(row["description"])}, {sql_literal(row["category"])} on conflict (id) do nothing;""" ) checks.append( f""" if not exists (select 1 from public.reasoning_tools - where id = {sql_literal(row['id'])}::uuid - and agent_id is not distinct from {sql_literal(row['agent_id'])}::uuid - and name = {sql_literal(row['name'])} - and description = {sql_literal(row['description'])} - and category is not distinct from {sql_literal(row['category'])}) then - raise exception 'approve_claim: reasoning tool row does not match strict apply payload: %', {sql_literal(row['id'])}; + where id = {sql_literal(row["id"])}::uuid + and agent_id is not distinct from {sql_literal(row["agent_id"])}::uuid + and name = {sql_literal(row["name"])} + and description = {sql_literal(row["description"])} + and category is not distinct from {sql_literal(row["category"])}) then + raise exception 'approve_claim: reasoning tool row does not match strict apply payload: %', {sql_literal(row["id"])}; end if;""" ) for row in evidence: statements.append( - f"""insert into public.claim_evidence (claim_id, source_id, role, weight, created_by) -select {sql_literal(row['claim_id'])}::uuid, {sql_literal(row['source_id'])}::uuid, - {sql_literal(row['role'])}::evidence_role, {sql_literal(row['weight'])}, - {sql_literal(row['created_by'])}::uuid + f"""insert into public.claim_evidence (id, claim_id, source_id, role, weight, created_by) +select {sql_literal(row["id"])}::uuid, {sql_literal(row["claim_id"])}::uuid, {sql_literal(row["source_id"])}::uuid, + {sql_literal(row["role"])}::evidence_role, {sql_literal(row["weight"])}, + {sql_literal(row["created_by"])}::uuid on conflict (claim_id, source_id, role) do nothing;""" ) checks.append( - f""" if exists (select 1 from public.claim_evidence - where claim_id = {sql_literal(row['claim_id'])}::uuid - and source_id = {sql_literal(row['source_id'])}::uuid - and role = {sql_literal(row['role'])}::evidence_role - and (weight is distinct from {sql_literal(row['weight'])} - or created_by is distinct from {sql_literal(row['created_by'])}::uuid)) then + f""" -- Accept a legacy receipt id only when exactly one semantic row matches. + if (select count(*) from public.claim_evidence + where claim_id = {sql_literal(row["claim_id"])}::uuid + and source_id = {sql_literal(row["source_id"])}::uuid + and role = {sql_literal(row["role"])}::evidence_role) <> 1 then + raise exception 'approve_claim: evidence row does not match strict apply payload'; + end if; + if exists (select 1 from public.claim_evidence + where claim_id = {sql_literal(row["claim_id"])}::uuid + and source_id = {sql_literal(row["source_id"])}::uuid + and role = {sql_literal(row["role"])}::evidence_role + and (weight is distinct from {sql_literal(row["weight"])} + or created_by is distinct from {sql_literal(row["created_by"])}::uuid)) then raise exception 'approve_claim: evidence row does not match strict apply payload'; end if; if not exists (select 1 from public.claim_evidence - where claim_id = {sql_literal(row['claim_id'])}::uuid - and source_id = {sql_literal(row['source_id'])}::uuid - and role = {sql_literal(row['role'])}::evidence_role - and weight is not distinct from {sql_literal(row['weight'])} - and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then + where claim_id = {sql_literal(row["claim_id"])}::uuid + and source_id = {sql_literal(row["source_id"])}::uuid + and role = {sql_literal(row["role"])}::evidence_role + and weight is not distinct from {sql_literal(row["weight"])} + and created_by is not distinct from {sql_literal(row["created_by"])}::uuid) then raise exception 'approve_claim: evidence row does not match strict apply payload'; end if;""" ) for row in edges: - edge_lock_key = ( - f"claim_edge:{row['from_claim']}:{row['to_claim']}:{row['edge_type']}" - ) + edge_lock_key = f"claim_edge:{row['from_claim']}:{row['to_claim']}:{row['edge_type']}" statements.append( f"""select pg_advisory_xact_lock(hashtextextended({sql_literal(edge_lock_key)}, 0)); -insert into public.claim_edges (from_claim, to_claim, edge_type, weight, created_by) -select {sql_literal(row['from_claim'])}::uuid, {sql_literal(row['to_claim'])}::uuid, - {sql_literal(row['edge_type'])}::edge_type, {sql_literal(row['weight'])}, - {sql_literal(row['created_by'])}::uuid +insert into public.claim_edges (id, from_claim, to_claim, edge_type, weight, created_by) +select {sql_literal(row["id"])}::uuid, {sql_literal(row["from_claim"])}::uuid, {sql_literal(row["to_claim"])}::uuid, + {sql_literal(row["edge_type"])}::edge_type, {sql_literal(row["weight"])}, + {sql_literal(row["created_by"])}::uuid where not exists ( select 1 from public.claim_edges - where from_claim = {sql_literal(row['from_claim'])}::uuid - and to_claim = {sql_literal(row['to_claim'])}::uuid - and edge_type = {sql_literal(row['edge_type'])}::edge_type);""" + where from_claim = {sql_literal(row["from_claim"])}::uuid + and to_claim = {sql_literal(row["to_claim"])}::uuid + and edge_type = {sql_literal(row["edge_type"])}::edge_type);""" ) checks.append( - f""" if exists (select 1 from public.claim_edges - where from_claim = {sql_literal(row['from_claim'])}::uuid - and to_claim = {sql_literal(row['to_claim'])}::uuid - and edge_type = {sql_literal(row['edge_type'])}::edge_type - and (weight is distinct from {sql_literal(row['weight'])} - or created_by is distinct from {sql_literal(row['created_by'])}::uuid)) then + f""" -- Accept a legacy receipt id only when exactly one semantic row matches. + if (select count(*) from public.claim_edges + where from_claim = {sql_literal(row["from_claim"])}::uuid + and to_claim = {sql_literal(row["to_claim"])}::uuid + and edge_type = {sql_literal(row["edge_type"])}::edge_type) <> 1 then + raise exception 'approve_claim: edge row does not match strict apply payload'; + end if; + if exists (select 1 from public.claim_edges + where from_claim = {sql_literal(row["from_claim"])}::uuid + and to_claim = {sql_literal(row["to_claim"])}::uuid + and edge_type = {sql_literal(row["edge_type"])}::edge_type + and (weight is distinct from {sql_literal(row["weight"])} + or created_by is distinct from {sql_literal(row["created_by"])}::uuid)) then raise exception 'approve_claim: edge row does not match strict apply payload'; end if; if not exists (select 1 from public.claim_edges - where from_claim = {sql_literal(row['from_claim'])}::uuid - and to_claim = {sql_literal(row['to_claim'])}::uuid - and edge_type = {sql_literal(row['edge_type'])}::edge_type - and weight is not distinct from {sql_literal(row['weight'])} - and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then + where from_claim = {sql_literal(row["from_claim"])}::uuid + and to_claim = {sql_literal(row["to_claim"])}::uuid + and edge_type = {sql_literal(row["edge_type"])}::edge_type + and weight is not distinct from {sql_literal(row["weight"])} + and created_by is not distinct from {sql_literal(row["created_by"])}::uuid) then raise exception 'approve_claim: edge row does not match strict apply payload'; end if;""" ) canonical = "\n\n".join(statements) - ledger = _ledger_and_verify( - proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval - ) + ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval) return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval)) @@ -837,9 +876,7 @@ def assert_applyable(proposal: dict[str, Any]) -> None: if status == "applied": raise SystemExit(f"proposal {proposal['id']} is already applied (idempotent no-op)") if status != "approved": - raise SystemExit( - f"proposal {proposal['id']} has status {status!r}; only 'approved' proposals apply" - ) + raise SystemExit(f"proposal {proposal['id']} has status {status!r}; only 'approved' proposals apply") def assert_receiptable(proposal: dict[str, Any]) -> None: @@ -877,23 +914,36 @@ def run_psql( ) -> str: docker_binary = shutil.which("docker") or "docker" command = [ - docker_binary, "exec", "-e", "PGPASSWORD", "-i", args.container, - "psql", "-U", args.role, "-h", args.host, "-d", args.db, - "-v", "ON_ERROR_STOP=1", "-At", "-q", + docker_binary, + "exec", + "-e", + "PGPASSWORD", + "-i", + args.container, + "psql", + "-U", + args.role, + "-h", + args.host, + "-d", + args.db, + "-v", + "ON_ERROR_STOP=1", + "-At", + "-q", ] result = subprocess.run( - command, input=sql, text=True, capture_output=True, + command, + input=sql, + text=True, + capture_output=True, env={"PGPASSWORD": password, "PATH": "/usr/bin:/bin:/usr/local/bin"}, check=False, ) if result.returncode != 0: if redact_output_on_error: - raise SystemExit( - f"psql failed ({result.returncode}); private postflight output redacted" - ) - raise SystemExit( - f"psql failed ({result.returncode})\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}" - ) + raise SystemExit(f"psql failed ({result.returncode}); private postflight output redacted") + raise SystemExit(f"psql failed ({result.returncode})\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}") return result.stdout @@ -980,8 +1030,7 @@ def parse_args(argv: list[str]) -> argparse.Namespace: p.add_argument( "--receipt-dir", default=None, - help="private receipt directory (default: KB_APPLY_RECEIPT_DIR or " - f"{replay_receipt.DEFAULT_RECEIPT_DIR})", + help=f"private receipt directory (default: KB_APPLY_RECEIPT_DIR or {replay_receipt.DEFAULT_RECEIPT_DIR})", ) p.add_argument( "--receipt-out", diff --git a/scripts/apply_worker.py b/scripts/apply_worker.py index 2abefc7..6d3dc13 100644 --- a/scripts/apply_worker.py +++ b/scripts/apply_worker.py @@ -35,6 +35,7 @@ from __future__ import annotations import argparse import json import os +import stat import subprocess import sys from pathlib import Path @@ -53,6 +54,13 @@ WORKER_TYPES = ap.APPLYABLE_TYPES # bundles and evidence/edge applies do not trigger a generic identity render. RENDER_TYPES = ("revise_strategy",) +POSTCOMMIT_RECEIPT_FAILURE_MARKER = "committed, but private replay receipt capture failed" +POSTCOMMIT_RECEIPT_RECOVERY_MARKER = ". Recover without reapplying via: " + + +class PostCommitReceiptError(RuntimeError): + """The proposal committed, but its private row-level receipt is unavailable.""" + # --------------------------------------------------------------------------- # # Pure helpers (unit-tested without a DB) # @@ -160,14 +168,69 @@ def partition_candidates( return {"poisoned": poisoned, "to_apply": eligible[: max(0, max_per_tick)]} +def has_exact_postcommit_receipt_failure(stderr: str | None, proposal_id: str) -> bool: + """Recognize only the proposal-bound post-COMMIT message from apply_proposal. + + The old marker can occur inside payload-validation tracebacks (for example, + as an attacker-controlled unknown field name). Requiring the complete + engine message shape prevents those pre-COMMIT failures from bypassing the + normal failure and poison-pill accounting. + """ + prefix = f"proposal {proposal_id} {POSTCOMMIT_RECEIPT_FAILURE_MARKER}: " + recovery_suffix = f" {proposal_id} --receipt-only" + for line in (stderr or "").splitlines(): + candidate = line.rstrip("\r") + if ( + candidate.startswith(prefix) + and POSTCOMMIT_RECEIPT_RECOVERY_MARKER in candidate[len(prefix) :] + and candidate.endswith(recovery_suffix) + ): + return True + return False + + +def receipt_path_for_proposal(args: argparse.Namespace, proposal_id: str) -> Path: + """Return the explicit, deterministic private receipt path for one proposal.""" + receipt_dir = ( + getattr(args, "receipt_dir", None) + or os.environ.get("KB_APPLY_WORKER_RECEIPT_DIR") + or os.environ.get("KB_APPLY_RECEIPT_DIR") + or ap.replay_receipt.DEFAULT_RECEIPT_DIR + ) + return Path(receipt_dir).expanduser().resolve() / f"{proposal_id}.json" + + +def assert_private_replay_receipt(path: Path, proposal_id: str) -> None: + """Verify the worker can rely on the exact private row-level receipt.""" + try: + path_stat = path.lstat() + except OSError as exc: + raise RuntimeError("private replay receipt was not written") from exc + if not stat.S_ISREG(path_stat.st_mode) or path.is_symlink(): + raise RuntimeError("private replay receipt is not a regular file") + if stat.S_IMODE(path_stat.st_mode) & 0o077: + raise RuntimeError("private replay receipt permissions are broader than 0600") + try: + receipt = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as exc: + raise RuntimeError("private replay receipt is unreadable or invalid") from exc + if not isinstance(receipt, dict): + raise RuntimeError("private replay receipt is not a JSON object") + try: + ap.replay_receipt.validate_replay_receipt( + receipt, + expected_proposal_id=str(proposal_id), + ) + except ValueError as exc: + raise RuntimeError("private replay receipt row-level contract is invalid") from exc + + # --------------------------------------------------------------------------- # # Side-effecting steps # # --------------------------------------------------------------------------- # def _psql_args(args: argparse.Namespace) -> argparse.Namespace: """Namespace shaped for ap.run_psql (reuses the kb_apply connection path).""" - return argparse.Namespace( - container=args.container, db=args.db, host=args.host, role=args.role - ) + return argparse.Namespace(container=args.container, db=args.db, host=args.host, role=args.role) def fetch_candidates( @@ -181,20 +244,73 @@ def fetch_candidates( def apply_one(args: argparse.Namespace, proposal_id: str) -> None: - """Apply via the audited apply_proposal.py CLI -- same txn + rowcount guard.""" + """Apply once and retain or safely recover the exact private replay receipt.""" + receipt_path = receipt_path_for_proposal(args, proposal_id) cmd = [ - sys.executable, str(args.apply_script), proposal_id, - "--applied-by", args.applied_by, - "--secrets-file", args.secrets_file, - "--container", args.container, "--db", args.db, - "--host", args.host, "--role", args.role, + sys.executable, + str(args.apply_script), + proposal_id, + "--applied-by", + args.applied_by, + "--secrets-file", + args.secrets_file, + "--container", + args.container, + "--db", + args.db, + "--host", + args.host, + "--role", + args.role, + "--receipt-dir", + str(receipt_path.parent), + "--receipt-out", + str(receipt_path), ] result = subprocess.run(cmd, text=True, capture_output=True, check=False) - if result.returncode != 0: + committed = result.returncode == 0 or has_exact_postcommit_receipt_failure( + result.stderr, + proposal_id, + ) + if not committed: raise RuntimeError( - f"apply failed for {proposal_id}: {result.stdout.strip()} {result.stderr.strip()}" + f"apply failed for {proposal_id}: {(result.stdout or '').strip()} {(result.stderr or '').strip()}" ) + if result.returncode == 0: + try: + assert_private_replay_receipt(receipt_path, proposal_id) + return + except RuntimeError: + # The engine returned only after COMMIT. A missing/invalid receipt is + # recoverable without replaying the apply transaction. + pass + + try: + recovery = subprocess.run( + [*cmd, "--receipt-only"], + text=True, + capture_output=True, + check=False, + ) + except OSError as exc: + raise PostCommitReceiptError( + f"proposal {proposal_id} committed, but the read-only receipt recovery " + "command could not start; do not retry the apply transaction" + ) from exc + if recovery.returncode != 0: + raise PostCommitReceiptError( + f"proposal {proposal_id} committed, but read-only receipt recovery " + f"failed (exit {recovery.returncode}); do not retry the apply transaction" + ) + try: + assert_private_replay_receipt(receipt_path, proposal_id) + except RuntimeError as exc: + raise PostCommitReceiptError( + f"proposal {proposal_id} committed, but receipt recovery did not produce " + "a valid private row-level receipt; do not retry the apply transaction" + ) from exc + def render_one(args: argparse.Namespace, agent_id: str | None) -> str: cmd = build_render_command(args.render_cmd, agent_id) @@ -202,9 +318,7 @@ def render_one(args: argparse.Namespace, agent_id: str | None) -> str: return "render skipped (no render-cmd configured; PR2 renderer not deployed)" result = subprocess.run(cmd, text=True, capture_output=True, check=False) if result.returncode != 0: - raise RuntimeError( - f"render failed for agent {agent_id}: {result.stdout.strip()} {result.stderr.strip()}" - ) + raise RuntimeError(f"render failed for agent {agent_id}: {result.stdout.strip()} {result.stderr.strip()}") return f"rendered agent {agent_id}" @@ -214,11 +328,7 @@ def render_one(args: argparse.Namespace, agent_id: str | None) -> str: def run(args: argparse.Namespace) -> int: password = ap.load_password(args.secrets_file) failure_counts = load_failure_state(args.failure_state_file) - exhausted_ids = tuple( - proposal_id - for proposal_id, count in failure_counts.items() - if count >= args.max_attempts - ) + exhausted_ids = tuple(proposal_id for proposal_id, count in failure_counts.items() if count >= args.max_attempts) candidates = fetch_candidates(args, password, exhausted_ids) for proposal_id in exhausted_ids: @@ -263,6 +373,15 @@ def run(args: argparse.Namespace) -> int: print(f"applied {pid} ({ptype})") if ptype in RENDER_TYPES: print(" " + render_one(args, agent_id)) + except PostCommitReceiptError as exc: + failures += 1 + # The canonical transaction already committed. Do not classify this + # as an apply failure or poison/retry the proposal; receipt-only is + # the sole safe recovery path. + print( + f"POST-COMMIT RECEIPT ERROR for {pid} ({ptype}): {exc}", + file=sys.stderr, + ) except Exception as exc: failures += 1 # Leave the proposal at 'approved' so a fixed one reapplies next tick @@ -270,48 +389,65 @@ def run(args: argparse.Namespace) -> int: # so a deterministically-failing proposal hits the ceiling instead of # retrying forever. Surface loudly for the operator. failure_counts[pid] = failure_counts.get(pid, 0) + 1 - print(f"ERROR applying {pid} ({ptype}) [attempt {failure_counts[pid]}/" - f"{args.max_attempts}]: {exc}", file=sys.stderr) + print( + f"ERROR applying {pid} ({ptype}) [attempt {failure_counts[pid]}/{args.max_attempts}]: {exc}", + file=sys.stderr, + ) save_failure_state(args.failure_state_file, failure_counts) return 1 if failures else 0 def parse_args(argv: list[str]) -> argparse.Namespace: - p = argparse.ArgumentParser( - description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter - ) + p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) p.add_argument( - "--enable", action="store_true", + "--enable", + action="store_true", help="actually apply (default: report-only). Also honored via KB_APPLY_WORKER_ENABLED=1.", ) p.add_argument("--limit", type=int, default=20, help="max candidates fetched per tick") p.add_argument( - "--max-per-tick", type=int, default=1, + "--max-per-tick", + type=int, + default=1, help="max proposals actually APPLIED per tick (default 1: applies land " "one-at-a-time and observably, not a whole-queue drain)", ) p.add_argument( - "--max-attempts", type=int, default=3, + "--max-attempts", + type=int, + default=3, help="consecutive apply failures before a proposal is treated as a " "poison pill and skipped (needs a human fix, not endless retries)", ) p.add_argument( "--failure-state-file", default=os.environ.get("KB_APPLY_WORKER_STATE", "/opt/teleo-eval/logs/kb-apply-worker-failures.json"), - help="persisted per-proposal failure counts (survives oneshot ticks so " - "the poison-pill ceiling actually bites)", + help="persisted per-proposal failure counts (survives oneshot ticks so the poison-pill ceiling actually bites)", ) p.add_argument( - "--applied-by", default=ap.SERVICE_AGENT_HANDLE, + "--applied-by", + default=ap.SERVICE_AGENT_HANDLE, help="handle recorded as applied_by (default: the kb-apply service agent)", ) p.add_argument( - "--apply-script", default=str(HERE / "apply_proposal.py"), + "--apply-script", + default=str(HERE / "apply_proposal.py"), help="path to the apply_proposal.py engine (the sole apply path)", ) p.add_argument( - "--render-cmd", default=os.environ.get("KB_APPLY_RENDER_CMD", ""), + "--receipt-dir", + default=( + os.environ.get("KB_APPLY_WORKER_RECEIPT_DIR") + or os.environ.get("KB_APPLY_RECEIPT_DIR") + or ap.replay_receipt.DEFAULT_RECEIPT_DIR + ), + help="private replay receipt directory; each apply writes the deterministic " + ".json path and verifies 0600 permissions", + ) + p.add_argument( + "--render-cmd", + default=os.environ.get("KB_APPLY_RENDER_CMD", ""), help="render hook template, e.g. 'python3 render_soul.py --agent-id {agent_id}'. " "Empty (default) skips render until the SOUL renderer is deployed.", ) diff --git a/scripts/finalize_approve_claim_isolated_canary.py b/scripts/finalize_approve_claim_isolated_canary.py new file mode 100644 index 0000000..059ca97 --- /dev/null +++ b/scripts/finalize_approve_claim_isolated_canary.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +"""Finalize outer isolation and cleanup evidence for the clone canary.""" + +from __future__ import annotations + +import hashlib +import json +import os +import sys +from collections.abc import Mapping +from pathlib import Path +from typing import Any + + +def _service(raw: str) -> dict[str, str]: + return dict(line.split("=", 1) for line in raw.splitlines() if "=" in line) + + +def _table_deltas(before: dict[str, int], after: dict[str, int]) -> dict[str, int]: + if set(before) != set(after): + raise ValueError( + f"live source count keys changed during the canary: before={sorted(before)} after={sorted(after)}" + ) + return {key: after[key] - before[key] for key in sorted(before)} + + +def _verify_source_binding(root: Path, records: list[dict[str, object]]) -> dict[str, object]: + readbacks = [] + for record in records: + relative_text = str(record.get("repo_relative_path", "")) + relative = Path(relative_text) + if not relative_text or relative.is_absolute() or ".." in relative.parts: + raise ValueError(f"unsafe repo-relative source path: {relative_text!r}") + candidate = (root / relative).resolve() + try: + candidate.relative_to(root) + except ValueError as exc: + raise ValueError(f"source path escaped repository root: {relative_text}") from exc + if not candidate.is_file(): + readbacks.append( + { + "repo_relative_path": relative.as_posix(), + "expected_sha256": record.get("sha256"), + "actual_sha256": None, + "matches": False, + } + ) + continue + content = candidate.read_bytes() + actual_sha256 = hashlib.sha256(content).hexdigest() + readbacks.append( + { + "repo_relative_path": relative.as_posix(), + "expected_sha256": record.get("sha256"), + "actual_sha256": actual_sha256, + "size_bytes": len(content), + "matches": (actual_sha256 == record.get("sha256") and len(content) == record.get("size_bytes")), + } + ) + return { + "files": readbacks, + "all_match": bool(readbacks) and all(bool(row["matches"]) for row in readbacks), + } + + +def _contains_ephemeral_path(value: object) -> bool: + if isinstance(value, str): + return "/tmp/" in value + if isinstance(value, dict): + return any(_contains_ephemeral_path(item) for item in value.values()) + if isinstance(value, list): + return any(_contains_ephemeral_path(item) for item in value) + return False + + +def finalize(path: Path, env: Mapping[str, str]) -> dict[str, Any]: + if not path.is_file(): + raise ValueError("inner canary did not produce a report") + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError("inner canary report must be a JSON object") + + before_counts = json.loads(env["SOURCE_COUNTS_BEFORE"]) + after_counts = json.loads(env["SOURCE_COUNTS_AFTER"]) + live_table_deltas = _table_deltas(before_counts, after_counts) + before_service = _service(env["SERVICE_BEFORE"]) + after_service = _service(env["SERVICE_AFTER"]) + source_tier = env["SOURCE_TIER"] + source_network_mode = env["SOURCE_NETWORK_MODE"] + source_canary_label = env["SOURCE_CANARY_LABEL"] + container_network_mode = env["CANARY_NETWORK_MODE"] + container_mounts = json.loads(env["CANARY_MOUNTS_JSON"]) + container_canary_label = env["CANARY_LABEL"] + container_instance_label = env["CANARY_INSTANCE_LABEL"] + container_volume_mounts = [mount for mount in container_mounts if mount.get("Type") == "volume"] + container_isolated = container_network_mode == "none" and not container_volume_mounts + container_labeled = container_canary_label == "proposal-apply-lifecycle" and container_instance_label.startswith( + "working-leo-approve-claim-" + ) + source_tier_enforced = source_tier != "isolated-local" or ( + source_network_mode == "none" and source_canary_label == "working-leo-approved-source" + ) + service_observable = before_service.get("Available") == "true" and after_service.get("Available") == "true" + service_stable = ( + all( + before_service.get(key) == after_service.get(key) + for key in ("ActiveState", "SubState", "MainPID", "NRestarts") + ) + if service_observable + else None + ) + service_gate_passes = service_stable is True if source_tier == "live-readonly" else service_stable is not False + container_absent = int(env["CONTAINER_NAME_READBACK_RC"]) == 0 and not env["CONTAINER_NAME_READBACK"].strip() + label_scoped_orphan_count = int(env["CONTAINER_LABEL_ORPHAN_COUNT"]) + label_scoped_container_absent = ( + int(env["CONTAINER_LABEL_READBACK_RC"]) == 0 + and label_scoped_orphan_count == 0 + and not env["CONTAINER_LABEL_READBACK"].strip() + ) + workdir_absent = env["OUTER_WORKDIR_LEXISTS"] == "false" + source_binding = _verify_source_binding( + Path(env["REPO_ROOT"]).resolve(), + data.get("source_binding", {}).get("files", []), + ) + data["source_binding"]["independent_post_cleanup_verification"] = source_binding + source_binding_ok = ( + data["source_binding"].get("unchanged_during_run") is True and source_binding["all_match"] is True + ) + stale_ephemeral_paths_absent = not _contains_ephemeral_path(data) + inner_runtime_pass = data.get("status") == "pass" and int(env["CANARY_RC"]) == 0 + outer_ok = ( + before_counts == after_counts + and all(delta == 0 for delta in live_table_deltas.values()) + and service_gate_passes + and container_absent + and label_scoped_container_absent + and workdir_absent + and source_binding_ok + and stale_ephemeral_paths_absent + and container_isolated + and container_labeled + and source_tier_enforced + ) + if source_tier == "isolated-local": + data["required_tier"] = "T2_runtime" + data["required_tiers"] = ["T2_runtime"] + data["runtime_scope"] = "isolated_postgres_container_from_readonly_local_fixture" + else: + data["required_tier"] = "T3_live_readonly" + data["required_tiers"] = ["T2_runtime", "T3_live_readonly"] + data["runtime_scope"] = "isolated_postgres_container_from_readonly_live_schema" + data["outer_isolation"] = { + "source_container": env.get("SOURCE_CONTAINER", "teleo-pg"), + "source_database": env.get("SOURCE_DB", "teleo"), + "source_counts_before": before_counts, + "source_counts_after": after_counts, + "canonical_table_deltas": live_table_deltas, + "source_counts_unchanged": before_counts == after_counts, + "service_before": before_service, + "service_after": after_service, + "service_required": source_tier == "live-readonly", + "service_observable": service_observable, + "service_stable": service_stable, + "service_gate_passes": service_gate_passes, + "source_boundary": { + "source_tier": source_tier, + "network_mode": source_network_mode, + "canary_label": source_canary_label, + "tier_enforced": source_tier_enforced, + }, + "container_isolation": { + "network_mode": container_network_mode, + "volume_mounts": container_volume_mounts, + "canary_label": container_canary_label, + "instance_label": container_instance_label, + "lifecycle_labeled": container_labeled, + "network_disabled": container_network_mode == "none", + "no_docker_volumes": not container_volume_mounts, + }, + "cleanup_readback": { + "container_remove_returncode": int(env["OUTER_CONTAINER_REMOVE_RC"]), + "container_name_query_returncode": int(env["CONTAINER_NAME_READBACK_RC"]), + "container_name_query_stdout": env["CONTAINER_NAME_READBACK"], + "temporary_container_absent": container_absent, + "label_scoped_query_returncode": int(env["CONTAINER_LABEL_READBACK_RC"]), + "label_scoped_query_stdout": env["CONTAINER_LABEL_READBACK"], + "label_scoped_orphan_count": label_scoped_orphan_count, + "label_scoped_temporary_container_absent": label_scoped_container_absent, + "workdir_remove_returncode": int(env["OUTER_WORKDIR_REMOVE_RC"]), + "workdir_lexists_after_cleanup": not workdir_absent, + "temporary_workdir_absent": workdir_absent, + }, + } + checks = data["checks"] + checks["outer_live_counts_exactly_unchanged"] = before_counts == after_counts + checks["outer_live_table_deltas_exactly_zero"] = all(delta == 0 for delta in live_table_deltas.values()) + checks["outer_service_observed_if_required"] = source_tier != "live-readonly" or service_observable + checks["outer_service_stable_if_observed"] = service_gate_passes + checks["outer_container_absent_independent_readback"] = container_absent + checks["outer_labeled_container_absent_independent_readback"] = label_scoped_container_absent + checks["outer_workdir_absent_independent_readback"] = workdir_absent + checks["source_binding_independently_verified"] = source_binding_ok + checks["stale_ephemeral_paths_absent"] = stale_ephemeral_paths_absent + checks["outer_source_tier_enforced"] = source_tier_enforced + checks["outer_container_network_disabled"] = container_network_mode == "none" + checks["outer_container_lifecycle_labeled"] = container_labeled + checks["outer_container_has_no_docker_volumes"] = not container_volume_mounts + checks["outer_isolation_complete"] = outer_ok + if outer_ok and inner_runtime_pass: + data["current_tier"] = "T2_runtime" if source_tier == "isolated-local" else "T3_live_readonly" + else: + data["status"] = "fail" + data["current_tier"] = "T2_runtime" if inner_runtime_pass else "T1_model" + path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8") + return data + + +def main(argv: list[str] | None = None) -> int: + arguments = sys.argv[1:] if argv is None else argv + if len(arguments) != 1: + raise SystemExit("usage: finalize_approve_claim_isolated_canary.py REPORT.json") + try: + data = finalize(Path(arguments[0]), os.environ) + except (KeyError, OSError, ValueError, json.JSONDecodeError) as exc: + raise SystemExit(str(exc)) from exc + return 0 if data["status"] == "pass" else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/kb_apply_replay_receipt.py b/scripts/kb_apply_replay_receipt.py index 83678a9..2e89345 100644 --- a/scripts/kb_apply_replay_receipt.py +++ b/scripts/kb_apply_replay_receipt.py @@ -446,6 +446,41 @@ def build_replay_receipt( } +def validate_replay_receipt( + receipt: dict[str, Any], + *, + expected_proposal_id: str | None = None, +) -> dict[str, Any]: + """Rebuild and require the exact private replay-receipt contract. + + Canonical JSON comparison is deliberate: Python equality treats booleans + and integers as interchangeable, which is unsafe for authorization and + receipt fields. + """ + if not isinstance(receipt, dict): + raise ValueError("replay receipt must be an object") + proposal = receipt.get("proposal") + rows = receipt.get("canonical_rows") + apply_engine = receipt.get("apply_engine") + if not isinstance(proposal, dict) or not isinstance(rows, dict) or not isinstance(apply_engine, dict): + raise ValueError("replay receipt is missing proposal, canonical rows, or apply-engine metadata") + if expected_proposal_id is not None and proposal.get("id") != expected_proposal_id: + raise ValueError("replay receipt proposal id does not match") + try: + rebuilt = build_replay_receipt( + proposal, + rows, + apply_sql_sha256=apply_engine.get("apply_sql_sha256"), + apply_sql_source=apply_engine.get("source"), + exported_at_utc=receipt.get("exported_at_utc"), + ) + except (KeyError, TypeError, ValueError) as exc: + raise ValueError("replay receipt failed full contract validation") from exc + if _canonical_json(receipt) != _canonical_json(rebuilt): + raise ValueError("replay receipt hashes, counts, rows, or contract fields are internally inconsistent") + return rebuilt + + def resolve_receipt_path( proposal_id: str, *, diff --git a/scripts/proposal_apply_lifecycle.py b/scripts/proposal_apply_lifecycle.py new file mode 100644 index 0000000..9ddb600 --- /dev/null +++ b/scripts/proposal_apply_lifecycle.py @@ -0,0 +1,1513 @@ +#!/usr/bin/env python3 +"""Build and verify exact apply/rollback lifecycle evidence for one proposal. + +The module deliberately supports compensating rollback only for a fresh-owned +``approve_claim`` bundle: every payload-owned row must have been absent before +apply. It is used by the disposable-clone canary and by the production +authorization packet builder. It never connects to a database by itself. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import subprocess +import sys +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +import apply_proposal as ap # noqa: E402 +import kb_apply_replay_receipt as replay_receipt # noqa: E402 + +ROLLBACK_SCHEMA = "livingip.proposalApplyRollback.v1" +LIFECYCLE_SCHEMA = "livingip.proposalApplyLifecycleReceipt.v1" +AUTHORIZATION_SCHEMA = "livingip.proposalApplyAuthorizationPacket.v1" +FRESH_PREFLIGHT_SCHEMA = "livingip.proposalApplyFreshPreflight.v1" +PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA = "livingip.proposalApplyProductionRollbackArtifact.v1" + +RUNTIME_DEPENDENCIES = ( + "scripts/proposal_apply_lifecycle.py", + "scripts/apply_proposal.py", + "scripts/kb_apply_replay_receipt.py", + "scripts/kb_apply_prereqs.sql", +) + +APPROVAL_GATE_CHECKS = ( + "immutable_approval_table_present", + "approve_function_present", + "assert_function_present", + "finish_function_present", + "review_role_present", + "apply_role_present", +) + +ROW_TABLES = { + "claims": "public.claims", + "sources": "public.sources", + "claim_evidence": "public.claim_evidence", + "claim_edges": "public.claim_edges", + "reasoning_tools": "public.reasoning_tools", +} +DELETE_ORDER = ( + "claim_evidence", + "claim_edges", + "reasoning_tools", + "sources", + "claims", +) + + +def canonical_json(value: Any) -> str: + return json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True) + + +def sha256_json(value: Any) -> str: + return hashlib.sha256(canonical_json(value).encode("utf-8")).hexdigest() + + +def sha256_text(value: str) -> str: + return hashlib.sha256(value.encode("utf-8")).hexdigest() + + +def sha256_file(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as handle: + for chunk in iter(lambda: handle.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def is_sha256(value: Any) -> bool: + return isinstance(value, str) and len(value) == 64 and all(character in "0123456789abcdef" for character in value) + + +def repo_relative_path(path: Path) -> str: + try: + return path.resolve().relative_to(HERE.parent.resolve()).as_posix() + except ValueError as exc: + raise ValueError(f"authorization dependency must be inside the repository: {path}") from exc + + +def _require_approved_bundle(proposal: dict[str, Any]) -> dict[str, Any]: + if proposal.get("proposal_type") != "approve_claim": + raise ValueError("compensating rollback supports only approve_claim") + if proposal.get("status") != "approved": + raise ValueError("pre-apply proposal must be approved") + if any(proposal.get(field) is not None for field in ("applied_by_handle", "applied_by_agent_id", "applied_at")): + raise ValueError("approved pre-apply proposal must have blank applied fields") + payload = proposal.get("payload") + apply_payload = payload.get("apply_payload") if isinstance(payload, dict) else None + if not isinstance(apply_payload, dict): + raise ValueError("approved proposal requires payload.apply_payload") + # Reuse the audited builder as the strict contract validator. + ap.build_apply_sql(proposal, ap.SERVICE_AGENT_HANDLE) + return apply_payload + + +def build_fresh_preflight( + proposal: dict[str, Any], + target_rows_before: dict[str, list[dict[str, Any]]], + *, + captured_at_utc: str | None = None, +) -> dict[str, Any]: + """Bind an approved bundle to proof that all payload-owned rows are absent.""" + captured = captured_at_utc or datetime.now(timezone.utc).isoformat() + if _parse_utc(captured) is None: + raise ValueError("fresh preflight captured_at_utc must be a timezone-aware timestamp") + apply_payload = _require_approved_bundle(proposal) + if set(target_rows_before) != set(ROW_TABLES): + raise ValueError("fresh preflight must contain every approve_claim target table") + malformed = [name for name, rows in target_rows_before.items() if not isinstance(rows, list)] + if malformed: + raise ValueError(f"fresh preflight target rows must be lists: {malformed}") + nonempty = {name: len(rows) for name, rows in target_rows_before.items() if rows} + if nonempty: + raise ValueError(f"fresh-owned rollback requires absent target rows: {nonempty}") + envelope = { + "proposal_id": str(proposal.get("id")), + "proposal_type": proposal.get("proposal_type"), + "proposal_payload_sha256": sha256_json(proposal.get("payload")), + "apply_payload_sha256": sha256_json(apply_payload), + "target_rows_before": target_rows_before, + } + artifact_envelope = { + "captured_at_utc": captured, + **envelope, + "fresh_owned_targets": True, + } + return { + "artifact": "proposal_apply_fresh_preflight", + "schema": FRESH_PREFLIGHT_SCHEMA, + **artifact_envelope, + "preflight_sha256": sha256_json(envelope), + "preflight_artifact_sha256": sha256_json(artifact_envelope), + } + + +def _require_fresh_preflight(proposal_before: dict[str, Any], preflight: dict[str, Any]) -> None: + apply_payload = _require_approved_bundle(proposal_before) + if not isinstance(preflight, dict): + raise ValueError("fresh preflight must be an object") + expected_keys = { + "artifact", + "schema", + "captured_at_utc", + "proposal_id", + "proposal_type", + "proposal_payload_sha256", + "apply_payload_sha256", + "target_rows_before", + "fresh_owned_targets", + "preflight_sha256", + "preflight_artifact_sha256", + } + if set(preflight) != expected_keys: + raise ValueError("fresh preflight contract fields are incomplete or unexpected") + if ( + preflight.get("artifact") != "proposal_apply_fresh_preflight" + or preflight.get("schema") != FRESH_PREFLIGHT_SCHEMA + or preflight.get("fresh_owned_targets") is not True + ): + raise ValueError("rollback requires an exact fresh-owned preflight contract") + target_rows = preflight.get("target_rows_before") + if ( + not isinstance(target_rows, dict) + or set(target_rows) != set(ROW_TABLES) + or any(not isinstance(rows, list) or rows for rows in target_rows.values()) + ): + raise ValueError("fresh preflight must prove every payload-owned target row was absent") + envelope = { + "proposal_id": str(proposal_before.get("id")), + "proposal_type": proposal_before.get("proposal_type"), + "proposal_payload_sha256": sha256_json(proposal_before.get("payload")), + "apply_payload_sha256": sha256_json(apply_payload), + "target_rows_before": target_rows, + } + if any(preflight.get(key) != value for key, value in envelope.items()): + raise ValueError("fresh preflight does not match the approved proposal") + if preflight.get("preflight_sha256") != sha256_json(envelope): + raise ValueError("fresh preflight hash is internally inconsistent") + artifact_envelope = { + "captured_at_utc": preflight.get("captured_at_utc"), + **envelope, + "fresh_owned_targets": True, + } + if _parse_utc(preflight.get("captured_at_utc")) is None: + raise ValueError("fresh preflight captured_at_utc is invalid") + if preflight.get("preflight_artifact_sha256") != sha256_json(artifact_envelope): + raise ValueError("fresh preflight artifact hash is internally inconsistent") + rebuilt = build_fresh_preflight( + proposal_before, + target_rows, + captured_at_utc=preflight.get("captured_at_utc"), + ) + if canonical_json(preflight) != canonical_json(rebuilt): + raise ValueError("fresh preflight contract is internally inconsistent") + + +def _require_apply_receipt( + proposal_before: dict[str, Any], + preflight: dict[str, Any], + apply_receipt: dict[str, Any], +) -> dict[str, list[dict[str, Any]]]: + _require_approved_bundle(proposal_before) + _require_fresh_preflight(proposal_before, preflight) + proposal_after = apply_receipt.get("proposal") + if ( + apply_receipt.get("artifact") != "kb_apply_replay_receipt" + or apply_receipt.get("receipt_contract_version") != replay_receipt.RECEIPT_CONTRACT_VERSION + or apply_receipt.get("replay_ready") is not True + ): + raise ValueError("rollback requires a replay-ready kb_apply receipt") + if not isinstance(proposal_after, dict) or proposal_after.get("status") != "applied": + raise ValueError("apply receipt proposal must be applied") + if proposal_after.get("id") != proposal_before.get("id"): + raise ValueError("apply receipt proposal id does not match preflight") + if proposal_after.get("payload") != proposal_before.get("payload"): + raise ValueError("apply receipt payload does not match preflight") + if not proposal_after.get("applied_at") or not proposal_after.get("applied_by_handle"): + raise ValueError("apply receipt requires applied_at and applied_by_handle") + rows = apply_receipt.get("canonical_rows") + if not isinstance(rows, dict) or set(rows) != set(ROW_TABLES): + raise ValueError("apply receipt must contain every approve_claim canonical row family") + for name, table_rows in rows.items(): + if not isinstance(table_rows, list) or any(not isinstance(row, dict) for row in table_rows): + raise ValueError(f"apply receipt {name} rows are malformed") + identifiers = [row.get("id") for row in table_rows] + if any(not identifier for identifier in identifiers) or len(set(identifiers)) != len(identifiers): + raise ValueError(f"apply receipt {name} rows require unique persisted ids") + try: + replay_receipt.validate_replay_receipt( + apply_receipt, + expected_proposal_id=str(proposal_before.get("id")), + ) + except ValueError as exc: + raise ValueError("apply receipt failed full replay-contract validation") from exc + proposal_id = str(proposal_before.get("id")) + for row in rows["claim_evidence"]: + expected_id = ap.deterministic_row_uuid( + proposal_id, + "claim_evidence", + row.get("claim_id"), + row.get("source_id"), + row.get("role"), + ) + if row.get("id") != expected_id: + raise ValueError("fresh apply receipt evidence id is not deterministic") + for row in rows["claim_edges"]: + expected_id = ap.deterministic_row_uuid( + proposal_id, + "claim_edge", + row.get("from_claim"), + row.get("to_claim"), + row.get("edge_type"), + ) + if row.get("id") != expected_id: + raise ValueError("fresh apply receipt edge id is not deterministic") + return rows + + +def _row_assertion(table: str, row: dict[str, Any], label: str) -> str: + row_json = ap.sql_literal(canonical_json(row)) + row_id = ap.sql_literal(row["id"]) + return f""" if (select count(*) from {table} t + where t.id = {row_id}::uuid and to_jsonb(t) = {row_json}::jsonb) <> 1 then + raise exception 'proposal rollback drift: {label} row does not match apply receipt'; + end if;""" + + +def _delete_statement(table: str, rows: list[dict[str, Any]], label: str) -> str: + if not rows: + return f" -- no {label} rows owned by this proposal" + identifiers = ", ".join(f"{ap.sql_literal(row['id'])}::uuid" for row in rows) + return f""" delete from {table} where id in ({identifiers}); + get diagnostics affected = row_count; + if affected <> {len(rows)} then + raise exception 'proposal rollback count mismatch for {label}: expected {len(rows)}, got %', affected; + end if;""" + + +def _require_approval_snapshot(proposal_before: dict[str, Any], approval_snapshot: dict[str, Any]) -> None: + expected_keys = { + "proposal_id", + "proposal_type", + "payload", + "reviewed_by_handle", + "reviewed_by_agent_id", + "reviewed_by_db_role", + "reviewed_at", + "review_note", + } + if not isinstance(approval_snapshot, dict) or set(approval_snapshot) != expected_keys: + raise ValueError("immutable approval snapshot contract is incomplete or unexpected") + reviewer_role = approval_snapshot.get("reviewed_by_db_role") + if not isinstance(reviewer_role, str) or not reviewer_role or reviewer_role == "kb_apply": + raise ValueError("immutable approval snapshot requires an independent review role") + expected = { + "proposal_id": proposal_before.get("id"), + "proposal_type": proposal_before.get("proposal_type"), + "payload": proposal_before.get("payload"), + "reviewed_by_handle": proposal_before.get("reviewed_by_handle"), + "reviewed_by_agent_id": proposal_before.get("reviewed_by_agent_id"), + "reviewed_by_db_role": reviewer_role, + "reviewed_at": proposal_before.get("reviewed_at"), + "review_note": proposal_before.get("review_note"), + } + if canonical_json(approval_snapshot) != canonical_json(expected): + raise ValueError("immutable approval snapshot does not match the approved proposal") + if approval_snapshot.get("reviewed_by_handle") == ap.SERVICE_AGENT_HANDLE: + raise ValueError("apply service cannot independently approve its own proposal") + + +def build_compensating_rollback_sql( + proposal_before: dict[str, Any], + approval_snapshot: dict[str, Any], + preflight: dict[str, Any], + apply_receipt: dict[str, Any], +) -> str: + """Build one atomic, drift-sensitive apply inverse for a fresh-owned bundle.""" + rows = _require_apply_receipt(proposal_before, preflight, apply_receipt) + _require_approval_snapshot(proposal_before, approval_snapshot) + + applied = apply_receipt["proposal"] + proposal_id = ap.sql_literal(proposal_before["id"]) + payload = ap.sql_literal(canonical_json(proposal_before["payload"])) + reviewed_by_handle = ap.sql_literal(proposal_before.get("reviewed_by_handle")) + reviewed_by_agent_id = ap.sql_literal(proposal_before.get("reviewed_by_agent_id")) + reviewed_at = ap.sql_literal(proposal_before.get("reviewed_at")) + review_note = ap.sql_literal(proposal_before.get("review_note")) + applied_by_handle = ap.sql_literal(applied.get("applied_by_handle")) + applied_by_agent_id = ap.sql_literal(applied.get("applied_by_agent_id")) + applied_at = ap.sql_literal(applied.get("applied_at")) + approval_json = ap.sql_literal(canonical_json(approval_snapshot)) + + row_assertions = [] + for family in DELETE_ORDER: + table = ROW_TABLES[family] + row_assertions.extend( + _row_assertion(table, row, f"{family}[{index}]") for index, row in enumerate(rows[family]) + ) + deletions = [_delete_statement(ROW_TABLES[family], rows[family], family) for family in DELETE_ORDER] + + return f"""begin; +set local standard_conforming_strings = on; +set local lock_timeout = '5s'; +select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || {proposal_id}, 0)); +do $rollback$ +declare + affected integer; + approval_now jsonb; +begin + perform 1 from kb_stage.kb_proposals + where id = {proposal_id}::uuid + for update; + if not found then + raise exception 'proposal rollback: proposal row missing'; + end if; + if not exists ( + select 1 from kb_stage.kb_proposals + where id = {proposal_id}::uuid + and proposal_type = 'approve_claim' + and status = 'applied' + and payload = {payload}::jsonb + and reviewed_by_handle is not distinct from {reviewed_by_handle} + and reviewed_by_agent_id is not distinct from {reviewed_by_agent_id}::uuid + and reviewed_at is not distinct from {reviewed_at}::timestamptz + and review_note is not distinct from {review_note} + and applied_by_handle is not distinct from {applied_by_handle} + and applied_by_agent_id is not distinct from {applied_by_agent_id}::uuid + and applied_at is not distinct from {applied_at}::timestamptz + ) then + raise exception 'proposal rollback: applied ledger does not match apply receipt'; + end if; + select jsonb_build_object( + 'proposal_id', proposal_id::text, + 'proposal_type', proposal_type, + 'payload', payload, + 'reviewed_by_handle', reviewed_by_handle, + 'reviewed_by_agent_id', reviewed_by_agent_id::text, + 'reviewed_by_db_role', reviewed_by_db_role::text, + 'reviewed_at', reviewed_at::text, + 'review_note', review_note + ) into approval_now + from kb_stage.kb_proposal_approvals + where proposal_id = {proposal_id}::uuid; + if approval_now is distinct from {approval_json}::jsonb then + raise exception 'proposal rollback: immutable approval snapshot drifted'; + end if; +{chr(10).join(row_assertions)} +{chr(10).join(deletions)} + update kb_stage.kb_proposals + set status = 'approved', + applied_by_handle = null, + applied_by_agent_id = null, + applied_at = null, + updated_at = now() + where id = {proposal_id}::uuid + and status = 'applied' + and payload = {payload}::jsonb + and applied_at is not distinct from {applied_at}::timestamptz; + get diagnostics affected = row_count; + if affected <> 1 then + raise exception 'proposal rollback: expected one applied ledger row, got %', affected; + end if; +end +$rollback$; +commit; +""" + + +def build_production_rollback_artifact( + *, + proposal_before: dict[str, Any], + approval_snapshot: dict[str, Any], + preflight: dict[str, Any], + apply_receipt: dict[str, Any], + destination: dict[str, Any], + generated_at_utc: str | None = None, +) -> dict[str, Any]: + """Build a private artifact whose rollback SQL is exactly reconstructable.""" + destination_keys = {"container", "database", "system_identifier", "server_version_num"} + if not isinstance(destination, dict) or set(destination) != destination_keys: + raise ValueError("production rollback artifact requires the exact destination identity") + if any(not destination.get(key) for key in destination_keys): + raise ValueError("production rollback artifact destination identity is incomplete") + generated = generated_at_utc or datetime.now(timezone.utc).isoformat() + if _parse_utc(generated) is None: + raise ValueError("production rollback artifact timestamp is invalid") + rollback_sql = build_compensating_rollback_sql( + proposal_before, + approval_snapshot, + preflight, + apply_receipt, + ) + private_material = { + "proposal_before": proposal_before, + "approval_snapshot": approval_snapshot, + "preflight": preflight, + "apply_receipt": apply_receipt, + } + artifact = { + "artifact": "proposal_apply_production_rollback_artifact", + "schema": PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA, + "generated_at_utc": generated, + "destination": destination, + "proposal_id": str(proposal_before.get("id")), + "proposal_payload_sha256": sha256_json(proposal_before.get("payload")), + "approval_snapshot_sha256": sha256_json(approval_snapshot), + "fresh_preflight_artifact_sha256": preflight.get("preflight_artifact_sha256"), + "apply_receipt_sha256": sha256_json(apply_receipt), + "rollback_sql": rollback_sql, + "rollback_sql_sha256": sha256_text(rollback_sql), + "private_material": private_material, + "privacy": "private production rollback material; never commit or print", + } + artifact["artifact_sha256"] = sha256_json(artifact) + return artifact + + +def validate_production_rollback_artifact( + artifact: dict[str, Any], + *, + expected_destination: dict[str, Any] | None = None, +) -> dict[str, Any]: + expected_keys = { + "artifact", + "schema", + "generated_at_utc", + "destination", + "proposal_id", + "proposal_payload_sha256", + "approval_snapshot_sha256", + "fresh_preflight_artifact_sha256", + "apply_receipt_sha256", + "rollback_sql", + "rollback_sql_sha256", + "private_material", + "privacy", + "artifact_sha256", + } + if not isinstance(artifact, dict) or set(artifact) != expected_keys: + raise ValueError("production rollback artifact contract is incomplete or unexpected") + if ( + artifact.get("artifact") != "proposal_apply_production_rollback_artifact" + or artifact.get("schema") != PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA + or artifact.get("privacy") != "private production rollback material; never commit or print" + or _parse_utc(artifact.get("generated_at_utc")) is None + ): + raise ValueError("production rollback artifact metadata is invalid") + unsigned = dict(artifact) + artifact_sha256 = unsigned.pop("artifact_sha256") + if not is_sha256(artifact_sha256) or sha256_json(unsigned) != artifact_sha256: + raise ValueError("production rollback artifact hash is internally inconsistent") + destination = artifact.get("destination") + destination_keys = {"container", "database", "system_identifier", "server_version_num"} + if not isinstance(destination, dict) or set(destination) != destination_keys: + raise ValueError("production rollback artifact destination is invalid") + if expected_destination is not None and canonical_json(destination) != canonical_json(expected_destination): + raise ValueError("production rollback artifact destination does not match authorization binding") + material = artifact.get("private_material") + material_keys = {"proposal_before", "approval_snapshot", "preflight", "apply_receipt"} + if not isinstance(material, dict) or set(material) != material_keys: + raise ValueError("production rollback artifact private material is incomplete") + expected_sql = build_compensating_rollback_sql( + material["proposal_before"], + material["approval_snapshot"], + material["preflight"], + material["apply_receipt"], + ) + expected_fields = { + "proposal_id": str(material["proposal_before"].get("id")), + "proposal_payload_sha256": sha256_json(material["proposal_before"].get("payload")), + "approval_snapshot_sha256": sha256_json(material["approval_snapshot"]), + "fresh_preflight_artifact_sha256": material["preflight"].get("preflight_artifact_sha256"), + "apply_receipt_sha256": sha256_json(material["apply_receipt"]), + "rollback_sql": expected_sql, + "rollback_sql_sha256": sha256_text(expected_sql), + } + if any(canonical_json(artifact.get(key)) != canonical_json(value) for key, value in expected_fields.items()): + raise ValueError("production rollback artifact does not match reconstructed exact SQL") + return artifact + + +def _row_ids(rows: dict[str, list[dict[str, Any]]]) -> dict[str, list[str]]: + return {name: sorted(str(row["id"]) for row in table_rows) for name, table_rows in rows.items()} + + +def build_lifecycle_receipt( + *, + proposal_before: dict[str, Any], + approval_before: dict[str, Any], + preflight: dict[str, Any], + apply_receipt: dict[str, Any], + rollback_sql: str, + proposal_after: dict[str, Any], + approval_after: dict[str, Any], + target_rows_after: dict[str, list[dict[str, Any]]], + counts_before: dict[str, int], + counts_after: dict[str, int], + unrelated_before: dict[str, Any], + unrelated_after: dict[str, Any], + rollback_replay_refused: bool, + generated_at_utc: str | None = None, +) -> dict[str, Any]: + rows = _require_apply_receipt(proposal_before, preflight, apply_receipt) + expected_rollback_sql = build_compensating_rollback_sql( + proposal_before, + approval_before, + preflight, + apply_receipt, + ) + target_rows_absent = set(target_rows_after) == set(ROW_TABLES) and all( + isinstance(value, list) and not value for value in target_rows_after.values() + ) + expected_after = dict(proposal_before) + expected_after.update( + { + "status": "approved", + "applied_by_handle": None, + "applied_by_agent_id": None, + "applied_at": None, + } + ) + ledger_restored = all(proposal_after.get(key) == value for key, value in expected_after.items()) + checks = { + "fresh_owned_targets": preflight.get("fresh_owned_targets") is True, + "apply_receipt_replay_ready": apply_receipt.get("replay_ready") is True, + "apply_rows_have_exact_ids": all(rows[name] == apply_receipt["canonical_rows"][name] for name in ROW_TABLES), + "rollback_target_rows_absent": target_rows_absent, + "rollback_counts_restored": counts_after == counts_before, + "rollback_ledger_restored_to_approved": ledger_restored, + "immutable_approval_unchanged": approval_after == approval_before, + "unrelated_rows_unchanged": unrelated_after == unrelated_before, + "rollback_replay_refused_without_mutation": rollback_replay_refused is True, + "rollback_sql_exact_for_bound_rows": rollback_sql == expected_rollback_sql, + } + proposal_projection = { + key: proposal_before.get(key) + for key in ( + "id", + "proposal_type", + "status", + "payload", + "reviewed_by_handle", + "reviewed_by_agent_id", + "reviewed_at", + "review_note", + "applied_by_handle", + "applied_by_agent_id", + "applied_at", + ) + } + receipt = { + "artifact": "proposal_apply_lifecycle_receipt", + "schema": LIFECYCLE_SCHEMA, + "generated_at_utc": generated_at_utc or datetime.now(timezone.utc).isoformat(), + "required_tier": "T2_runtime", + "current_tier": "T2_runtime" if all(checks.values()) else "T1_model", + "proposal_before_apply": proposal_projection, + "proposal_payload_sha256": sha256_json(proposal_before.get("payload")), + "apply_payload_sha256": sha256_json(proposal_before["payload"]["apply_payload"]), + "approval_snapshot_sha256": sha256_json(approval_before), + "fresh_preflight_sha256": preflight["preflight_sha256"], + "fresh_preflight_artifact_sha256": preflight["preflight_artifact_sha256"], + "apply_receipt_sha256": sha256_json(apply_receipt), + "apply_sql_sha256": apply_receipt["apply_engine"]["apply_sql_sha256"], + "applied_row_ids": _row_ids(rows), + "applied_row_sha256": {name: [sha256_json(row) for row in table_rows] for name, table_rows in rows.items()}, + "rollback": { + "schema": ROLLBACK_SCHEMA, + "rollback_sql_sha256": sha256_text(rollback_sql), + "delete_order": list(DELETE_ORDER), + "target_rows_after": target_rows_after, + "counts_before_apply": counts_before, + "counts_after_rollback": counts_after, + "proposal_after": { + key: proposal_after.get(key) + for key in ( + "id", + "proposal_type", + "status", + "reviewed_by_handle", + "reviewed_by_agent_id", + "reviewed_at", + "review_note", + "applied_by_handle", + "applied_by_agent_id", + "applied_at", + ) + }, + }, + "checks": checks, + "pass": all(checks.values()), + "production_apply_executed": False, + "production_apply_authorization_present": False, + "strongest_claim_allowed": ( + "deterministic disposable-clone apply and compensating rollback" + if all(checks.values()) + else "local lifecycle evidence incomplete" + ), + } + receipt["lifecycle_receipt_sha256"] = sha256_json(receipt) + return receipt + + +def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: + expected_keys = { + "artifact", + "schema", + "generated_at_utc", + "required_tier", + "current_tier", + "proposal_before_apply", + "proposal_payload_sha256", + "apply_payload_sha256", + "approval_snapshot_sha256", + "fresh_preflight_sha256", + "fresh_preflight_artifact_sha256", + "apply_receipt_sha256", + "apply_sql_sha256", + "applied_row_ids", + "applied_row_sha256", + "rollback", + "checks", + "pass", + "production_apply_executed", + "production_apply_authorization_present", + "strongest_claim_allowed", + "lifecycle_receipt_sha256", + } + if not isinstance(lifecycle_receipt, dict) or set(lifecycle_receipt) != expected_keys: + raise ValueError("authorization packet requires the exact lifecycle receipt contract") + if ( + lifecycle_receipt.get("artifact") != "proposal_apply_lifecycle_receipt" + or lifecycle_receipt.get("schema") != LIFECYCLE_SCHEMA + or lifecycle_receipt.get("required_tier") != "T2_runtime" + or lifecycle_receipt.get("current_tier") != "T2_runtime" + or lifecycle_receipt.get("pass") is not True + or lifecycle_receipt.get("production_apply_executed") is not False + or lifecycle_receipt.get("production_apply_authorization_present") is not False + ): + raise ValueError("authorization packet requires a passing, non-production lifecycle receipt") + checks = lifecycle_receipt.get("checks") + if not isinstance(checks, dict) or not checks or any(value is not True for value in checks.values()): + raise ValueError("lifecycle receipt checks are incomplete or failed") + unsigned = dict(lifecycle_receipt) + receipt_sha256 = unsigned.pop("lifecycle_receipt_sha256") + if not is_sha256(receipt_sha256) or sha256_json(unsigned) != receipt_sha256: + raise ValueError("lifecycle receipt hash is internally inconsistent") + proposal = lifecycle_receipt.get("proposal_before_apply") + if not isinstance(proposal, dict) or proposal.get("status") != "approved": + raise ValueError("lifecycle receipt proposal is not approved before apply") + payload = proposal.get("payload") + apply_payload = payload.get("apply_payload") if isinstance(payload, dict) else None + if ( + not isinstance(apply_payload, dict) + or sha256_json(payload) != lifecycle_receipt.get("proposal_payload_sha256") + or sha256_json(apply_payload) != lifecycle_receipt.get("apply_payload_sha256") + ): + raise ValueError("lifecycle receipt proposal hashes are inconsistent") + hash_fields = ( + "approval_snapshot_sha256", + "fresh_preflight_sha256", + "fresh_preflight_artifact_sha256", + "apply_receipt_sha256", + "apply_sql_sha256", + ) + if any(not is_sha256(lifecycle_receipt.get(field)) for field in hash_fields): + raise ValueError("lifecycle receipt is missing an exact SHA-256 binding") + row_ids = lifecycle_receipt.get("applied_row_ids") + row_hashes = lifecycle_receipt.get("applied_row_sha256") + if ( + not isinstance(row_ids, dict) + or not isinstance(row_hashes, dict) + or set(row_ids) != set(ROW_TABLES) + or set(row_hashes) != set(ROW_TABLES) + or any(not isinstance(values, list) for values in row_ids.values()) + or any( + not isinstance(values, list) or any(not is_sha256(value) for value in values) + for values in row_hashes.values() + ) + or any(len(row_ids[name]) != len(row_hashes[name]) for name in ROW_TABLES) + ): + raise ValueError("lifecycle receipt row-level bindings are incomplete") + rollback = lifecycle_receipt.get("rollback") + if not isinstance(rollback, dict) or rollback.get("schema") != ROLLBACK_SCHEMA: + raise ValueError("lifecycle receipt rollback contract is missing") + if not is_sha256(rollback.get("rollback_sql_sha256")): + raise ValueError("lifecycle receipt rollback SQL hash is invalid") + target_rows_after = rollback.get("target_rows_after") + if ( + not isinstance(target_rows_after, dict) + or set(target_rows_after) != set(ROW_TABLES) + or any(not isinstance(rows, list) or rows for rows in target_rows_after.values()) + or rollback.get("counts_before_apply") != rollback.get("counts_after_rollback") + ): + raise ValueError("lifecycle receipt does not prove exact rollback cleanup") + + +def current_git_sha(repo_root: Path) -> str: + result = subprocess.run( + ["git", "rev-parse", "HEAD"], + cwd=repo_root, + text=True, + capture_output=True, + check=False, + ) + return result.stdout.strip() if result.returncode == 0 else "" + + +def runtime_manifest_for_commit( + repo_git_sha: str, + *, + require_current_head: bool, +) -> dict[str, str]: + repo_root = HERE.parent.resolve() + if ( + not isinstance(repo_git_sha, str) + or len(repo_git_sha) != 40 + or any(character not in "0123456789abcdef" for character in repo_git_sha) + ): + raise ValueError("authorization runtime requires a full lowercase Git commit SHA") + head = current_git_sha(repo_root) + if require_current_head and head != repo_git_sha: + raise ValueError("authorization packet Git SHA must equal the current implementation HEAD") + ancestor = subprocess.run( + ["git", "merge-base", "--is-ancestor", repo_git_sha, head], + cwd=repo_root, + text=True, + capture_output=True, + check=False, + ) + if ancestor.returncode != 0: + raise ValueError("authorization runtime commit is not an ancestor of the current checkout") + status = subprocess.run( + ["git", "status", "--porcelain", "--", *RUNTIME_DEPENDENCIES], + cwd=repo_root, + text=True, + capture_output=True, + check=False, + ) + if status.returncode != 0 or status.stdout.strip(): + raise ValueError("authorization runtime dependencies are dirty or untracked") + manifest: dict[str, str] = {} + for relative in RUNTIME_DEPENDENCIES: + current_path = repo_root / relative + if not current_path.is_file(): + raise ValueError(f"authorization runtime dependency is missing: {relative}") + committed = subprocess.run( + ["git", "show", f"{repo_git_sha}:{relative}"], + cwd=repo_root, + capture_output=True, + check=False, + ) + if committed.returncode != 0: + raise ValueError(f"authorization runtime dependency is absent from the bound commit: {relative}") + committed_sha256 = hashlib.sha256(committed.stdout).hexdigest() + current_sha256 = sha256_file(current_path) + if committed_sha256 != current_sha256: + raise ValueError(f"authorization runtime dependency differs from the bound commit: {relative}") + manifest[relative] = current_sha256 + return manifest + + +def _authorization_text_template(binding: dict[str, Any], binding_sha256: str) -> str: + proposal = binding["proposal"] + destination = binding["destination"] + return ( + "I authorize one production DB apply for proposal " + f"{proposal['id']} with payload SHA-256 {proposal['proposal_payload_sha256']} " + f"to Docker container {destination['container']}, database {destination['database']}, " + f"system identifier {destination['system_identifier']}, binding SHA-256 {binding_sha256}. " + "I also authorize conditional production rollback SHA-256 " + " " + "only if the bound postflight fails and no downstream dependency exists. " + "Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. " + "Operator ; received ; expires ." + ) + + +def build_authorization_packet( + lifecycle_receipt: dict[str, Any], + destination_readback: dict[str, Any], + *, + repo_git_sha: str, + apply_engine_path: Path, + approval_gate_path: Path = HERE / "kb_apply_prereqs.sql", + production_rollback_artifact: dict[str, Any] | None = None, + generated_at_utc: str | None = None, +) -> dict[str, Any]: + _require_lifecycle_receipt(lifecycle_receipt) + if not apply_engine_path.is_file(): + raise ValueError(f"apply engine file is missing: {apply_engine_path}") + if not approval_gate_path.is_file(): + raise ValueError(f"approval gate prerequisite file is missing: {approval_gate_path}") + apply_engine_relative = repo_relative_path(apply_engine_path) + approval_gate_relative = repo_relative_path(approval_gate_path) + if apply_engine_relative != "scripts/apply_proposal.py": + raise ValueError("authorization packet requires the canonical apply engine path") + if approval_gate_relative != "scripts/kb_apply_prereqs.sql": + raise ValueError("authorization packet requires the canonical approval-gate path") + runtime_manifest = runtime_manifest_for_commit(repo_git_sha, require_current_head=True) + required_destination = { + key: destination_readback.get(key) + for key in ("container", "database", "system_identifier", "server_version_num") + } + if any(not value for value in required_destination.values()): + raise ValueError("destination readback is missing exact production identity fields") + production_rollback_sha256: str | None = None + production_rollback_artifact_sha256: str | None = None + if production_rollback_artifact is not None: + validated_rollback = validate_production_rollback_artifact( + production_rollback_artifact, + expected_destination=required_destination, + ) + if ( + validated_rollback.get("proposal_id") != lifecycle_receipt["proposal_before_apply"].get("id") + or validated_rollback.get("proposal_payload_sha256") != lifecycle_receipt.get("proposal_payload_sha256") + or validated_rollback.get("approval_snapshot_sha256") != lifecycle_receipt.get("approval_snapshot_sha256") + ): + raise ValueError("production rollback artifact does not match the lifecycle proposal binding") + production_rollback_sha256 = validated_rollback["rollback_sql_sha256"] + production_rollback_artifact_sha256 = validated_rollback["artifact_sha256"] + proposal = lifecycle_receipt["proposal_before_apply"] + approval_gate = destination_readback.get("approval_gate") or {} + bound_gate = {check: approval_gate.get(check) for check in APPROVAL_GATE_CHECKS} + approval_gate_ready = all(bound_gate.get(check) is True for check in APPROVAL_GATE_CHECKS) + candidates = destination_readback.get("approved_strict_candidates") or [] + if not isinstance(candidates, list) or any(not isinstance(row, dict) for row in candidates): + raise ValueError("destination readback candidates must be row objects") + matching = [ + row + for row in candidates + if row.get("id") == proposal["id"] + and row.get("proposal_type") == proposal["proposal_type"] + and row.get("status") == "approved" + and row.get("applied_at") is None + and row.get("proposal_payload_sha256") == lifecycle_receipt["proposal_payload_sha256"] + and row.get("apply_payload_sha256") == lifecycle_receipt["apply_payload_sha256"] + and row.get("approval_snapshot_sha256") == lifecycle_receipt["approval_snapshot_sha256"] + and row.get("reviewed_by_handle") == proposal.get("reviewed_by_handle") + and row.get("reviewed_by_agent_id") == proposal.get("reviewed_by_agent_id") + and row.get("reviewed_at") == proposal.get("reviewed_at") + and row.get("review_note") == proposal.get("review_note") + and row.get("immutable_approval_exact") is True + ] + candidate_projection = ( + { + "id": matching[0].get("id"), + "proposal_type": matching[0].get("proposal_type"), + "status": matching[0].get("status"), + "applied_at": matching[0].get("applied_at"), + "proposal_payload_sha256": matching[0].get("proposal_payload_sha256"), + "apply_payload_sha256": matching[0].get("apply_payload_sha256"), + "approval_snapshot_sha256": matching[0].get("approval_snapshot_sha256"), + "reviewed_by_handle": matching[0].get("reviewed_by_handle"), + "reviewed_by_agent_id": matching[0].get("reviewed_by_agent_id"), + "reviewed_at": matching[0].get("reviewed_at"), + "review_note": matching[0].get("review_note"), + "immutable_approval_exact": matching[0].get("immutable_approval_exact"), + } + if len(matching) == 1 + else None + ) + observed_at_utc = destination_readback.get("observed_at_utc") + destination_readback_was_read_only = ( + destination_readback.get("read_only_transaction") is True and _parse_utc(observed_at_utc) is not None + ) + production_preconditions = { + "destination_readback_observed_at_utc": observed_at_utc, + "destination_readback_was_read_only": destination_readback_was_read_only, + "approval_gate_ready": approval_gate_ready, + "strict_proposal_present_and_approved": len(matching) == 1, + "matching_candidate_count": len(matching), + "exact_production_rollback_packet_ready": production_rollback_sha256 is not None, + "production_apply_authorization_present": False, + "production_apply_executed": False, + } + binding = { + "proposal": { + "id": proposal["id"], + "proposal_type": proposal["proposal_type"], + "required_status": "approved", + "required_applied_at": None, + "payload": proposal["payload"], + "reviewed_by_handle": proposal.get("reviewed_by_handle"), + "reviewed_by_agent_id": proposal.get("reviewed_by_agent_id"), + "reviewed_at": proposal.get("reviewed_at"), + "review_note": proposal.get("review_note"), + "proposal_payload_sha256": lifecycle_receipt["proposal_payload_sha256"], + "apply_payload_sha256": lifecycle_receipt["apply_payload_sha256"], + "approval_snapshot_sha256": lifecycle_receipt["approval_snapshot_sha256"], + }, + "destination": required_destination, + "destination_readback": { + "observed_at_utc": observed_at_utc, + "read_only_transaction": destination_readback.get("read_only_transaction"), + }, + "approval_gate": bound_gate, + "candidate_readback": { + "matching_candidate_count": len(matching), + "matching_candidate": candidate_projection, + }, + "approval_gate_dependency": { + "path": approval_gate_relative, + "sha256": sha256_file(approval_gate_path), + "requires_separate_production_authorization": True, + }, + "engine": { + "repo_git_sha": repo_git_sha, + "apply_engine_path": apply_engine_relative, + "apply_engine_sha256": sha256_file(apply_engine_path), + "apply_sql_sha256": lifecycle_receipt["apply_sql_sha256"], + "runtime_manifest": runtime_manifest, + }, + "rollback": { + "rollback_sql_sha256": lifecycle_receipt["rollback"]["rollback_sql_sha256"], + "lifecycle_receipt_sha256": lifecycle_receipt["lifecycle_receipt_sha256"], + "scope": "disposable_clone_rehearsal", + "production_executable": False, + "conditional_rollback_requires_explicit_authorization": True, + }, + "production_rollback": { + "status": "ready" if production_rollback_sha256 is not None else "not_generated", + "rollback_sql_sha256": production_rollback_sha256, + "artifact_schema": ( + PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA if production_rollback_artifact_sha256 is not None else None + ), + "artifact_sha256": production_rollback_artifact_sha256, + "scope": "exact_production_destination_postapply_receipt", + "bound_for_action_time_authorization": production_rollback_artifact_sha256 is not None, + "conditional_rollback_requires_explicit_authorization": True, + }, + "expected_rows": { + "row_ids": lifecycle_receipt["applied_row_ids"], + "row_sha256": lifecycle_receipt["applied_row_sha256"], + }, + "production_preconditions": production_preconditions, + } + binding_sha256 = sha256_json(binding) + packet = { + "artifact": "proposal_apply_production_authorization_packet", + "schema": AUTHORIZATION_SCHEMA, + "generated_at_utc": generated_at_utc or datetime.now(timezone.utc).isoformat(), + "required_tier": "T6_authorized_production", + "current_tier": "T3_live_readonly", + "binding": binding, + "binding_sha256": binding_sha256, + "production_preconditions": dict(production_preconditions), + "authorization_record_required": { + "authorized": True, + "rollback_authorized": True, + "binding_sha256": binding_sha256, + "production_rollback_sql_sha256": (production_rollback_sha256 or ""), + "operator_identity": "", + "received_at_utc": "", + "expires_at_utc": "", + "authorization_text": "", + }, + "authorization_text_template": _authorization_text_template(binding, binding_sha256), + "safe_to_enter_apply_window": False, + "production_apply_authorization_present": False, + "production_apply_executed": False, + "scope_exclusions": { + "approval_gate_deployment_authorized": False, + "telegram_send_authorized": False, + "gcp_promotion_authorized": False, + "cloud_sql_exposure_authorized": False, + }, + "production_rollback_requirement": { + "status": "ready" if production_rollback_sha256 is not None else "not_generated", + "production_rollback_sql_sha256": production_rollback_sha256, + "production_rollback_artifact_schema": ( + PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA if production_rollback_artifact_sha256 is not None else None + ), + "production_rollback_artifact_sha256": production_rollback_artifact_sha256, + "clone_rehearsal_rollback_sql_sha256": lifecycle_receipt["rollback"]["rollback_sql_sha256"], + "clone_rehearsal_is_not_production_rollback": True, + "required_before_apply_window": True, + "required_binding": ( + "an exact production rollback SQL SHA-256 in both the action-time record and authorization text" + ), + }, + "next_exact_action": ( + "refresh the exact destination through a read-only transaction" + if not destination_readback_was_read_only + else "deploy and independently verify the immutable approval gate before selecting a production proposal" + if not approval_gate_ready + else "stage this exact strict proposal in production and obtain independent review" + if not matching + else "generate and retain the exact production rollback SQL" + if production_rollback_sha256 is None + else "obtain the exact action-time authorization record" + ), + "claim_ceiling": ( + "T2 clone lifecycle plus T3 destination readback; no production apply authorization or execution" + ), + } + return packet + + +def expected_authorization_text(packet: dict[str, Any], record: dict[str, Any]) -> str: + template = packet.get("authorization_text_template") + if not isinstance(template, str): + raise ValueError("authorization packet has no text template") + return ( + template.replace( + "", + str(record.get("production_rollback_sql_sha256") or ""), + ) + .replace("", str(record.get("operator_identity") or "")) + .replace("", str(record.get("received_at_utc") or ""), 1) + .replace("", str(record.get("expires_at_utc") or ""), 1) + ) + + +def _parse_utc(value: Any) -> datetime | None: + if not isinstance(value, str) or not value: + return None + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError: + return None + if parsed.tzinfo is None: + return None + return parsed.astimezone(timezone.utc) + + +def verify_authorization_record( + packet: dict[str, Any], + record: dict[str, Any], + *, + observed_destination: dict[str, Any], + apply_engine_path: Path, + approval_gate_path: Path = HERE / "kb_apply_prereqs.sql", + production_rollback_artifact: dict[str, Any] | None = None, + now: datetime | None = None, +) -> dict[str, Any]: + packet = packet if isinstance(packet, dict) else {} + record = record if isinstance(record, dict) else {} + observed_destination = observed_destination if isinstance(observed_destination, dict) else {} + now = (now or datetime.now(timezone.utc)).astimezone(timezone.utc) + received = _parse_utc(record.get("received_at_utc")) + expires = _parse_utc(record.get("expires_at_utc")) + binding = packet.get("binding") if isinstance(packet.get("binding"), dict) else {} + packet_preconditions = ( + packet.get("production_preconditions") if isinstance(packet.get("production_preconditions"), dict) else {} + ) + bound_preconditions = ( + binding.get("production_preconditions") if isinstance(binding.get("production_preconditions"), dict) else {} + ) + required_destination = binding.get("destination") if isinstance(binding.get("destination"), dict) else {} + destination_keys = {"container", "database", "system_identifier", "server_version_num"} + observed_destination_projection = {key: observed_destination.get(key) for key in destination_keys} + destination_matches = set(required_destination) == destination_keys and canonical_json( + observed_destination_projection + ) == canonical_json(required_destination) + bound_destination_readback = ( + binding.get("destination_readback") if isinstance(binding.get("destination_readback"), dict) else {} + ) + required_gate = binding.get("approval_gate") if isinstance(binding.get("approval_gate"), dict) else {} + observed_gate = ( + observed_destination.get("approval_gate") if isinstance(observed_destination.get("approval_gate"), dict) else {} + ) + required_gate_ready = set(required_gate) == set(APPROVAL_GATE_CHECKS) and all( + required_gate.get(key) is True for key in APPROVAL_GATE_CHECKS + ) + observed_gate_ready = all(observed_gate.get(key) is True for key in APPROVAL_GATE_CHECKS) + gate_matches = ( + required_gate_ready + and observed_gate_ready + and all(observed_gate.get(key) is required_gate.get(key) for key in APPROVAL_GATE_CHECKS) + ) + required_proposal = binding.get("proposal") if isinstance(binding.get("proposal"), dict) else {} + required_payload = required_proposal.get("payload") + required_apply_payload = required_payload.get("apply_payload") if isinstance(required_payload, dict) else None + proposal_binding_self_consistent = ( + required_proposal.get("required_status") == "approved" + and required_proposal.get("required_applied_at") is None + and isinstance(required_apply_payload, dict) + and sha256_json(required_payload) == required_proposal.get("proposal_payload_sha256") + and sha256_json(required_apply_payload) == required_proposal.get("apply_payload_sha256") + and is_sha256(required_proposal.get("approval_snapshot_sha256")) + ) + bound_candidate_readback = ( + binding.get("candidate_readback") if isinstance(binding.get("candidate_readback"), dict) else {} + ) + bound_candidate = bound_candidate_readback.get("matching_candidate") + expected_bound_candidate = { + "id": required_proposal.get("id"), + "proposal_type": required_proposal.get("proposal_type"), + "status": required_proposal.get("required_status"), + "applied_at": required_proposal.get("required_applied_at"), + "proposal_payload_sha256": required_proposal.get("proposal_payload_sha256"), + "apply_payload_sha256": required_proposal.get("apply_payload_sha256"), + "approval_snapshot_sha256": required_proposal.get("approval_snapshot_sha256"), + "reviewed_by_handle": required_proposal.get("reviewed_by_handle"), + "reviewed_by_agent_id": required_proposal.get("reviewed_by_agent_id"), + "reviewed_at": required_proposal.get("reviewed_at"), + "review_note": required_proposal.get("review_note"), + "immutable_approval_exact": True, + } + bound_candidate_exact = ( + bound_candidate_readback.get("matching_candidate_count") == 1 + and isinstance(bound_candidate, dict) + and canonical_json(bound_candidate) == canonical_json(expected_bound_candidate) + ) + observed_candidates = observed_destination.get("approved_strict_candidates") or [] + if not isinstance(observed_candidates, list) or any(not isinstance(row, dict) for row in observed_candidates): + observed_candidates = [] + matching_candidates = [ + candidate + for candidate in observed_candidates + if candidate.get("id") == required_proposal.get("id") + and candidate.get("proposal_type") == required_proposal.get("proposal_type") + and candidate.get("status") == required_proposal.get("required_status") + and candidate.get("applied_at") is required_proposal.get("required_applied_at") + and candidate.get("proposal_payload_sha256") == required_proposal.get("proposal_payload_sha256") + and candidate.get("apply_payload_sha256") == required_proposal.get("apply_payload_sha256") + and candidate.get("approval_snapshot_sha256") == required_proposal.get("approval_snapshot_sha256") + and candidate.get("reviewed_by_handle") == required_proposal.get("reviewed_by_handle") + and candidate.get("reviewed_by_agent_id") == required_proposal.get("reviewed_by_agent_id") + and candidate.get("reviewed_at") == required_proposal.get("reviewed_at") + and candidate.get("review_note") == required_proposal.get("review_note") + and candidate.get("immutable_approval_exact") is True + ] + production_rollback_sha256 = record.get("production_rollback_sql_sha256") + bound_production_rollback = ( + binding.get("production_rollback") if isinstance(binding.get("production_rollback"), dict) else {} + ) + bound_production_rollback_sha256 = bound_production_rollback.get("rollback_sql_sha256") + production_rollback_artifact_valid = False + if production_rollback_artifact is not None: + try: + validated_rollback = validate_production_rollback_artifact( + production_rollback_artifact, + expected_destination=required_destination, + ) + production_rollback_artifact_valid = ( + validated_rollback.get("artifact_sha256") == bound_production_rollback.get("artifact_sha256") + and validated_rollback.get("schema") == bound_production_rollback.get("artifact_schema") + and validated_rollback.get("rollback_sql_sha256") == bound_production_rollback_sha256 + and validated_rollback.get("proposal_id") == required_proposal.get("id") + and validated_rollback.get("proposal_payload_sha256") + == required_proposal.get("proposal_payload_sha256") + and validated_rollback.get("approval_snapshot_sha256") + == required_proposal.get("approval_snapshot_sha256") + ) + except ValueError: + production_rollback_artifact_valid = False + production_rollback_packet_ready = ( + bound_production_rollback.get("status") == "ready" + and bound_production_rollback.get("bound_for_action_time_authorization") is True + and bound_production_rollback.get("conditional_rollback_requires_explicit_authorization") is True + and bound_production_rollback.get("artifact_schema") == PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA + and is_sha256(bound_production_rollback.get("artifact_sha256")) + and is_sha256(bound_production_rollback_sha256) + and production_rollback_artifact_valid + ) + packet_binding_sha256 = packet.get("binding_sha256") + binding_self_consistent = is_sha256(packet_binding_sha256) and sha256_json(binding) == packet_binding_sha256 + try: + expected_template = _authorization_text_template(binding, packet_binding_sha256) + except (KeyError, TypeError): + expected_template = "" + expected_scope_exclusions = { + "approval_gate_deployment_authorized": False, + "telegram_send_authorized": False, + "gcp_promotion_authorized": False, + "cloud_sql_exposure_authorized": False, + } + required_record_keys = { + "authorized", + "rollback_authorized", + "binding_sha256", + "production_rollback_sql_sha256", + "operator_identity", + "received_at_utc", + "expires_at_utc", + "authorization_text", + } + expected_record_template = { + "authorized": True, + "rollback_authorized": True, + "binding_sha256": packet_binding_sha256, + "production_rollback_sql_sha256": ( + bound_production_rollback_sha256 + if is_sha256(bound_production_rollback_sha256) + else "" + ), + "operator_identity": "", + "received_at_utc": "", + "expires_at_utc": "", + "authorization_text": "", + } + try: + expected_record_text = expected_authorization_text(packet, record) + except ValueError: + expected_record_text = "" + bound_engine = binding.get("engine") if isinstance(binding.get("engine"), dict) else {} + bound_gate_dependency = ( + binding.get("approval_gate_dependency") if isinstance(binding.get("approval_gate_dependency"), dict) else {} + ) + runtime_provenance_valid = False + try: + current_runtime_manifest = runtime_manifest_for_commit( + bound_engine.get("repo_git_sha"), + require_current_head=False, + ) + runtime_provenance_valid = canonical_json(current_runtime_manifest) == canonical_json( + bound_engine.get("runtime_manifest") + ) + except ValueError: + runtime_provenance_valid = False + try: + apply_engine_relative = repo_relative_path(apply_engine_path) + except ValueError: + apply_engine_relative = "" + try: + approval_gate_relative = repo_relative_path(approval_gate_path) + except ValueError: + approval_gate_relative = "" + action_observed_at = _parse_utc(observed_destination.get("observed_at_utc")) + action_readback_fresh = ( + received is not None + and action_observed_at is not None + and received <= action_observed_at <= now + and observed_destination.get("read_only_transaction") is True + ) + checks = { + "packet_schema_exact": ( + packet.get("artifact") == "proposal_apply_production_authorization_packet" + and packet.get("schema") == AUTHORIZATION_SCHEMA + and packet.get("required_tier") == "T6_authorized_production" + and packet.get("current_tier") == "T3_live_readonly" + and _parse_utc(packet.get("generated_at_utc")) is not None + ), + "packet_binding_sha256_self_consistent": binding_self_consistent, + "packet_preconditions_bound_exactly": ( + canonical_json(packet_preconditions) == canonical_json(bound_preconditions) + ), + "proposal_binding_self_consistent": proposal_binding_self_consistent, + "packet_destination_readback_was_read_only": ( + packet_preconditions.get("destination_readback_was_read_only") is True + and bound_destination_readback.get("read_only_transaction") is True + and _parse_utc(bound_destination_readback.get("observed_at_utc")) is not None + and bound_destination_readback.get("observed_at_utc") + == packet_preconditions.get("destination_readback_observed_at_utc") + ), + "approval_gate_ready_at_packet": ( + packet_preconditions.get("approval_gate_ready") is True and required_gate_ready + ), + "exact_production_rollback_packet_ready": ( + packet_preconditions.get("exact_production_rollback_packet_ready") is True + and production_rollback_packet_ready + ), + "strict_proposal_present_and_approved": ( + packet_preconditions.get("strict_proposal_present_and_approved") is True + and packet_preconditions.get("matching_candidate_count") == 1 + and bound_candidate_exact + ), + "packet_never_self_authorizes_or_expands_scope": ( + packet.get("safe_to_enter_apply_window") is False + and packet.get("production_apply_authorization_present") is False + and packet.get("production_apply_executed") is False + and packet_preconditions.get("production_apply_authorization_present") is False + and packet_preconditions.get("production_apply_executed") is False + and canonical_json(packet.get("scope_exclusions")) == canonical_json(expected_scope_exclusions) + ), + "authorization_text_template_exact": packet.get("authorization_text_template") == expected_template, + "authorization_record_template_exact": ( + canonical_json(packet.get("authorization_record_required")) == canonical_json(expected_record_template) + ), + "authorization_record_contract_exact": isinstance(record, dict) and set(record) == required_record_keys, + "authorized_is_exact_true": record.get("authorized") is True, + "rollback_authorized_is_exact_true": record.get("rollback_authorized") is True, + "production_rollback_sql_sha256_exact": ( + is_sha256(production_rollback_sha256) and production_rollback_sha256 == bound_production_rollback_sha256 + ), + "binding_sha256_exact": binding_self_consistent and record.get("binding_sha256") == packet_binding_sha256, + "operator_identity_present": ( + isinstance(record.get("operator_identity"), str) + and bool(record.get("operator_identity", "").strip()) + and not record.get("operator_identity", "").startswith("<") + ), + "authorization_window_valid": ( + received is not None and expires is not None and received <= now <= expires and received < expires + ), + "authorization_text_exact": bool(expected_record_text) + and record.get("authorization_text") == expected_record_text, + "destination_identity_exact": destination_matches, + "destination_readback_fresh_and_read_only_at_action": action_readback_fresh, + "approval_gate_identity_exact_at_action": gate_matches, + "strict_proposal_exact_at_action": len(matching_candidates) == 1, + "apply_engine_sha256_exact": ( + apply_engine_path.is_file() + and apply_engine_relative == bound_engine.get("apply_engine_path") + and sha256_file(apply_engine_path) == bound_engine.get("apply_engine_sha256") + ), + "runtime_commit_and_manifest_exact": runtime_provenance_valid, + "approval_gate_prerequisite_sha256_exact": ( + approval_gate_path.is_file() + and approval_gate_relative == bound_gate_dependency.get("path") + and sha256_file(approval_gate_path) == bound_gate_dependency.get("sha256") + ), + } + return { + "schema": "livingip.proposalApplyAuthorizationVerification.v1", + "checks": checks, + "safe_to_enter_apply_window": all(checks.values()), + "production_apply_authorization_present": all(checks.values()), + "production_apply_executed": False, + } + + +def _load_json(path: Path) -> dict[str, Any]: + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError(f"JSON file must contain an object: {path}") + return data + + +def _write_json(path: Path, data: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def write_authorization_markdown(path: Path, packet: dict[str, Any]) -> None: + binding = packet["binding"] + proposal = binding["proposal"] + destination = binding["destination"] + engine = binding["engine"] + rollback = binding["rollback"] + production_rollback = binding["production_rollback"] + gate_dependency = binding["approval_gate_dependency"] + preconditions = packet["production_preconditions"] + lines = [ + "# Proposal Apply Production Authorization Packet", + "", + f"Generated UTC: `{packet['generated_at_utc']}`", + f"Required tier: `{packet['required_tier']}`", + f"Current tier: `{packet['current_tier']}`", + f"Safe to enter apply window: `{packet['safe_to_enter_apply_window']}`", + f"Production apply authorized: `{packet['production_apply_authorization_present']}`", + f"Production apply executed: `{packet['production_apply_executed']}`", + "", + "## Exact Binding", + "", + f"- Proposal: `{proposal['id']}` (`{proposal['proposal_type']}`)", + f"- Proposal payload SHA-256: `{proposal['proposal_payload_sha256']}`", + f"- Apply payload SHA-256: `{proposal['apply_payload_sha256']}`", + f"- Immutable approval SHA-256: `{proposal['approval_snapshot_sha256']}`", + f"- Destination: `{destination['container']}/{destination['database']}`", + f"- Destination system identifier: `{destination['system_identifier']}`", + f"- Apply engine SHA-256: `{engine['apply_engine_sha256']}`", + f"- Apply engine path: `{engine['apply_engine_path']}`", + f"- Apply SQL SHA-256: `{engine['apply_sql_sha256']}`", + f"- Clone rehearsal rollback SQL SHA-256: `{rollback['rollback_sql_sha256']}`", + f"- Production rollback status: `{production_rollback['status']}`", + f"- Production rollback SQL SHA-256: `{production_rollback['rollback_sql_sha256']}`", + f"- Approval gate prerequisite SHA-256: `{gate_dependency['sha256']}`", + f"- Approval gate prerequisite path: `{gate_dependency['path']}`", + f"- Binding SHA-256: `{packet['binding_sha256']}`", + "", + "## Production Preconditions", + "", + ] + lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(preconditions.items())) + lines.extend(["", "## Approval Gate Readback", ""]) + lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(binding["approval_gate"].items())) + lines.extend( + [ + "", + "## Exact Action-Time Authorization Text", + "", + "This text is not actionable until every production precondition above is true.", + "", + packet["authorization_text_template"], + "", + "## Current Gate", + "", + packet["next_exact_action"], + "", + "The production approval-gate deployment is explicitly outside this apply packet and requires separate authorization.", + "", + "## Claim Ceiling", + "", + packet["claim_ceiling"], + "", + ] + ) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("\n".join(lines), encoding="utf-8") + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + sub = parser.add_subparsers(dest="command", required=True) + packet = sub.add_parser("build-authorization-packet") + packet.add_argument("--lifecycle-receipt", required=True, type=Path) + packet.add_argument("--destination-readback", required=True, type=Path) + packet.add_argument("--apply-engine", type=Path, default=HERE / "apply_proposal.py") + packet.add_argument("--approval-gate", type=Path, default=HERE / "kb_apply_prereqs.sql") + packet.add_argument("--production-rollback-artifact", type=Path) + packet.add_argument("--repo-git-sha") + packet.add_argument("--out", required=True, type=Path) + packet.add_argument("--markdown-out", type=Path) + verify = sub.add_parser("verify-authorization") + verify.add_argument("--packet", required=True, type=Path) + verify.add_argument("--record", required=True, type=Path) + verify.add_argument("--observed-destination", required=True, type=Path) + verify.add_argument("--apply-engine", type=Path, default=HERE / "apply_proposal.py") + verify.add_argument("--approval-gate", type=Path, default=HERE / "kb_apply_prereqs.sql") + verify.add_argument("--production-rollback-artifact", type=Path) + verify.add_argument("--out", required=True, type=Path) + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + if args.command == "build-authorization-packet": + raw = _load_json(args.lifecycle_receipt) + lifecycle = raw.get("applied_rollback_receipt", raw) + destination = _load_json(args.destination_readback) + packet = build_authorization_packet( + lifecycle, + destination, + repo_git_sha=args.repo_git_sha or current_git_sha(HERE.parent), + apply_engine_path=args.apply_engine, + approval_gate_path=args.approval_gate, + production_rollback_artifact=( + _load_json(args.production_rollback_artifact) if args.production_rollback_artifact else None + ), + ) + _write_json(args.out, packet) + if args.markdown_out: + write_authorization_markdown(args.markdown_out, packet) + print(json.dumps({"out": str(args.out), "safe_to_enter_apply_window": False}, sort_keys=True)) + return 0 + packet = _load_json(args.packet) + record = _load_json(args.record) + destination = _load_json(args.observed_destination) + result = verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=args.apply_engine, + approval_gate_path=args.approval_gate, + production_rollback_artifact=( + _load_json(args.production_rollback_artifact) if args.production_rollback_artifact else None + ), + ) + _write_json(args.out, result) + print(json.dumps(result, sort_keys=True)) + return 0 if result["safe_to_enter_apply_window"] else 2 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/run_approve_claim_clone_canary.py b/scripts/run_approve_claim_clone_canary.py index 6985401..87c4de2 100644 --- a/scripts/run_approve_claim_clone_canary.py +++ b/scripts/run_approve_claim_clone_canary.py @@ -18,6 +18,7 @@ import re import shutil import subprocess import sys +import tempfile import uuid from datetime import datetime, timezone from pathlib import Path @@ -28,13 +29,12 @@ REPO_ROOT = HERE.parent sys.path.insert(0, str(HERE)) import apply_proposal as ap # noqa: E402 +import proposal_apply_lifecycle as lifecycle # noqa: E402 SAFE_DB_RE = re.compile(r"^[a-z][a-z0-9_]{1,62}$") REVIEWER_HANDLE = "m3ta" REVIEW_NOTE = "Reviewed exact strict payload inside the disposable clone." -DEFAULT_REVIEW_SECRETS_FILE = ( - "/home/teleo/.hermes/profiles/leoclean/secrets/kb-review.env" -) +DEFAULT_REVIEW_SECRETS_FILE = "/home/teleo/.hermes/profiles/leoclean/secrets/kb-review.env" SECURITY_DEFINER_DEPENDENCIES = { "approve_strict_proposal": "kb_review", "assert_approved_proposal": "kb_apply", @@ -98,8 +98,10 @@ def _source_file_manifest(args: argparse.Namespace) -> list[dict[str, Any]]: paths = { Path(__file__).resolve(), (HERE / "run_approve_claim_isolated_container_canary.sh").resolve(), + (HERE / "finalize_approve_claim_isolated_canary.py").resolve(), Path(args.approve_script).resolve(), Path(args.apply_script).resolve(), + (HERE / "proposal_apply_lifecycle.py").resolve(), Path(args.prereqs).resolve(), } return sorted( @@ -190,9 +192,7 @@ def _schema_copy(container: str, source_db: str, clone_db: str) -> None: "ON_ERROR_STOP=1", "-q", ] - dump = subprocess.Popen( - dump_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True - ) + dump = subprocess.Popen(dump_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) assert dump.stdout is not None assert dump.stderr is not None restore = subprocess.run( @@ -319,37 +319,22 @@ def _cluster_roles_are_preprovisioned(rows: list[dict[str, Any]]) -> bool: def _clone_prerequisites_sql(prereqs: str) -> tuple[str, dict[str, Any]]: """Remove cluster-global role DDL while preserving clone-local objects/ACLs.""" start_marker = "do $roles$" - end_marker = ( - "alter role kb_apply login noinherit nosuperuser nocreatedb nocreaterole " - "noreplication nobypassrls;" - ) + end_marker = "alter role kb_apply login noinherit nosuperuser nocreatedb nocreaterole noreplication nobypassrls;" start = prereqs.lower().find(start_marker) end_start = prereqs.lower().find(end_marker, start) if start < 0 or end_start < 0: - raise RuntimeError( - "prerequisites role bootstrap block changed; refusing unsafe clone execution" - ) + raise RuntimeError("prerequisites role bootstrap block changed; refusing unsafe clone execution") end = end_start + len(end_marker) removed = prereqs[start:end] - sanitized = ( - prereqs[:start] - + "-- Cluster-global role DDL omitted by disposable clone canary.\n" - + prereqs[end:] - ) + sanitized = prereqs[:start] + "-- Cluster-global role DDL omitted by disposable clone canary.\n" + prereqs[end:] if re.search(r"\b(?:create|alter|drop)\s+role\b", sanitized, re.IGNORECASE): - raise RuntimeError( - "prerequisites still contain cluster-global role DDL after sanitization" - ) + raise RuntimeError("prerequisites still contain cluster-global role DDL after sanitization") return sanitized, { "source_sha256": hashlib.sha256(prereqs.encode()).hexdigest(), "clone_sql_sha256": hashlib.sha256(sanitized.encode()).hexdigest(), "cluster_role_ddl_removed": True, - "removed_create_role_statements": len( - re.findall(r"\bcreate\s+role\b", removed, re.IGNORECASE) - ), - "removed_alter_role_statements": len( - re.findall(r"\balter\s+role\b", removed, re.IGNORECASE) - ), + "removed_create_role_statements": len(re.findall(r"\bcreate\s+role\b", removed, re.IGNORECASE)), + "removed_alter_role_statements": len(re.findall(r"\balter\s+role\b", removed, re.IGNORECASE)), } @@ -460,9 +445,7 @@ def load_normalized_fixture(path: Path, namespace: str) -> dict[str, Any]: data = json.loads(path.read_text(encoding="utf-8")) previews = data.get("normalization_previews") if isinstance(data, dict) else None if not isinstance(previews, list) or len(previews) != 1: - raise ValueError( - "normalization JSON must contain exactly one normalization_previews row" - ) + raise ValueError("normalization JSON must contain exactly one normalization_previews row") preview = previews[0] children = preview.get("strict_child_proposals") if ( @@ -472,9 +455,7 @@ def load_normalized_fixture(path: Path, namespace: str) -> dict[str, Any]: or len(children) != 1 or children[0].get("proposal_type") != "approve_claim" ): - raise ValueError( - "normalization JSON is not one unblocked strict approve_claim child" - ) + raise ValueError("normalization JSON is not one unblocked strict approve_claim child") apply_payload = (children[0].get("payload") or {}).get("apply_payload") if not isinstance(apply_payload, dict): raise ValueError("strict approve_claim child has no apply_payload") @@ -527,9 +508,7 @@ def _payload_agent_ids(payload: dict[str, Any]) -> list[str]: return sorted(values) -def _seed_payload_agents( - container: str, source_db: str, clone_db: str, payload: dict[str, Any] -) -> dict[str, Any]: +def _seed_payload_agents(container: str, source_db: str, clone_db: str, payload: dict[str, Any]) -> dict[str, Any]: required_ids = _payload_agent_ids(payload) if not required_ids: return { @@ -538,9 +517,7 @@ def _seed_payload_agents( "clone_rows": [], "exact_clone_copy": True, } - id_sql = ", ".join( - f"{ap.sql_literal(value)}::uuid" for value in required_ids - ) + id_sql = ", ".join(f"{ap.sql_literal(value)}::uuid" for value in required_ids) source_raw = _psql( container, source_db, @@ -560,8 +537,8 @@ rollback; statements = [ f"""insert into public.agents (id, handle, kind) -values ({ap.sql_literal(row['id'])}::uuid, {ap.sql_literal(row['handle'])}, - {ap.sql_literal(row['kind'])}) +values ({ap.sql_literal(row["id"])}::uuid, {ap.sql_literal(row["handle"])}, + {ap.sql_literal(row["kind"])}) on conflict (id) do nothing;""" for row in source_rows ] @@ -604,16 +581,14 @@ rollback; ) source_row = json.loads(raw) if not source_row: - raise RuntimeError( - f"reviewer principal dependency is missing from source agents: {reviewer_handle}" - ) + raise RuntimeError(f"reviewer principal dependency is missing from source agents: {reviewer_handle}") _psql( container, clone_db, f"""insert into public.agents (id, handle, kind) -values ({ap.sql_literal(source_row['id'])}::uuid, - {ap.sql_literal(source_row['handle'])}, - {ap.sql_literal(source_row['kind'])});""", +values ({ap.sql_literal(source_row["id"])}::uuid, + {ap.sql_literal(source_row["handle"])}, + {ap.sql_literal(source_row["kind"])});""", tuples=False, ) clone_raw = _psql( @@ -635,9 +610,7 @@ from public.agents where handle = {ap.sql_literal(reviewer_handle)};""", } -def _seed_external_claims( - container: str, source_db: str, clone_db: str, payload: dict[str, Any] -) -> dict[str, Any]: +def _seed_external_claims(container: str, source_db: str, clone_db: str, payload: dict[str, Any]) -> dict[str, Any]: external_ids = _external_claim_ids(payload) if not external_ids: return { @@ -646,9 +619,7 @@ def _seed_external_claims( "clone_rows": [], "exact_clone_copy": True, } - id_sql = ", ".join( - f"{ap.sql_literal(value)}::uuid" for value in external_ids - ) + id_sql = ", ".join(f"{ap.sql_literal(value)}::uuid" for value in external_ids) raw = _psql( container, source_db, @@ -666,28 +637,22 @@ rollback; found = {row["id"] for row in rows} missing = sorted(set(external_ids) - found) if missing: - raise RuntimeError( - f"normalized bundle references missing source claims: {missing}" - ) + raise RuntimeError(f"normalized bundle references missing source claims: {missing}") statements = [] for row in rows: tags = row.get("tags") or [] tags_sql = ( - "'{}'::text[]" - if not tags - else "array[" - + ", ".join(ap.sql_literal(tag) for tag in tags) - + "]::text[]" + "'{}'::text[]" if not tags else "array[" + ", ".join(ap.sql_literal(tag) for tag in tags) + "]::text[]" ) statements.append( f"""insert into public.claims (id, type, text, status, confidence, tags, created_by, superseded_by) values - ({ap.sql_literal(row['id'])}::uuid, {ap.sql_literal(row['type'])}, - {ap.sql_literal(row['text'])}, {ap.sql_literal(row['status'])}, - {ap.sql_literal(row.get('confidence'))}, {tags_sql}, - {ap.sql_literal(row.get('created_by'))}::uuid, - {ap.sql_literal(row.get('superseded_by'))}::uuid);""" + ({ap.sql_literal(row["id"])}::uuid, {ap.sql_literal(row["type"])}, + {ap.sql_literal(row["text"])}, {ap.sql_literal(row["status"])}, + {ap.sql_literal(row.get("confidence"))}, {tags_sql}, + {ap.sql_literal(row.get("created_by"))}::uuid, + {ap.sql_literal(row.get("superseded_by"))}::uuid);""" ) _psql(container, clone_db, "\n".join(statements), tuples=False) clone_raw = _psql( @@ -712,9 +677,7 @@ from public.claims where id in ({id_sql});""", def _id_predicate(column: str, values: list[str]) -> str: if not values: return "false" - return f"{column} in (" + ", ".join( - f"{ap.sql_literal(value)}::uuid" for value in values - ) + ")" + return f"{column} in (" + ", ".join(f"{ap.sql_literal(value)}::uuid" for value in values) + ")" def _key_predicate(rows: list[dict[str, Any]], fields: list[tuple[str, str]]) -> str: @@ -829,8 +792,7 @@ def _expected_table_deltas( def _table_deltas(before: dict[str, int], after: dict[str, int]) -> dict[str, int]: if set(before) != set(after): raise ValueError( - "cannot compare table counts with different keys: " - f"before={sorted(before)} after={sorted(after)}" + f"cannot compare table counts with different keys: before={sorted(before)} after={sorted(after)}" ) return {key: after[key] - before[key] for key in sorted(before)} @@ -862,9 +824,7 @@ def _canonical_row_keys(rows: dict[str, list[dict[str, Any]]]) -> dict[str, Any] ], key=lambda row: (row["from_claim"], row["to_claim"], row["edge_type"]), ), - "public.reasoning_tools": sorted( - row["id"] for row in rows.get("reasoning_tools", []) - ), + "public.reasoning_tools": sorted(row["id"] for row in rows.get("reasoning_tools", [])), } @@ -879,8 +839,7 @@ def _strict_receipt( expected_keys = _canonical_row_keys(expected_rows) actual_keys = _canonical_row_keys(actual_rows) checks = { - "proposal_id_exact": applied.get("id") - == result.get("fixture_ids", {}).get("proposal_id"), + "proposal_id_exact": applied.get("id") == result.get("fixture_ids", {}).get("proposal_id"), "proposal_status_applied": applied.get("status") == "applied", "proposal_applied_at_present": bool(applied.get("applied_at")), "canonical_rows_exact": actual_rows == expected_rows, @@ -889,18 +848,12 @@ def _strict_receipt( isinstance(result.get("clone_counts_before_apply"), dict) and isinstance(result.get("clone_counts_after_apply"), dict) ), - "table_deltas_exact": result.get("clone_apply_table_deltas") - == expected_table_deltas, - "conflict_transaction_rolled_back": result.get("checks", {}).get( - "conflict_transaction_rolled_back_exactly" - ) + "table_deltas_exact": result.get("clone_apply_table_deltas") == expected_table_deltas, + "conflict_transaction_rolled_back": result.get("checks", {}).get("conflict_transaction_rolled_back_exactly") is True, "clone_database_removed": ( result.get("clone_dropped") is True - and result.get("cleanup_readback", {}).get( - "leftover_clone_database_count" - ) - == 0 + and result.get("cleanup_readback", {}).get("leftover_clone_database_count") == 0 ), "source_database_unchanged": result.get("source_database_mutated") is False, } @@ -925,28 +878,18 @@ def _strict_receipt( "actual_deltas": result.get("clone_apply_table_deltas"), }, "rollback_cleanup": { - "conflict_transaction_rolled_back": checks[ - "conflict_transaction_rolled_back" - ], + "conflict_transaction_rolled_back": checks["conflict_transaction_rolled_back"], "clone_database_removed": checks["clone_database_removed"], - "leftover_clone_database_count": result.get("cleanup_readback", {}).get( - "leftover_clone_database_count" - ), + "leftover_clone_database_count": result.get("cleanup_readback", {}).get("leftover_clone_database_count"), "source_database_unchanged": checks["source_database_unchanged"], }, } -def _exact_bundle_readback( - container: str, database: str, payload: dict[str, Any] -) -> dict[str, list[dict[str, Any]]]: +def _exact_bundle_readback(container: str, database: str, payload: dict[str, Any]) -> dict[str, list[dict[str, Any]]]: expected = _expected_bundle_rows(payload) - claim_predicate = _id_predicate( - "id", [row["id"] for row in expected["claims"]] - ) - source_predicate = _id_predicate( - "id", [row["id"] for row in expected["sources"]] - ) + claim_predicate = _id_predicate("id", [row["id"] for row in expected["claims"]]) + source_predicate = _id_predicate("id", [row["id"] for row in expected["sources"]]) evidence_predicate = _key_predicate( expected["claim_evidence"], [("claim_id", "uuid"), ("source_id", "uuid"), ("role", "text")], @@ -959,9 +902,7 @@ def _exact_bundle_readback( ("edge_type", "text"), ], ) - tool_predicate = _id_predicate( - "id", [row["id"] for row in expected["reasoning_tools"]] - ) + tool_predicate = _id_predicate("id", [row["id"] for row in expected["reasoning_tools"]]) raw = _psql( container, database, @@ -1001,9 +942,53 @@ rollback; return json.loads(raw) -def _proposal_readback( - container: str, database: str, proposal_id: str -) -> dict[str, Any] | None: +def _unrelated_state_fingerprint( + container: str, + database: str, + payload: dict[str, Any], + proposal_id: str, +) -> dict[str, Any]: + """Hash every potentially adjacent row while excluding proposal-owned rows.""" + expected = _expected_bundle_rows(payload) + claim_predicate = _id_predicate("id", [row["id"] for row in expected["claims"]]) + source_predicate = _id_predicate("id", [row["id"] for row in expected["sources"]]) + evidence_predicate = _key_predicate( + expected["claim_evidence"], + [("claim_id", "uuid"), ("source_id", "uuid"), ("role", "text")], + ) + edge_predicate = _key_predicate( + expected["claim_edges"], + [("from_claim", "uuid"), ("to_claim", "uuid"), ("edge_type", "text")], + ) + tool_predicate = _id_predicate("id", [row["id"] for row in expected["reasoning_tools"]]) + + def fingerprint(table: str, alias: str, where: str, order: str) -> str: + return f"""(select json_build_object( + 'row_count', count(*), + 'content_md5', md5(coalesce(string_agg(to_jsonb({alias})::text, '|' order by {order}), '')) + ) from {table} {alias} where {where})""" + + raw = _psql( + container, + database, + f"""begin transaction read only; +select json_build_object( + 'public.agents', {fingerprint("public.agents", "a", "true", "a.id::text")}, + 'public.claims', {fingerprint("public.claims", "c", f"not ({claim_predicate})", "c.id::text")}, + 'public.sources', {fingerprint("public.sources", "s", f"not ({source_predicate})", "s.id::text")}, + 'public.claim_evidence', {fingerprint("public.claim_evidence", "ce", f"not ({evidence_predicate})", "ce.id::text")}, + 'public.claim_edges', {fingerprint("public.claim_edges", "e", f"not ({edge_predicate})", "e.id::text")}, + 'public.reasoning_tools', {fingerprint("public.reasoning_tools", "rt", f"not ({tool_predicate})", "rt.id::text")}, + 'kb_stage.kb_proposals', {fingerprint("kb_stage.kb_proposals", "p", f"p.id <> {ap.sql_literal(proposal_id)}::uuid", "p.id::text")}, + 'kb_stage.kb_proposal_approvals', {fingerprint("kb_stage.kb_proposal_approvals", "pa", f"pa.proposal_id <> {ap.sql_literal(proposal_id)}::uuid", "pa.proposal_id::text")} +)::text; +rollback; +""", + ) + return json.loads(raw) + + +def _proposal_readback(container: str, database: str, proposal_id: str) -> dict[str, Any] | None: raw = _psql( container, database, @@ -1031,9 +1016,7 @@ rollback; return json.loads(raw) -def _approval_snapshot_readback( - container: str, database: str, proposal_id: str -) -> dict[str, Any] | None: +def _approval_snapshot_readback(container: str, database: str, proposal_id: str) -> dict[str, Any] | None: raw = _psql( container, database, @@ -1069,7 +1052,7 @@ values ({ap.sql_literal(proposal_id)}::uuid, 'approve_claim', 'pending_review', 'clone_canary', {ap.sql_literal(source_ref)}, 'Exercise strict canonical bundle review and apply lifecycle.', - {ap.sql_literal(json.dumps({'apply_payload': payload}, sort_keys=True))}::jsonb); + {ap.sql_literal(json.dumps({"apply_payload": payload}, sort_keys=True))}::jsonb); """ _psql(container, database, sql) @@ -1111,6 +1094,7 @@ def _apply( database: str, *, dry_run: bool = False, + receipt_out: Path | None = None, ) -> subprocess.CompletedProcess[str]: command = [ sys.executable, @@ -1129,15 +1113,37 @@ def _apply( "--role", args.apply_role, ] + if receipt_out is not None: + command.extend(["--receipt-out", str(receipt_out)]) if dry_run: command.append("--dry-run") return _run(command, check=False) +def _apply_command_readback( + result: subprocess.CompletedProcess[str], +) -> dict[str, Any]: + """Keep the public report useful without leaking a private receipt path.""" + readback: dict[str, Any] = { + "returncode": result.returncode, + "stderr": result.stderr.strip(), + } + try: + summary = json.loads(result.stdout) + except json.JSONDecodeError: + readback["stdout"] = result.stdout.strip() + else: + if isinstance(summary, dict): + summary.pop("receipt_path", None) + readback["result"] = summary + else: + readback["stdout"] = result.stdout.strip() + return readback + + def _security_definer_readback(container: str, database: str) -> dict[str, Any]: expected_values = ",\n".join( - f"({ap.sql_literal(name)}, {ap.sql_literal(role)}, " - f"{ap.sql_literal(SECURITY_DEFINER_ARGUMENT_TYPES[name])})" + f"({ap.sql_literal(name)}, {ap.sql_literal(role)}, {ap.sql_literal(SECURITY_DEFINER_ARGUMENT_TYPES[name])})" for name, role in SECURITY_DEFINER_DEPENDENCIES.items() ) raw = _psql( @@ -1270,8 +1276,7 @@ def _security_dependencies_ready(readback: dict[str, Any]) -> bool: functions = readback.get("functions") or [] functions_ready = len(functions) == len(SECURITY_DEFINER_DEPENDENCIES) and all( row.get("present") is True - and row.get("argument_types") - == SECURITY_DEFINER_ARGUMENT_TYPES[row["function"].removeprefix("kb_stage.")] + and row.get("argument_types") == SECURITY_DEFINER_ARGUMENT_TYPES[row["function"].removeprefix("kb_stage.")] and row.get("security_definer") is True and row.get("expected_role_execute") is True and row.get("other_runtime_role_execute") is False @@ -1285,23 +1290,26 @@ def _security_dependencies_ready(readback: dict[str, Any]) -> bool: and readback.get("protected_role_memberships") == [] and readback.get("login_role_owned_objects") == [] ) - return functions_ready and catalog_ready and privileges == { - "kb_review_proposal_select": True, - "kb_review_proposal_update": False, - "kb_apply_proposal_select": True, - "kb_apply_proposal_update": False, - "kb_apply_claim_evidence_insert": True, - "kb_apply_claim_evidence_update": False, - "kb_review_approval_snapshot_select": False, - "kb_review_approval_snapshot_update": False, - "kb_apply_approval_snapshot_select": False, - "kb_apply_approval_snapshot_update": False, - } + return ( + functions_ready + and catalog_ready + and privileges + == { + "kb_review_proposal_select": True, + "kb_review_proposal_update": False, + "kb_apply_proposal_select": True, + "kb_apply_proposal_update": False, + "kb_apply_claim_evidence_insert": True, + "kb_apply_claim_evidence_update": False, + "kb_review_approval_snapshot_select": False, + "kb_review_approval_snapshot_update": False, + "kb_apply_approval_snapshot_select": False, + "kb_apply_approval_snapshot_update": False, + } + ) -def _approval_transition_valid( - pending: dict[str, Any] | None, approved: dict[str, Any] | None -) -> bool: +def _approval_transition_valid(pending: dict[str, Any] | None, approved: dict[str, Any] | None) -> bool: if not pending or not approved: return False immutable = [ @@ -1337,9 +1345,7 @@ def _approval_transition_valid( ) -def _apply_transition_valid( - approved: dict[str, Any] | None, applied: dict[str, Any] | None -) -> bool: +def _apply_transition_valid(approved: dict[str, Any] | None, applied: dict[str, Any] | None) -> bool: if not approved or not applied: return False preserved = [ @@ -1382,9 +1388,7 @@ def _approval_snapshot_matches( } -def _seed_evidence_permission_probe( - container: str, database: str, fixture: dict[str, Any] -) -> None: +def _seed_evidence_permission_probe(container: str, database: str, fixture: dict[str, Any]) -> None: source_hash = f"approve-claim-permission-probe-{fixture['permission_source_id']}" _psql( container, @@ -1392,20 +1396,20 @@ def _seed_evidence_permission_probe( f"""insert into public.claims (id, type, text, status, confidence, tags, created_by, superseded_by) values - ({ap.sql_literal(fixture['permission_claim_id'])}::uuid, 'structural', + ({ap.sql_literal(fixture["permission_claim_id"])}::uuid, 'structural', 'Existing claim_evidence permission probe.', 'open', 0.42, array['clone-canary-permission-probe']::text[], null, null); insert into public.sources (id, source_type, url, storage_path, excerpt, hash, created_by) values - ({ap.sql_literal(fixture['permission_source_id'])}::uuid, 'observation', null, + ({ap.sql_literal(fixture["permission_source_id"])}::uuid, 'observation', null, null, 'Existing claim_evidence permission probe source.', {ap.sql_literal(source_hash)}, null); insert into public.claim_evidence (claim_id, source_id, role, weight, created_by) values - ({ap.sql_literal(fixture['permission_claim_id'])}::uuid, - {ap.sql_literal(fixture['permission_source_id'])}::uuid, + ({ap.sql_literal(fixture["permission_claim_id"])}::uuid, + {ap.sql_literal(fixture["permission_source_id"])}::uuid, 'grounds', 0.42, null); """, tuples=False, @@ -1426,8 +1430,8 @@ select coalesce((select json_build_object( 'weight', weight, 'created_by', created_by::text ) from public.claim_evidence -where claim_id = {ap.sql_literal(fixture['permission_claim_id'])}::uuid - and source_id = {ap.sql_literal(fixture['permission_source_id'])}::uuid +where claim_id = {ap.sql_literal(fixture["permission_claim_id"])}::uuid + and source_id = {ap.sql_literal(fixture["permission_source_id"])}::uuid and role = 'grounds'), 'null'::json)::text; rollback; """, @@ -1482,10 +1486,7 @@ def _conflict_payload(fixture: dict[str, Any]) -> dict[str, Any]: "url": None, "storage_path": None, "excerpt": "Conflicting source id.", - "hash": ( - f"approve-claim-permission-probe-" - f"{fixture['permission_source_id']}" - ), + "hash": (f"approve-claim-permission-probe-{fixture['permission_source_id']}"), "created_by": None, } ], @@ -1497,18 +1498,14 @@ def _conflict_payload(fixture: dict[str, Any]) -> dict[str, Any]: def run_canary(args: argparse.Namespace) -> dict[str, Any]: if args.review_role != "kb_review" or args.apply_role != "kb_apply": - raise ValueError( - "the canary is pinned to the intended kb_review/kb_apply authority split" - ) + raise ValueError("the canary is pinned to the intended kb_review/kb_apply authority split") suffix = uuid.uuid4().hex[:10] clone_db = f"{args.database_prefix}_{suffix}" if not SAFE_DB_RE.match(clone_db): raise ValueError(f"unsafe generated database name: {clone_db}") fixture = ( - load_normalized_fixture(args.normalization_json, suffix) - if args.normalization_json - else build_fixture(suffix) + load_normalized_fixture(args.normalization_json, suffix) if args.normalization_json else build_fixture(suffix) ) payload = fixture["apply_payload"] expected_rows = _expected_bundle_rows(payload) @@ -1526,33 +1523,19 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "service_restarted": False, "clone_created": False, "clone_dropped": False, - "fixture_ids": { - key: value for key, value in fixture.items() if key != "apply_payload" - }, + "fixture_ids": {key: value for key, value in fixture.items() if key != "apply_payload"}, "dependencies": { - "approve_script": Path(args.approve_script) - .resolve() - .relative_to(REPO_ROOT.resolve()) - .as_posix(), - "apply_script": Path(args.apply_script) - .resolve() - .relative_to(REPO_ROOT.resolve()) - .as_posix(), - "prerequisites_sql": Path(args.prereqs) - .resolve() - .relative_to(REPO_ROOT.resolve()) - .as_posix(), + "approve_script": Path(args.approve_script).resolve().relative_to(REPO_ROOT.resolve()).as_posix(), + "apply_script": Path(args.apply_script).resolve().relative_to(REPO_ROOT.resolve()).as_posix(), + "prerequisites_sql": Path(args.prereqs).resolve().relative_to(REPO_ROOT.resolve()).as_posix(), "review_role": args.review_role, "apply_role": args.apply_role, "gate_owner_role": "kb_gate_owner", "reviewer_handle": REVIEWER_HANDLE, "immutable_approval_table": "kb_stage.kb_proposal_approvals", - "security_definer_functions": [ - f"kb_stage.{name}" for name in SECURITY_DEFINER_DEPENDENCIES - ], + "security_definer_functions": [f"kb_stage.{name}" for name in SECURITY_DEFINER_DEPENDENCIES], "security_definer_argument_types": { - f"kb_stage.{name}": argument_types - for name, argument_types in SECURITY_DEFINER_ARGUMENT_TYPES.items() + f"kb_stage.{name}": argument_types for name, argument_types in SECURITY_DEFINER_ARGUMENT_TYPES.items() }, "credential_files": { "review": { @@ -1579,15 +1562,9 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: } try: result["service_before"] = _service_state(args.service) - result["source_counts_before"] = _base_counts( - args.container, args.source_db - ) - result["source_cluster_roles_before"] = _cluster_role_readback( - args.container, args.source_db - ) - if not _cluster_roles_are_preprovisioned( - result["source_cluster_roles_before"] - ): + result["source_counts_before"] = _base_counts(args.container, args.source_db) + result["source_cluster_roles_before"] = _cluster_role_readback(args.container, args.source_db) + if not _cluster_roles_are_preprovisioned(result["source_cluster_roles_before"]): raise RuntimeError( "refusing clone prerequisites until kb_apply, kb_review, and " "NOLOGIN kb_gate_owner are pre-provisioned without elevated attributes" @@ -1598,13 +1575,8 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: if not readback["present_at_start"] ] if missing_credentials: - raise RuntimeError( - "required separated credential file(s) are absent: " - + ", ".join(missing_credentials) - ) - result["source_target_rows_before"] = _exact_bundle_readback( - args.container, args.source_db, payload - ) + raise RuntimeError("required separated credential file(s) are absent: " + ", ".join(missing_credentials)) + result["source_target_rows_before"] = _exact_bundle_readback(args.container, args.source_db, payload) prereqs = Path(args.prereqs).read_text(encoding="utf-8") clone_prereqs, prereq_sanitization = _clone_prerequisites_sql(prereqs) result["clone_prerequisite_sanitization"] = prereq_sanitization @@ -1620,19 +1592,11 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: ) _psql(args.container, clone_db, clone_prereqs, tuples=False) - result["security_definer_readback"] = _security_definer_readback( - args.container, clone_db - ) - result["payload_agent_seed"] = _seed_payload_agents( - args.container, args.source_db, clone_db, payload - ) - result["external_claim_seed"] = _seed_external_claims( - args.container, args.source_db, clone_db, payload - ) + result["security_definer_readback"] = _security_definer_readback(args.container, clone_db) + result["payload_agent_seed"] = _seed_payload_agents(args.container, args.source_db, clone_db, payload) + result["external_claim_seed"] = _seed_external_claims(args.container, args.source_db, clone_db, payload) _seed_evidence_permission_probe(args.container, clone_db, fixture) - evidence_before = _evidence_permission_probe_readback( - args.container, clone_db, fixture - ) + evidence_before = _evidence_permission_probe_readback(args.container, clone_db, fixture) apply_password = ap.load_password(args.secrets_file) evidence_update = _permission_probe( @@ -1640,15 +1604,13 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: clone_db, f"""update public.claim_evidence set weight = 0.99 - where claim_id = {ap.sql_literal(fixture['permission_claim_id'])}::uuid - and source_id = {ap.sql_literal(fixture['permission_source_id'])}::uuid + where claim_id = {ap.sql_literal(fixture["permission_claim_id"])}::uuid + and source_id = {ap.sql_literal(fixture["permission_source_id"])}::uuid and role = 'grounds';""", role=args.apply_role, password=apply_password, ) - evidence_after = _evidence_permission_probe_readback( - args.container, clone_db, fixture - ) + evidence_after = _evidence_permission_probe_readback(args.container, clone_db, fixture) result["kb_apply_claim_evidence_update_probe"] = { "before": evidence_before, "attempt": evidence_update, @@ -1663,41 +1625,25 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: payload, source_ref="working-leo:approve-claim-clone-canary", ) - pending_proposal = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - pending_approval_snapshot = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) - review_dry_run = _approve( - args, fixture["proposal_id"], clone_db, dry_run=True - ) + pending_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + pending_approval_snapshot = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) + review_dry_run = _approve(args, fixture["proposal_id"], clone_db, dry_run=True) review_apply = _approve(args, fixture["proposal_id"], clone_db) - approved_proposal = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - approved_snapshot = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + approved_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + approved_snapshot = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) result["review_transition"] = { "pending_readback": pending_proposal, "pending_immutable_approval": pending_approval_snapshot, "review_dry_run": { "returncode": review_dry_run.returncode, - "uses_approve_strict_proposal": ( - "kb_stage.approve_strict_proposal" in review_dry_run.stdout - ), + "uses_approve_strict_proposal": ("kb_stage.approve_strict_proposal" in review_dry_run.stdout), "stderr": review_dry_run.stderr.strip(), }, "review_apply": _command_readback(review_apply), "approved_readback": approved_proposal, "immutable_approval_readback": approved_snapshot, - "immutable_approval_matches_ledger": _approval_snapshot_matches( - approved_proposal, approved_snapshot - ), - "exact_transition": _approval_transition_valid( - pending_proposal, approved_proposal - ), + "immutable_approval_matches_ledger": _approval_snapshot_matches(approved_proposal, approved_snapshot), + "exact_transition": _approval_transition_valid(pending_proposal, approved_proposal), } approval_update = _permission_probe( @@ -1705,7 +1651,7 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: clone_db, f"""update kb_stage.kb_proposals set status = 'pending_review', review_note = 'kb_apply direct mutation probe' - where id = {ap.sql_literal(fixture['proposal_id'])}::uuid;""", + where id = {ap.sql_literal(fixture["proposal_id"])}::uuid;""", role=args.apply_role, password=apply_password, ) @@ -1714,7 +1660,7 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: clone_db, f"""update kb_stage.kb_proposals set payload = payload || '{{"kb_apply_direct_mutation_probe": true}}'::jsonb - where id = {ap.sql_literal(fixture['proposal_id'])}::uuid;""", + where id = {ap.sql_literal(fixture["proposal_id"])}::uuid;""", role=args.apply_role, password=apply_password, ) @@ -1723,16 +1669,12 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: clone_db, f"""update kb_stage.kb_proposal_approvals set payload = payload || '{{"kb_apply_direct_mutation_probe": true}}'::jsonb - where proposal_id = {ap.sql_literal(fixture['proposal_id'])}::uuid;""", + where proposal_id = {ap.sql_literal(fixture["proposal_id"])}::uuid;""", role=args.apply_role, password=apply_password, ) - proposal_after_permission_probes = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - snapshot_after_permission_probes = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + proposal_after_permission_probes = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + snapshot_after_permission_probes = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) result["kb_apply_proposal_mutation_probes"] = { "approval_fields": approval_update, "payload": payload_update, @@ -1741,36 +1683,25 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "after": proposal_after_permission_probes, "immutable_approval_before": approved_snapshot, "immutable_approval_after": snapshot_after_permission_probes, - "exact_row_unchanged": ( - approved_proposal == proposal_after_permission_probes - ), - "immutable_approval_exactly_unchanged": ( - approved_snapshot == snapshot_after_permission_probes - ), + "exact_row_unchanged": (approved_proposal == proposal_after_permission_probes), + "immutable_approval_exactly_unchanged": (approved_snapshot == snapshot_after_permission_probes), } built_apply = _apply(args, fixture["proposal_id"], clone_db, dry_run=True) built_sql = built_apply.stdout if built_apply.returncode != 0 or not built_sql.strip(): - raise RuntimeError( - "failed to build apply SQL before mutation: " - f"{built_apply.stderr.strip()}" - ) + raise RuntimeError(f"failed to build apply SQL before mutation: {built_apply.stderr.strip()}") _psql( args.container, clone_db, f"""update kb_stage.kb_proposals set payload = payload || '{{"mutation_after_build": true}}'::jsonb, updated_at = now() - where id = {ap.sql_literal(fixture['proposal_id'])}::uuid;""", + where id = {ap.sql_literal(fixture["proposal_id"])}::uuid;""", tuples=False, ) - proposal_after_mutation = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - snapshot_after_ledger_mutation = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + proposal_after_mutation = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + snapshot_after_ledger_mutation = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) stale_execute = _role_psql( args.container, clone_db, @@ -1778,58 +1709,38 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: role=args.apply_role, password=apply_password, ) - rows_after_stale_execute = _exact_bundle_readback( - args.container, clone_db, payload - ) - proposal_after_stale_execute = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - snapshot_after_stale_execute = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + rows_after_stale_execute = _exact_bundle_readback(args.container, clone_db, payload) + proposal_after_stale_execute = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + snapshot_after_stale_execute = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) assert approved_proposal is not None _psql( args.container, clone_db, f"""update kb_stage.kb_proposals - set payload = {ap.sql_literal(json.dumps(approved_proposal['payload'], sort_keys=True))}::jsonb, + set payload = {ap.sql_literal(json.dumps(approved_proposal["payload"], sort_keys=True))}::jsonb, updated_at = now() - where id = {ap.sql_literal(fixture['proposal_id'])}::uuid;""", + where id = {ap.sql_literal(fixture["proposal_id"])}::uuid;""", tuples=False, ) - restored_proposal = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - restored_snapshot = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + restored_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + restored_snapshot = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) result["mutation_between_build_and_execute"] = { "build_returncode": built_apply.returncode, "built_sql_sha256": hashlib.sha256(built_sql.encode()).hexdigest(), - "built_sql_uses_assert_approved_proposal": ( - "kb_stage.assert_approved_proposal" in built_sql - ), - "built_sql_uses_finish_approved_proposal": ( - "kb_stage.finish_approved_proposal" in built_sql - ), + "built_sql_uses_assert_approved_proposal": ("kb_stage.assert_approved_proposal" in built_sql), + "built_sql_uses_finish_approved_proposal": ("kb_stage.finish_approved_proposal" in built_sql), "approved_before_mutation": approved_proposal, "immutable_approval_before_mutation": approved_snapshot, "mutated_readback": proposal_after_mutation, - "immutable_approval_after_ledger_mutation": ( - snapshot_after_ledger_mutation - ), + "immutable_approval_after_ledger_mutation": (snapshot_after_ledger_mutation), "stale_execute": _command_readback(stale_execute), "rows_after_stale_execute": rows_after_stale_execute, "proposal_after_stale_execute": proposal_after_stale_execute, - "immutable_approval_after_stale_execute": ( - snapshot_after_stale_execute - ), + "immutable_approval_after_stale_execute": (snapshot_after_stale_execute), "restored_readback": restored_proposal, "restored_immutable_approval": restored_snapshot, "stale_apply_refused": stale_execute.returncode != 0, - "canonical_rows_unchanged": ( - rows_after_stale_execute == _empty_bundle_readback(payload) - ), + "canonical_rows_unchanged": (rows_after_stale_execute == _empty_bundle_readback(payload)), "approval_restored_exactly": restored_proposal == approved_proposal, "immutable_approval_never_changed": all( snapshot == approved_snapshot @@ -1841,27 +1752,41 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: ), } - result["clone_counts_before_apply"] = _base_counts( - args.container, clone_db + if approved_proposal is None or approved_snapshot is None: + raise RuntimeError("approved ledger and immutable approval are required") + result["target_rows_before_apply"] = _exact_bundle_readback(args.container, clone_db, payload) + fresh_preflight = lifecycle.build_fresh_preflight( + approved_proposal, + result["target_rows_before_apply"], ) - first_apply = _apply(args, fixture["proposal_id"], clone_db) - result["first_apply"] = _command_readback(first_apply) - result["row_readback"] = _exact_bundle_readback( - args.container, clone_db, payload - ) - result["clone_counts_after_apply"] = _base_counts( - args.container, clone_db + result["fresh_owned_preflight"] = fresh_preflight + result["unrelated_fingerprint_before_apply"] = _unrelated_state_fingerprint( + args.container, clone_db, payload, fixture["proposal_id"] ) + result["clone_counts_before_apply"] = _base_counts(args.container, clone_db) + with tempfile.TemporaryDirectory(prefix="leo-proposal-apply-receipt-") as receipt_dir: + private_receipt_path = Path(receipt_dir) / "apply-receipt.json" + first_apply = _apply( + args, + fixture["proposal_id"], + clone_db, + receipt_out=private_receipt_path, + ) + result["first_apply"] = _apply_command_readback(first_apply) + if first_apply.returncode != 0 or not private_receipt_path.is_file(): + raise RuntimeError( + "first apply did not produce its explicit private receipt: " + f"returncode={first_apply.returncode} stderr={first_apply.stderr.strip()}" + ) + apply_receipt = json.loads(private_receipt_path.read_text(encoding="utf-8")) + result["row_readback"] = _exact_bundle_readback(args.container, clone_db, payload) + result["clone_counts_after_apply"] = _base_counts(args.container, clone_db) result["clone_apply_table_deltas"] = _table_deltas( result["clone_counts_before_apply"], result["clone_counts_after_apply"], ) - applied_proposal = _proposal_readback( - args.container, clone_db, fixture["proposal_id"] - ) - applied_snapshot = _approval_snapshot_readback( - args.container, clone_db, fixture["proposal_id"] - ) + applied_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + applied_snapshot = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) result["apply_transition"] = { "approved_readback": approved_proposal, "applied_readback": applied_proposal, @@ -1869,20 +1794,93 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "immutable_approval_matches_applied_ledger": ( _approval_snapshot_matches(applied_proposal, applied_snapshot) ), - "exact_transition": _apply_transition_valid( - approved_proposal, applied_proposal - ), + "exact_transition": _apply_transition_valid(approved_proposal, applied_proposal), } replay = _apply(args, fixture["proposal_id"], clone_db) result["idempotent_replay"] = { "returncode": replay.returncode, - "already_applied_refusal": ( - "already applied" in (replay.stdout + replay.stderr).lower() - ), + "already_applied_refusal": ("already applied" in (replay.stdout + replay.stderr).lower()), "stderr": replay.stderr.strip(), } + rollback_sql = lifecycle.build_compensating_rollback_sql( + approved_proposal, + approved_snapshot, + fresh_preflight, + apply_receipt, + ) + result["rollback_plan"] = { + "schema": lifecycle.ROLLBACK_SCHEMA, + "rollback_sql_sha256": lifecycle.sha256_text(rollback_sql), + "execution_authority": "disposable_clone_admin_only", + } + _psql(args.container, clone_db, rollback_sql, tuples=False) + rollback_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + rollback_approval = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) + rollback_target_rows = _exact_bundle_readback(args.container, clone_db, payload) + rollback_counts = _base_counts(args.container, clone_db) + rollback_unrelated = _unrelated_state_fingerprint(args.container, clone_db, payload, fixture["proposal_id"]) + + rollback_replay = _run( + [ + "docker", + "exec", + "-i", + args.container, + "psql", + "-U", + "postgres", + "-d", + clone_db, + "-v", + "ON_ERROR_STOP=1", + ], + input_text=rollback_sql, + check=False, + ) + rollback_replay_state = { + "proposal": _proposal_readback(args.container, clone_db, fixture["proposal_id"]), + "approval": _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]), + "target_rows": _exact_bundle_readback(args.container, clone_db, payload), + "counts": _base_counts(args.container, clone_db), + "unrelated": _unrelated_state_fingerprint(args.container, clone_db, payload, fixture["proposal_id"]), + } + rollback_replay_state_unchanged = rollback_replay_state == { + "proposal": rollback_proposal, + "approval": rollback_approval, + "target_rows": rollback_target_rows, + "counts": rollback_counts, + "unrelated": rollback_unrelated, + } + result["rollback_replay"] = { + "returncode": rollback_replay.returncode, + "refused": rollback_replay.returncode != 0, + "state_unchanged": rollback_replay_state_unchanged, + "stderr": rollback_replay.stderr.strip(), + } + lifecycle_receipt = lifecycle.build_lifecycle_receipt( + proposal_before=approved_proposal, + approval_before=approved_snapshot, + preflight=fresh_preflight, + apply_receipt=apply_receipt, + rollback_sql=rollback_sql, + proposal_after=rollback_proposal or {}, + approval_after=rollback_approval or {}, + target_rows_after=rollback_target_rows, + counts_before=result["clone_counts_before_apply"], + counts_after=rollback_counts, + unrelated_before=result["unrelated_fingerprint_before_apply"], + unrelated_after=rollback_unrelated, + rollback_replay_refused=(rollback_replay.returncode != 0 and rollback_replay_state_unchanged), + ) + result["applied_rollback_receipt"] = lifecycle_receipt + if args.lifecycle_receipt_output: + lifecycle._write_json(args.lifecycle_receipt_output, lifecycle_receipt) + if args.rollback_sql_output: + args.rollback_sql_output.parent.mkdir(parents=True, exist_ok=True) + args.rollback_sql_output.write_text(rollback_sql, encoding="utf-8") + _stage_proposal( args.container, clone_db, @@ -1890,29 +1888,19 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: conflict_payload, source_ref="working-leo:approve-claim-conflict-canary", ) - conflict_pending = _proposal_readback( - args.container, clone_db, fixture["conflict_proposal_id"] - ) + conflict_pending = _proposal_readback(args.container, clone_db, fixture["conflict_proposal_id"]) conflict_pending_snapshot = _approval_snapshot_readback( args.container, clone_db, fixture["conflict_proposal_id"] ) conflict_review = _approve(args, fixture["conflict_proposal_id"], clone_db) - conflict_approved = _proposal_readback( - args.container, clone_db, fixture["conflict_proposal_id"] - ) + conflict_approved = _proposal_readback(args.container, clone_db, fixture["conflict_proposal_id"]) conflict_approved_snapshot = _approval_snapshot_readback( args.container, clone_db, fixture["conflict_proposal_id"] ) conflict = _apply(args, fixture["conflict_proposal_id"], clone_db) - conflict_after = _proposal_readback( - args.container, clone_db, fixture["conflict_proposal_id"] - ) - conflict_snapshot_after = _approval_snapshot_readback( - args.container, clone_db, fixture["conflict_proposal_id"] - ) - conflict_rows = _exact_bundle_readback( - args.container, clone_db, conflict_payload - ) + conflict_after = _proposal_readback(args.container, clone_db, fixture["conflict_proposal_id"]) + conflict_snapshot_after = _approval_snapshot_readback(args.container, clone_db, fixture["conflict_proposal_id"]) + conflict_rows = _exact_bundle_readback(args.container, clone_db, conflict_payload) result["conflict_review_transition"] = { "pending_readback": conflict_pending, "pending_immutable_approval": conflict_pending_snapshot, @@ -1922,15 +1910,11 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "immutable_approval_matches_ledger": _approval_snapshot_matches( conflict_approved, conflict_approved_snapshot ), - "exact_transition": _approval_transition_valid( - conflict_pending, conflict_approved - ), + "exact_transition": _approval_transition_valid(conflict_pending, conflict_approved), } result["conflict_apply"] = { "returncode": conflict.returncode, - "source_hash_collision_refusal": ( - "source hash collision" in (conflict.stdout + conflict.stderr).lower() - ), + "source_hash_collision_refusal": ("source hash collision" in (conflict.stdout + conflict.stderr).lower()), "stderr": conflict.stderr.strip(), } result["conflict_readback"] = { @@ -1938,19 +1922,13 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "immutable_approval": conflict_snapshot_after, "canonical_rows": conflict_rows, "proposal_approval_unchanged": conflict_after == conflict_approved, - "immutable_approval_unchanged": ( - conflict_snapshot_after == conflict_approved_snapshot - ), - "canonical_rows_absent": ( - conflict_rows == _empty_bundle_readback(conflict_payload) - ), + "immutable_approval_unchanged": (conflict_snapshot_after == conflict_approved_snapshot), + "canonical_rows_absent": (conflict_rows == _empty_bundle_readback(conflict_payload)), } except Exception as exc: result["error"] = f"{type(exc).__name__}: {exc}" finally: - cleanup_readback: dict[str, Any] = { - "drop_attempted": bool(result["clone_created"]) - } + cleanup_readback: dict[str, Any] = {"drop_attempted": bool(result["clone_created"])} if result["clone_created"]: cleanup_sql = f"""select pg_terminate_backend(pid) from pg_stat_activity @@ -1985,46 +1963,32 @@ drop database if exists {clone_db}; ) or "0" ) - cleanup_readback["leftover_clone_database_count"] = result[ - "leftover_clone_count" - ] + cleanup_readback["leftover_clone_database_count"] = result["leftover_clone_count"] result["cleanup_readback"] = cleanup_readback - result["source_counts_after"] = _base_counts( - args.container, args.source_db - ) + result["source_counts_after"] = _base_counts(args.container, args.source_db) if "source_counts_before" in result: result["source_table_deltas"] = _table_deltas( result["source_counts_before"], result["source_counts_after"], ) - result["source_cluster_roles_after"] = _cluster_role_readback( - args.container, args.source_db - ) - result["source_target_rows_after"] = _exact_bundle_readback( - args.container, args.source_db, payload - ) + result["source_cluster_roles_after"] = _cluster_role_readback(args.container, args.source_db) + result["source_target_rows_after"] = _exact_bundle_readback(args.container, args.source_db, payload) result["service_after"] = _service_state(args.service) try: source_files_after = _source_file_manifest(args) result["source_binding"]["post_run_files"] = source_files_after - result["source_binding"]["unchanged_during_run"] = ( - source_files_after == source_files_before - ) + result["source_binding"]["unchanged_during_run"] = source_files_after == source_files_before except Exception as exc: - result["source_binding"]["post_run_error"] = ( - f"{type(exc).__name__}: {exc}" - ) + result["source_binding"]["post_run_error"] = f"{type(exc).__name__}: {exc}" gateway_process_observable = ( result.get("service_before", {}).get("available") is True and result.get("service_after", {}).get("available") is True ) gateway_process_unchanged = ( - result.get("service_before", {}).get("MainPID") - == result.get("service_after", {}).get("MainPID") - and result.get("service_before", {}).get("NRestarts") - == result.get("service_after", {}).get("NRestarts") + result.get("service_before", {}).get("MainPID") == result.get("service_after", {}).get("MainPID") + and result.get("service_before", {}).get("NRestarts") == result.get("service_after", {}).get("NRestarts") if gateway_process_observable else None ) @@ -2033,75 +1997,39 @@ drop database if exists {clone_db}; result.get("security_definer_readback") or {} ), "clone_prerequisites_omit_cluster_role_ddl": ( - result.get("clone_prerequisite_sanitization", {}).get( - "cluster_role_ddl_removed" - ) - is True - ), - "reviewer_agent_seeded_exactly": ( - result.get("reviewer_agent_seed", {}).get("exact_clone_copy") is True - ), - "payload_agents_seeded_exactly": ( - result.get("payload_agent_seed", {}).get("exact_clone_copy") is True + result.get("clone_prerequisite_sanitization", {}).get("cluster_role_ddl_removed") is True ), + "reviewer_agent_seeded_exactly": (result.get("reviewer_agent_seed", {}).get("exact_clone_copy") is True), + "payload_agents_seeded_exactly": (result.get("payload_agent_seed", {}).get("exact_clone_copy") is True), "kb_review_approval_succeeded": ( - result.get("review_transition", {}) - .get("review_apply", {}) - .get("returncode") - == 0 + result.get("review_transition", {}).get("review_apply", {}).get("returncode") == 0 ), "kb_review_used_security_definer": ( - result.get("review_transition", {}) - .get("review_dry_run", {}) - .get("uses_approve_strict_proposal") - is True + result.get("review_transition", {}).get("review_dry_run", {}).get("uses_approve_strict_proposal") is True ), "review_transition_exact": ( result.get("review_transition", {}).get("exact_transition") is True - and result.get("review_transition", {}).get( - "immutable_approval_matches_ledger" - ) - is True + and result.get("review_transition", {}).get("immutable_approval_matches_ledger") is True ), "kb_apply_cannot_mutate_proposal_approval": ( - result.get("kb_apply_proposal_mutation_probes", {}) - .get("approval_fields", {}) - .get("refused") - is True + result.get("kb_apply_proposal_mutation_probes", {}).get("approval_fields", {}).get("refused") is True ), "kb_apply_cannot_mutate_proposal_payload": ( - result.get("kb_apply_proposal_mutation_probes", {}) - .get("payload", {}) - .get("refused") - is True + result.get("kb_apply_proposal_mutation_probes", {}).get("payload", {}).get("refused") is True ), "kb_apply_cannot_mutate_immutable_approval": ( - result.get("kb_apply_proposal_mutation_probes", {}) - .get("immutable_approval_payload", {}) - .get("refused") + result.get("kb_apply_proposal_mutation_probes", {}).get("immutable_approval_payload", {}).get("refused") is True ), "proposal_exact_after_permission_probes": ( - result.get("kb_apply_proposal_mutation_probes", {}).get( - "exact_row_unchanged" - ) - is True - and result.get("kb_apply_proposal_mutation_probes", {}).get( - "immutable_approval_exactly_unchanged" - ) - is True + result.get("kb_apply_proposal_mutation_probes", {}).get("exact_row_unchanged") is True + and result.get("kb_apply_proposal_mutation_probes", {}).get("immutable_approval_exactly_unchanged") is True ), "kb_apply_cannot_update_existing_claim_evidence": ( - result.get("kb_apply_claim_evidence_update_probe", {}) - .get("attempt", {}) - .get("refused") - is True + result.get("kb_apply_claim_evidence_update_probe", {}).get("attempt", {}).get("refused") is True ), "claim_evidence_exact_after_permission_probe": ( - result.get("kb_apply_claim_evidence_update_probe", {}).get( - "exact_row_unchanged" - ) - is True + result.get("kb_apply_claim_evidence_update_probe", {}).get("exact_row_unchanged") is True ), "mutation_between_build_and_execute_refused": all( result.get("mutation_between_build_and_execute", {}).get(key) is True @@ -2114,87 +2042,64 @@ drop database if exists {clone_db}; "immutable_approval_never_changed", ) ), - "first_apply_succeeded": result.get("first_apply", {}).get("returncode") - == 0, - "payload_projection_exact": result.get("row_readback") == expected_rows, - "clone_apply_table_deltas_exact": ( - result.get("clone_apply_table_deltas") == expected_table_deltas + "first_apply_succeeded": result.get("first_apply", {}).get("returncode") == 0, + "fresh_owned_preflight_exact": ( + result.get("fresh_owned_preflight", {}).get("fresh_owned_targets") is True + and result.get("target_rows_before_apply") == _empty_bundle_readback(payload) ), + "compensating_rollback_receipt_passes": ( + result.get("applied_rollback_receipt", {}).get("pass") is True + and result.get("applied_rollback_receipt", {}).get("current_tier") == "T2_runtime" + ), + "rollback_replay_refused_without_mutation": ( + result.get("rollback_replay", {}).get("refused") is True + and result.get("rollback_replay", {}).get("state_unchanged") is True + ), + "payload_projection_exact": result.get("row_readback") == expected_rows, + "clone_apply_table_deltas_exact": (result.get("clone_apply_table_deltas") == expected_table_deltas), "apply_transition_exact": ( result.get("apply_transition", {}).get("exact_transition") is True - and result.get("apply_transition", {}).get( - "immutable_approval_matches_applied_ledger" - ) - is True + and result.get("apply_transition", {}).get("immutable_approval_matches_applied_ledger") is True ), "idempotent_replay_refused": ( result.get("idempotent_replay", {}).get("returncode", 0) != 0 - and result.get("idempotent_replay", {}).get( - "already_applied_refusal" - ) - is True + and result.get("idempotent_replay", {}).get("already_applied_refusal") is True ), "conflict_review_separate_and_exact": ( - result.get("conflict_review_transition", {}).get("exact_transition") - is True - and result.get("conflict_review_transition", {}).get( - "immutable_approval_matches_ledger" - ) - is True + result.get("conflict_review_transition", {}).get("exact_transition") is True + and result.get("conflict_review_transition", {}).get("immutable_approval_matches_ledger") is True ), "source_hash_conflict_refused": ( result.get("conflict_apply", {}).get("returncode", 0) != 0 - and result.get("conflict_apply", {}).get( - "source_hash_collision_refusal" - ) - is True + and result.get("conflict_apply", {}).get("source_hash_collision_refusal") is True ), "conflict_transaction_rolled_back_exactly": ( - result.get("conflict_readback", {}).get( - "proposal_approval_unchanged" - ) - is True - and result.get("conflict_readback", {}).get( - "immutable_approval_unchanged" - ) - is True - and result.get("conflict_readback", {}).get("canonical_rows_absent") - is True + result.get("conflict_readback", {}).get("proposal_approval_unchanged") is True + and result.get("conflict_readback", {}).get("immutable_approval_unchanged") is True + and result.get("conflict_readback", {}).get("canonical_rows_absent") is True ), "source_target_rows_unchanged": ( - result.get("source_target_rows_before") - == result.get("source_target_rows_after") + result.get("source_target_rows_before") == result.get("source_target_rows_after") ), "source_cluster_roles_preexisting": ( - _cluster_roles_are_preprovisioned( - result.get("source_cluster_roles_before") or [] - ) + _cluster_roles_are_preprovisioned(result.get("source_cluster_roles_before") or []) ), "source_cluster_roles_unchanged": ( - result.get("source_cluster_roles_before") - == result.get("source_cluster_roles_after") + result.get("source_cluster_roles_before") == result.get("source_cluster_roles_after") ), "source_table_deltas_exactly_zero": ( bool(result.get("source_table_deltas")) and all(delta == 0 for delta in result["source_table_deltas"].values()) ), - "source_files_unchanged_during_run": ( - result.get("source_binding", {}).get("unchanged_during_run") is True - ), + "source_files_unchanged_during_run": (result.get("source_binding", {}).get("unchanged_during_run") is True), "gateway_process_unchanged": gateway_process_unchanged, - "clone_cleanup_complete": ( - result.get("clone_dropped") is True - and result.get("leftover_clone_count") == 0 - ), + "clone_cleanup_complete": (result.get("clone_dropped") is True and result.get("leftover_clone_count") == 0), } - result["source_counts_observed_unchanged"] = ( - result.get("source_counts_before") == result.get("source_counts_after") - ) + result["source_counts_observed_unchanged"] = result.get("source_counts_before") == result.get("source_counts_after") result["gateway_process_observable"] = gateway_process_observable result["status"] = ( "pass" - if all(value is True for value in result["checks"].values() if value is not None) - and "error" not in result + if all(value is True for value in result["checks"].values() if value is not None) and "error" not in result else "fail" ) result["source_database_mutated"] = not all( @@ -2205,11 +2110,7 @@ drop database if exists {clone_db}; "source_table_deltas_exactly_zero", ) ) - result["service_restarted"] = ( - None - if gateway_process_unchanged is None - else not gateway_process_unchanged - ) + result["service_restarted"] = None if gateway_process_unchanged is None else not gateway_process_unchanged result["post_run_cleanup"] = { "leftover_clone_database_count": result.get("leftover_clone_count"), "gateway_process_observable": gateway_process_observable, @@ -2218,9 +2119,7 @@ drop database if exists {clone_db}; "gateway_main_pid": result.get("service_after", {}).get("MainPID"), "gateway_restart_count": result.get("service_after", {}).get("NRestarts"), } - result["strict_receipt"] = _strict_receipt( - result, expected_rows, expected_table_deltas - ) + result["strict_receipt"] = _strict_receipt(result, expected_rows, expected_table_deltas) if not result["strict_receipt"]["pass"]: result["status"] = "fail" return result @@ -2232,15 +2131,9 @@ def parse_args(argv: list[str]) -> argparse.Namespace: parser.add_argument("--source-db", default=ap.DEFAULT_DB) parser.add_argument("--database-prefix", default="teleo_approve_claim_clone") parser.add_argument("--service", default="leoclean-gateway.service") - parser.add_argument( - "--approve-script", type=Path, default=HERE / "approve_proposal.py" - ) - parser.add_argument( - "--apply-script", type=Path, default=HERE / "apply_proposal.py" - ) - parser.add_argument( - "--prereqs", type=Path, default=HERE / "kb_apply_prereqs.sql" - ) + parser.add_argument("--approve-script", type=Path, default=HERE / "approve_proposal.py") + parser.add_argument("--apply-script", type=Path, default=HERE / "apply_proposal.py") + parser.add_argument("--prereqs", type=Path, default=HERE / "kb_apply_prereqs.sql") parser.add_argument("--review-secrets-file", default=DEFAULT_REVIEW_SECRETS_FILE) parser.add_argument("--secrets-file", default=ap.DEFAULT_SECRETS_FILE) parser.add_argument("--review-role", default="kb_review") @@ -2251,6 +2144,16 @@ def parse_args(argv: list[str]) -> argparse.Namespace: help="optional one-row normalization output containing one strict approve_claim child", ) parser.add_argument("--output", type=Path) + parser.add_argument( + "--lifecycle-receipt-output", + type=Path, + help="optional public fixture receipt output (never use for private production data)", + ) + parser.add_argument( + "--rollback-sql-output", + type=Path, + help="optional exact clone rollback SQL output", + ) return parser.parse_args(argv) diff --git a/scripts/run_approve_claim_isolated_container_canary.sh b/scripts/run_approve_claim_isolated_container_canary.sh index a34f3bf..5690c31 100755 --- a/scripts/run_approve_claim_isolated_container_canary.sh +++ b/scripts/run_approve_claim_isolated_container_canary.sh @@ -9,6 +9,8 @@ image="${POSTGRES_CANARY_IMAGE:-postgres:16}" source_tier="${SOURCE_TIER:-live-readonly}" normalization_json="" output="${repo_root}/docs/reports/leo-working-state-20260709/approve-claim-clone-canary-current.json" +lifecycle_receipt_output="" +rollback_sql_output="" while [[ $# -gt 0 ]]; do case "$1" in @@ -20,6 +22,14 @@ while [[ $# -gt 0 ]]; do output="$2" shift 2 ;; + --lifecycle-receipt-output) + lifecycle_receipt_output="$2" + shift 2 + ;; + --rollback-sql-output) + rollback_sql_output="$2" + shift 2 + ;; --source-container) source_container="$2" shift 2 @@ -99,11 +109,19 @@ service_state() { } mkdir -p "$workdir" "$(dirname "$output")" +if [[ -n "$lifecycle_receipt_output" ]]; then + mkdir -p "$(dirname "$lifecycle_receipt_output")" +fi +if [[ -n "$rollback_sql_output" ]]; then + mkdir -p "$(dirname "$rollback_sql_output")" +fi source_counts_before="$(source_counts)" service_before="$(service_state)" docker run -d --name "$container" \ --network none \ + --label livingip.canary=proposal-apply-lifecycle \ + --label "livingip.canary.instance=${container}" \ --tmpfs /var/lib/postgresql/data:rw,nosuid,size=512m \ -e POSTGRES_PASSWORD="isolated-postgres-${RANDOM}-${RANDOM}" \ -e POSTGRES_DB=teleo \ @@ -127,6 +145,12 @@ if [[ "$ready_streak" -lt 2 ]]; then fi container_network_mode="$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$container")" container_mounts_json="$(docker inspect -f '{{json .Mounts}}' "$container")" +container_canary_label="$( + docker inspect -f '{{index .Config.Labels "livingip.canary"}}' "$container" +)" +container_instance_label="$( + docker inspect -f '{{index .Config.Labels "livingip.canary.instance"}}' "$container" +)" docker exec "$source_container" pg_dump -U postgres -d "$source_db" \ --schema-only --no-owner --no-privileges >"$workdir/schema.sql" @@ -165,6 +189,13 @@ normalization_args=() if [[ -n "$normalization_json" ]]; then normalization_args=(--normalization-json "$normalization_json") fi +artifact_args=() +if [[ -n "$lifecycle_receipt_output" ]]; then + artifact_args+=(--lifecycle-receipt-output "$lifecycle_receipt_output") +fi +if [[ -n "$rollback_sql_output" ]]; then + artifact_args+=(--rollback-sql-output "$rollback_sql_output") +fi set +e python3 "$repo_root/scripts/run_approve_claim_clone_canary.py" \ @@ -178,6 +209,7 @@ python3 "$repo_root/scripts/run_approve_claim_clone_canary.py" \ --review-secrets-file "$workdir/kb-review.env" \ --secrets-file "$workdir/kb-apply.env" \ "${normalization_args[@]}" \ + "${artifact_args[@]}" \ --output "$output" \ >"$workdir/stdout.json" 2>"$workdir/stderr.log" canary_rc=$? @@ -192,6 +224,20 @@ container_name_readback="$( docker container ls -a --filter "name=^/${container}$" --format '{{.Names}}' 2>&1 )" container_name_readback_rc=$? +container_label_readback="$( + docker container ls -a \ + --filter "label=livingip.canary=proposal-apply-lifecycle" \ + --filter "label=livingip.canary.instance=${container}" \ + --format '{{.Names}}' 2>&1 +)" +container_label_readback_rc=$? +if [[ "$container_label_readback_rc" -eq 0 ]]; then + container_label_orphan_count="$( + awk 'NF { count += 1 } END { print count + 0 }' <<<"$container_label_readback" + )" +else + container_label_orphan_count=-1 +fi if [[ -e "$workdir" || -L "$workdir" ]]; then outer_workdir_lexists=true else @@ -214,6 +260,9 @@ OUTER_CONTAINER_REMOVE_RC="$outer_container_remove_rc" \ OUTER_WORKDIR_REMOVE_RC="$outer_workdir_remove_rc" \ CONTAINER_NAME_READBACK="$container_name_readback" \ CONTAINER_NAME_READBACK_RC="$container_name_readback_rc" \ +CONTAINER_LABEL_READBACK="$container_label_readback" \ +CONTAINER_LABEL_READBACK_RC="$container_label_readback_rc" \ +CONTAINER_LABEL_ORPHAN_COUNT="$container_label_orphan_count" \ OUTER_WORKDIR_LEXISTS="$outer_workdir_lexists" \ CANARY_RC="$canary_rc" \ SOURCE_TIER="$source_tier" \ @@ -221,219 +270,6 @@ SOURCE_NETWORK_MODE="$source_network_mode" \ SOURCE_CANARY_LABEL="$source_canary_label" \ CANARY_NETWORK_MODE="$container_network_mode" \ CANARY_MOUNTS_JSON="$container_mounts_json" \ -python3 - "$output" <<'PY' -import hashlib -import json -import os -import sys -from pathlib import Path - -path = Path(sys.argv[1]) -if not path.is_file(): - raise SystemExit("inner canary did not produce a report") - -data = json.loads(path.read_text(encoding="utf-8")) - -def service(raw: str) -> dict[str, str]: - return dict(line.split("=", 1) for line in raw.splitlines() if "=" in line) - -def table_deltas(before: dict[str, int], after: dict[str, int]) -> dict[str, int]: - if set(before) != set(after): - raise SystemExit( - "live source count keys changed during the canary: " - f"before={sorted(before)} after={sorted(after)}" - ) - return {key: after[key] - before[key] for key in sorted(before)} - -def verify_source_binding(root: Path, records: list[dict[str, object]]) -> dict[str, object]: - readbacks = [] - for record in records: - relative_text = str(record.get("repo_relative_path", "")) - relative = Path(relative_text) - if not relative_text or relative.is_absolute() or ".." in relative.parts: - raise SystemExit(f"unsafe repo-relative source path: {relative_text!r}") - candidate = (root / relative).resolve() - try: - candidate.relative_to(root) - except ValueError as exc: - raise SystemExit( - f"source path escaped repository root: {relative_text}" - ) from exc - if not candidate.is_file(): - readbacks.append( - { - "repo_relative_path": relative.as_posix(), - "expected_sha256": record.get("sha256"), - "actual_sha256": None, - "matches": False, - } - ) - continue - content = candidate.read_bytes() - actual_sha256 = hashlib.sha256(content).hexdigest() - readbacks.append( - { - "repo_relative_path": relative.as_posix(), - "expected_sha256": record.get("sha256"), - "actual_sha256": actual_sha256, - "size_bytes": len(content), - "matches": ( - actual_sha256 == record.get("sha256") - and len(content) == record.get("size_bytes") - ), - } - ) - return { - "files": readbacks, - "all_match": bool(readbacks) and all(row["matches"] for row in readbacks), - } - -def contains_ephemeral_path(value: object) -> bool: - if isinstance(value, str): - return "/tmp/" in value - if isinstance(value, dict): - return any(contains_ephemeral_path(item) for item in value.values()) - if isinstance(value, list): - return any(contains_ephemeral_path(item) for item in value) - return False - -before_counts = json.loads(os.environ["SOURCE_COUNTS_BEFORE"]) -after_counts = json.loads(os.environ["SOURCE_COUNTS_AFTER"]) -live_table_deltas = table_deltas(before_counts, after_counts) -before_service = service(os.environ["SERVICE_BEFORE"]) -after_service = service(os.environ["SERVICE_AFTER"]) -source_tier = os.environ["SOURCE_TIER"] -source_network_mode = os.environ["SOURCE_NETWORK_MODE"] -source_canary_label = os.environ["SOURCE_CANARY_LABEL"] -container_network_mode = os.environ["CANARY_NETWORK_MODE"] -container_mounts = json.loads(os.environ["CANARY_MOUNTS_JSON"]) -container_volume_mounts = [ - mount for mount in container_mounts if mount.get("Type") == "volume" -] -container_isolated = ( - container_network_mode == "none" and not container_volume_mounts -) -source_tier_enforced = ( - source_tier != "isolated-local" - or ( - source_network_mode == "none" - and source_canary_label == "working-leo-approved-source" - ) -) -service_observable = ( - before_service.get("Available") == "true" - and after_service.get("Available") == "true" -) -service_stable = ( - all( - before_service.get(key) == after_service.get(key) - for key in ("ActiveState", "SubState", "MainPID", "NRestarts") - ) - if service_observable - else None -) -service_gate_passes = ( - service_stable is True - if source_tier == "live-readonly" - else service_stable is not False -) -container_absent = ( - int(os.environ["CONTAINER_NAME_READBACK_RC"]) == 0 - and not os.environ["CONTAINER_NAME_READBACK"].strip() -) -workdir_absent = os.environ["OUTER_WORKDIR_LEXISTS"] == "false" -source_binding = verify_source_binding( - Path(os.environ["REPO_ROOT"]).resolve(), - data.get("source_binding", {}).get("files", []), -) -data["source_binding"]["independent_post_cleanup_verification"] = source_binding -source_binding_ok = ( - data["source_binding"].get("unchanged_during_run") is True - and source_binding["all_match"] is True -) -stale_ephemeral_paths_absent = not contains_ephemeral_path(data) -inner_runtime_pass = data.get("status") == "pass" and int(os.environ["CANARY_RC"]) == 0 -outer_ok = ( - before_counts == after_counts - and all(delta == 0 for delta in live_table_deltas.values()) - and service_gate_passes - and container_absent - and workdir_absent - and source_binding_ok - and stale_ephemeral_paths_absent - and container_isolated - and source_tier_enforced -) -if source_tier == "isolated-local": - data["required_tier"] = "T2_runtime" - data["required_tiers"] = ["T2_runtime"] - data["runtime_scope"] = "isolated_postgres_container_from_readonly_local_fixture" -else: - data["required_tier"] = "T3_live_readonly" - data["required_tiers"] = ["T2_runtime", "T3_live_readonly"] - data["runtime_scope"] = "isolated_postgres_container_from_readonly_live_schema" -data["outer_isolation"] = { - "source_container": os.environ.get("SOURCE_CONTAINER", "teleo-pg"), - "source_database": os.environ.get("SOURCE_DB", "teleo"), - "source_counts_before": before_counts, - "source_counts_after": after_counts, - "canonical_table_deltas": live_table_deltas, - "source_counts_unchanged": before_counts == after_counts, - "service_before": before_service, - "service_after": after_service, - "service_required": source_tier == "live-readonly", - "service_observable": service_observable, - "service_stable": service_stable, - "service_gate_passes": service_gate_passes, - "source_boundary": { - "source_tier": source_tier, - "network_mode": source_network_mode, - "canary_label": source_canary_label, - "tier_enforced": source_tier_enforced, - }, - "container_isolation": { - "network_mode": container_network_mode, - "volume_mounts": container_volume_mounts, - "network_disabled": container_network_mode == "none", - "no_docker_volumes": not container_volume_mounts, - }, - "cleanup_readback": { - "container_remove_returncode": int(os.environ["OUTER_CONTAINER_REMOVE_RC"]), - "container_name_query_returncode": int( - os.environ["CONTAINER_NAME_READBACK_RC"] - ), - "container_name_query_stdout": os.environ["CONTAINER_NAME_READBACK"], - "temporary_container_absent": container_absent, - "workdir_remove_returncode": int(os.environ["OUTER_WORKDIR_REMOVE_RC"]), - "workdir_lexists_after_cleanup": not workdir_absent, - "temporary_workdir_absent": workdir_absent, - }, -} -data["checks"]["outer_live_counts_exactly_unchanged"] = before_counts == after_counts -data["checks"]["outer_live_table_deltas_exactly_zero"] = all( - delta == 0 for delta in live_table_deltas.values() -) -data["checks"]["outer_service_observed_if_required"] = ( - source_tier != "live-readonly" or service_observable -) -data["checks"]["outer_service_stable_if_observed"] = service_gate_passes -data["checks"]["outer_container_absent_independent_readback"] = container_absent -data["checks"]["outer_workdir_absent_independent_readback"] = workdir_absent -data["checks"]["source_binding_independently_verified"] = source_binding_ok -data["checks"]["stale_ephemeral_paths_absent"] = stale_ephemeral_paths_absent -data["checks"]["outer_source_tier_enforced"] = source_tier_enforced -data["checks"]["outer_container_network_disabled"] = ( - container_network_mode == "none" -) -data["checks"]["outer_container_has_no_docker_volumes"] = not container_volume_mounts -data["checks"]["outer_isolation_complete"] = outer_ok -if outer_ok and inner_runtime_pass: - data["current_tier"] = ( - "T2_runtime" if source_tier == "isolated-local" else "T3_live_readonly" - ) -else: - data["status"] = "fail" - data["current_tier"] = "T2_runtime" if inner_runtime_pass else "T1_model" -path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8") -raise SystemExit(0 if data["status"] == "pass" else 1) -PY +CANARY_LABEL="$container_canary_label" \ +CANARY_INSTANCE_LABEL="$container_instance_label" \ +python3 "$repo_root/scripts/finalize_approve_claim_isolated_canary.py" "$output" diff --git a/tests/test_apply_proposal.py b/tests/test_apply_proposal.py index b1fb67d..8f79873 100644 --- a/tests/test_apply_proposal.py +++ b/tests/test_apply_proposal.py @@ -30,6 +30,10 @@ sys.path.insert(0, str(REPO_ROOT / "scripts")) import apply_proposal as ap # noqa: E402 +CLAIM_A = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +CLAIM_B = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +SOURCE_A = "cccccccc-cccc-4ccc-8ccc-cccccccccccc" + def _approval_meta(proposal_type, apply_payload): return { @@ -112,7 +116,7 @@ def test_revise_strategy_rejects_bad_node_type(): # --- add_edge ------------------------------------------------------------- # def test_add_edge_sql_dedup_guard(): - payload = {"from_claim": "aaaa", "to_claim": "bbbb", "edge_type": "supersedes", "weight": 0.9} + payload = {"from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supersedes", "weight": 0.9} sql = ap.build_add_edge_sql(payload, "pid-2", None, _approval_meta("add_edge", payload)) assert "insert into public.claim_edges" in sql assert "not exists" in sql @@ -122,7 +126,7 @@ def test_add_edge_sql_dedup_guard(): def test_add_edge_semantic_row_accepts_match_and_rejects_weight_mismatch(): - payload = {"from_claim": "aaaa", "to_claim": "bbbb", "edge_type": "supports", "weight": 0.9} + payload = {"from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports", "weight": 0.9} sql = ap.build_add_edge_sql(payload, "pid-2", None, _approval_meta("add_edge", payload)) verify = sql[sql.index("do $verify$") : sql.index("kb_stage.finish_approved_proposal")] @@ -131,9 +135,7 @@ def test_add_edge_semantic_row_accepts_match_and_rejects_weight_mismatch(): assert "claim_edge row does not match strict apply payload" in verify assert sql.startswith("begin;") assert sql.rstrip().endswith("commit;") - assert sql.index("raise exception 'apply_proposal: claim_edge row") < sql.index( - "kb_stage.finish_approved_proposal" - ) + assert sql.index("raise exception 'apply_proposal: claim_edge row") < sql.index("kb_stage.finish_approved_proposal") def test_add_edge_rejects_self_loop(): @@ -144,7 +146,7 @@ def test_add_edge_rejects_self_loop(): # --- attach_evidence ------------------------------------------------------ # def test_attach_evidence_sql_with_source_id(): - payload = {"evidence": [{"claim_id": "cccc", "source_id": "dddd", "role": "grounds", "weight": 0.78}]} + payload = {"evidence": [{"claim_id": CLAIM_A, "source_id": SOURCE_A, "role": "grounds", "weight": 0.78}]} sql = ap.build_attach_evidence_sql(payload, "pid-3", None, _approval_meta("attach_evidence", payload)) assert "insert into public.claim_evidence" in sql assert "::evidence_role" in sql @@ -152,14 +154,8 @@ def test_attach_evidence_sql_with_source_id(): def test_attach_evidence_semantic_row_accepts_match_and_rejects_weight_mismatch(): - payload = { - "evidence": [ - {"claim_id": "cccc", "source_id": "dddd", "role": "grounds", "weight": 0.78} - ] - } - sql = ap.build_attach_evidence_sql( - payload, "pid-3", None, _approval_meta("attach_evidence", payload) - ) + payload = {"evidence": [{"claim_id": CLAIM_A, "source_id": SOURCE_A, "role": "grounds", "weight": 0.78}]} + sql = ap.build_attach_evidence_sql(payload, "pid-3", None, _approval_meta("attach_evidence", payload)) verify = sql[sql.index("do $verify$") : sql.index("kb_stage.finish_approved_proposal")] assert "weight is not distinct from 0.78" in verify @@ -167,9 +163,7 @@ def test_attach_evidence_semantic_row_accepts_match_and_rejects_weight_mismatch( assert "evidence row % does not match strict apply payload" in verify assert sql.startswith("begin;") assert sql.rstrip().endswith("commit;") - assert sql.index("raise exception 'apply_proposal: evidence row") < sql.index( - "kb_stage.finish_approved_proposal" - ) + assert sql.index("raise exception 'apply_proposal: evidence row") < sql.index("kb_stage.finish_approved_proposal") def test_attach_evidence_requires_source_id(): @@ -231,9 +225,7 @@ def _approve_claim_bundle(): {"claim_id": claim_a, "source_id": source_a, "role": "grounds", "weight": 0.9}, {"claim_id": claim_b, "source_id": source_b, "role": "illustrates", "weight": None}, ], - "edges": [ - {"from_claim": claim_a, "to_claim": claim_b, "edge_type": "supports", "weight": 0.7} - ], + "edges": [{"from_claim": claim_a, "to_claim": claim_b, "edge_type": "supports", "weight": 0.7}], "reasoning_tools": [ { "id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee", @@ -291,9 +283,7 @@ def test_approve_claim_semantic_rows_accept_matches_and_reject_payload_mismatche assert "approve_claim: edge row does not match strict apply payload" in verify assert sql.startswith("begin;") assert sql.rstrip().endswith("commit;") - assert sql.index("raise exception 'approve_claim: evidence row") < sql.index( - "kb_stage.finish_approved_proposal" - ) + assert sql.index("raise exception 'approve_claim: evidence row") < sql.index("kb_stage.finish_approved_proposal") def test_approve_claim_bundle_rejects_duplicate_source_hashes(): @@ -445,7 +435,7 @@ def test_assert_applyable_allows_approved(): # --- ledger flip: concurrency guard + FK stamp --------------------------- # def test_ledger_transition_uses_payload_bound_security_functions(): - payload = {"from_claim": "a", "to_claim": "b", "edge_type": "supports"} + payload = {"from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports"} sql = ap.build_add_edge_sql(payload, "pid", None, _approval_meta("add_edge", payload)) assert "kb_stage.assert_approved_proposal" in sql assert "kb_stage.finish_approved_proposal" in sql @@ -459,7 +449,7 @@ def test_ledger_transition_uses_payload_bound_security_functions(): def test_ledger_flip_stamps_agent_fk(): - payload = {"from_claim": "a", "to_claim": "b", "edge_type": "supports"} + payload = {"from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports"} sql = ap.build_add_edge_sql(payload, "pid", "kb-apply", _approval_meta("add_edge", payload)) # Hard resolve into a variable + NOT-NULL assert, never a silent inline # subselect that would stamp NULL on an unresolved handle. @@ -468,7 +458,7 @@ def test_ledger_flip_stamps_agent_fk(): def test_build_apply_sql_defaults_applied_by_to_service_agent(): - payload = {"from_claim": "a", "to_claim": "b", "edge_type": "supports"} + payload = {"from_claim": CLAIM_A, "to_claim": CLAIM_B, "edge_type": "supports"} proposal = { "id": "pid", "proposal_type": "add_edge", diff --git a/tests/test_apply_worker.py b/tests/test_apply_worker.py index 21ce813..cd04d1d 100644 --- a/tests/test_apply_worker.py +++ b/tests/test_apply_worker.py @@ -6,7 +6,10 @@ standalone (`python3 tests/test_apply_worker.py`). """ import argparse +import json +import stat import sys +import tempfile from pathlib import Path try: @@ -40,19 +43,33 @@ sys.path.insert(0, str(REPO_ROOT / "scripts")) import apply_worker as w # noqa: E402 -@pytest.fixture(autouse=True) -def restore_apply_worker_dependencies(): +def _dependency_restore(): original_load_password = w.ap.load_password original_load_failure_state = w.load_failure_state original_fetch_candidates = w.fetch_candidates original_apply_one = w.apply_one original_render_one = w.render_one + original_subprocess_run = w.subprocess.run yield w.ap.load_password = original_load_password w.load_failure_state = original_load_failure_state w.fetch_candidates = original_fetch_candidates w.apply_one = original_apply_one w.render_one = original_render_one + w.subprocess.run = original_subprocess_run + + +@pytest.fixture(autouse=True) +def restore_apply_worker_dependencies(): + restore = _dependency_restore() + next(restore) + try: + yield + finally: + try: + next(restore) + except StopIteration: + pass # --- candidate query ------------------------------------------------------ # @@ -116,22 +133,283 @@ def test_render_command_expands_agent_id(): # --- enablement gate ------------------------------------------------------ # def _args(**over): base = dict( - enable=False, limit=20, max_per_tick=1, max_attempts=3, - failure_state_file=None, applied_by="kb-apply", - apply_script="apply_proposal.py", render_cmd="", - secrets_file="x", container="teleo-pg", db="teleo", - host="127.0.0.1", role="kb_apply", + enable=False, + limit=20, + max_per_tick=1, + max_attempts=3, + failure_state_file=None, + applied_by="kb-apply", + apply_script="apply_proposal.py", + render_cmd="", + receipt_dir="/private/tmp/kb-apply-worker-test-receipts", + secrets_file="x", + container="teleo-pg", + db="teleo", + host="127.0.0.1", + role="kb_apply", ) base.update(over) return argparse.Namespace(**base) +def _write_valid_private_receipt(path: Path, proposal_id: str) -> None: + from_claim = "11111111-1111-4111-8111-111111111111" + to_claim = "22222222-2222-4222-8222-222222222222" + proposal = { + "id": proposal_id, + "proposal_type": "add_edge", + "status": "applied", + "payload": { + "apply_payload": { + "from_claim": from_claim, + "to_claim": to_claim, + "edge_type": "supports", + "weight": 0.75, + } + }, + "reviewed_by_handle": "reviewer", + "reviewed_by_agent_id": None, + "reviewed_at": "2026-07-15T10:00:00+00:00", + "review_note": "Approved for worker receipt testing.", + "applied_by_handle": "kb-apply", + "applied_by_agent_id": None, + "applied_at": "2026-07-15T10:01:00+00:00", + } + receipt = w.ap.replay_receipt.build_replay_receipt( + proposal, + { + "claim_edges": [ + { + "id": "33333333-3333-4333-8333-333333333333", + "from_claim": from_claim, + "to_claim": to_claim, + "edge_type": "supports", + "weight": 0.75, + "created_by": None, + } + ] + }, + apply_sql_sha256="a" * 64, + apply_sql_source="exact_executed_sql", + exported_at_utc="2026-07-15T10:02:00+00:00", + ) + path.parent.mkdir(parents=True, exist_ok=True, mode=0o700) + path.write_text(json.dumps(receipt), encoding="utf-8") + path.chmod(0o600) + + +def _load_private_receipt(path: Path) -> dict: + return json.loads(path.read_text(encoding="utf-8")) + + +def _write_private_receipt(path: Path, receipt: dict) -> None: + path.write_text(json.dumps(receipt), encoding="utf-8") + path.chmod(0o600) + + +def _completed(returncode: int, *, stdout: str = "", stderr: str = ""): + return w.subprocess.CompletedProcess([], returncode, stdout=stdout, stderr=stderr) + + +def _postcommit_receipt_failure(proposal_id: str, detail: str = "receipt write failed") -> str: + return ( + f"proposal {proposal_id} {w.POSTCOMMIT_RECEIPT_FAILURE_MARKER}: {detail}" + f"{w.POSTCOMMIT_RECEIPT_RECOVERY_MARKER}" + f"apply_proposal.py {proposal_id} --receipt-only" + ) + + +# --- private receipt and post-COMMIT recovery ---------------------------- # +def test_private_receipt_requires_complete_canonical_rows_and_hashes(): + proposal_id = "99999999-9999-4999-8999-999999999999" + receipt_path = Path(tempfile.mkdtemp()) / "receipt.json" + _write_valid_private_receipt(receipt_path, proposal_id) + + missing_rows = _load_private_receipt(receipt_path) + missing_rows.pop("canonical_rows") + _write_private_receipt(receipt_path, missing_rows) + with pytest.raises(RuntimeError, match="row-level contract is invalid"): + w.assert_private_replay_receipt(receipt_path, proposal_id) + + _write_valid_private_receipt(receipt_path, proposal_id) + missing_hashes = _load_private_receipt(receipt_path) + missing_hashes.pop("hashes") + _write_private_receipt(receipt_path, missing_hashes) + with pytest.raises(RuntimeError, match="row-level contract is invalid"): + w.assert_private_replay_receipt(receipt_path, proposal_id) + + +def test_private_receipt_rejects_canonical_row_tampering_without_recomputed_hashes(): + proposal_id = "88888888-8888-4888-8888-888888888888" + receipt_path = Path(tempfile.mkdtemp()) / "receipt.json" + _write_valid_private_receipt(receipt_path, proposal_id) + tampered = _load_private_receipt(receipt_path) + tampered["canonical_rows"]["claim_edges"][0]["weight"] = 0.5 + _write_private_receipt(receipt_path, tampered) + + with pytest.raises(RuntimeError, match="row-level contract is invalid|internally inconsistent"): + w.assert_private_replay_receipt(receipt_path, proposal_id) + + +def test_apply_one_supplies_deterministic_private_receipt_path(): + proposal_id = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + receipt_dir = Path(tempfile.mkdtemp()) / "receipts" + calls = [] + + def _run(cmd, **_kwargs): + calls.append(cmd) + receipt_path = Path(cmd[cmd.index("--receipt-out") + 1]) + _write_valid_private_receipt(receipt_path, proposal_id) + return _completed(0, stdout='{"applied": true}') + + w.subprocess.run = _run + w.apply_one(_args(receipt_dir=str(receipt_dir)), proposal_id) + + expected = receipt_dir.resolve() / f"{proposal_id}.json" + assert len(calls) == 1 + assert calls[0][calls[0].index("--receipt-dir") + 1] == str(expected.parent) + assert calls[0][calls[0].index("--receipt-out") + 1] == str(expected) + assert stat.S_IMODE(expected.stat().st_mode) == 0o600 + + +def test_apply_one_recovers_postcommit_receipt_failure_without_reapplying(): + proposal_id = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + receipt_dir = Path(tempfile.mkdtemp()) / "receipts" + calls = [] + + def _run(cmd, **_kwargs): + calls.append(cmd) + if len(calls) == 1: + return _completed( + 1, + stderr=_postcommit_receipt_failure(proposal_id), + ) + assert "--receipt-only" in cmd + receipt_path = Path(cmd[cmd.index("--receipt-out") + 1]) + _write_valid_private_receipt(receipt_path, proposal_id) + return _completed(0, stdout='{"replay_ready": true}') + + w.subprocess.run = _run + w.apply_one(_args(receipt_dir=str(receipt_dir)), proposal_id) + + assert len(calls) == 2 + assert "--receipt-only" not in calls[0] + assert "--receipt-only" in calls[1] + assert calls[0][calls[0].index("--receipt-out") + 1] == calls[1][calls[1].index("--receipt-out") + 1] + + +def test_apply_one_does_not_recover_a_precommit_apply_failure(): + calls = [] + + def _run(cmd, **_kwargs): + calls.append(cmd) + return _completed(1, stderr="psql transaction failed before commit") + + w.subprocess.run = _run + try: + w.apply_one(_args(receipt_dir=tempfile.mkdtemp()), "p1") + except w.PostCommitReceiptError as exc: + raise AssertionError("pre-COMMIT failure was misclassified as committed") from exc + except RuntimeError: + pass + else: + raise AssertionError("expected pre-COMMIT apply failure") + + assert len(calls) == 1 + + +def test_apply_one_classifies_unrecovered_receipt_as_postcommit(): + calls = [] + + def _run(cmd, **_kwargs): + calls.append(cmd) + if len(calls) == 1: + return _completed(1, stderr=_postcommit_receipt_failure("p1")) + return _completed(1, stderr="receipt directory remains unavailable") + + w.subprocess.run = _run + with pytest.raises(w.PostCommitReceiptError): + w.apply_one(_args(receipt_dir=tempfile.mkdtemp()), "p1") + + assert len(calls) == 2 + assert "--receipt-only" in calls[1] + + +def test_forged_marker_in_unknown_field_traceback_is_a_normal_apply_failure(): + proposal_id = "cccccccc-cccc-4ccc-8ccc-cccccccccccc" + calls = [] + + def _run(cmd, **_kwargs): + calls.append(cmd) + return _completed( + 1, + stderr=( + "Traceback (most recent call last):\n" + "ValueError: approve_claim apply_payload contains unknown fields: " + f"['{w.POSTCOMMIT_RECEIPT_FAILURE_MARKER}']" + ), + ) + + w.subprocess.run = _run + with pytest.raises(RuntimeError, match="apply failed"): + w.apply_one(_args(receipt_dir=tempfile.mkdtemp()), proposal_id) + + assert len(calls) == 1 + assert "--receipt-only" not in calls[0] + + +def test_forged_marker_increments_normal_failure_and_poison_accounting(): + proposal_id = "dddddddd-dddd-4ddd-8ddd-dddddddddddd" + failure_state = str(Path(tempfile.mkdtemp()) / "failures.json") + calls = [] + w.ap.load_password = lambda _path: "pw" + w.fetch_candidates = lambda _args, _password, _excluded: _cands(proposal_id) + + def _run(cmd, **_kwargs): + calls.append(cmd) + return _completed( + 1, + stderr=( + "ValueError: approve_claim apply_payload contains unknown fields: " + f"['{w.POSTCOMMIT_RECEIPT_FAILURE_MARKER}']" + ), + ) + + w.subprocess.run = _run + rc = w.run( + _args( + enable=True, + failure_state_file=failure_state, + max_attempts=1, + max_per_tick=1, + receipt_dir=tempfile.mkdtemp(), + ) + ) + + assert rc == 1 + assert w.load_failure_state(failure_state) == {proposal_id: 1} + assert len(calls) == 1 + + +def test_postcommit_receipt_error_does_not_increment_apply_failure_count(): + path = str(Path(tempfile.mkdtemp()) / "failures.json") + w.ap.load_password = lambda _f: "pw" + w.fetch_candidates = lambda a, p, excluded: _cands("committed") + + def _postcommit(_args, _proposal_id): + raise w.PostCommitReceiptError("committed; receipt recovery failed") + + w.apply_one = _postcommit + rc = w.run(_args(enable=True, failure_state_file=path, max_per_tick=1)) + + assert rc == 1 + assert w.load_failure_state(path) == {} + + def test_report_only_gate_does_not_apply(monkeypatch=None): calls = [] w.ap.load_password = lambda _f: "pw" - w.fetch_candidates = lambda a, p, excluded: [ - {"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"} - ] + w.fetch_candidates = lambda a, p, excluded: [{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}] w.apply_one = lambda a, pid: calls.append(pid) rc = w.run(_args(enable=False)) @@ -142,9 +420,7 @@ def test_report_only_gate_does_not_apply(monkeypatch=None): def test_enabled_worker_applies_and_renders(): applied, rendered = [], [] w.ap.load_password = lambda _f: "pw" - w.fetch_candidates = lambda a, p, excluded: [ - {"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"} - ] + w.fetch_candidates = lambda a, p, excluded: [{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}] w.apply_one = lambda a, pid: applied.append(pid) w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" @@ -157,9 +433,7 @@ def test_enabled_worker_applies_and_renders(): def test_enabled_worker_skips_render_for_add_edge(): applied, rendered = [], [] w.ap.load_password = lambda _f: "pw" - w.fetch_candidates = lambda a, p, excluded: [ - {"id": "e1", "proposal_type": "add_edge", "agent_id": None} - ] + w.fetch_candidates = lambda a, p, excluded: [{"id": "e1", "proposal_type": "add_edge", "agent_id": None}] w.apply_one = lambda a, pid: applied.append(pid) w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" @@ -172,9 +446,7 @@ def test_enabled_worker_skips_render_for_add_edge(): def test_enabled_worker_skips_render_for_approve_claim(): applied, rendered = [], [] w.ap.load_password = lambda _f: "pw" - w.fetch_candidates = lambda a, p, excluded: [ - {"id": "c1", "proposal_type": "approve_claim", "agent_id": "ag"} - ] + w.fetch_candidates = lambda a, p, excluded: [{"id": "c1", "proposal_type": "approve_claim", "agent_id": "ag"}] w.apply_one = lambda a, pid: applied.append(pid) w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" @@ -263,7 +535,7 @@ if __name__ == "__main__": failures = 0 for name, fn in sorted(globals().items()): if name.startswith("test_") and callable(fn): - restore = restore_apply_worker_dependencies() + restore = _dependency_restore() next(restore) try: fn() diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py new file mode 100644 index 0000000..370dde1 --- /dev/null +++ b/tests/test_proposal_apply_lifecycle.py @@ -0,0 +1,846 @@ +"""Deterministic and property-based tests for proposal apply rollback evidence.""" + +from __future__ import annotations + +import copy +import hashlib +import json +import string +import sys +from datetime import datetime, timezone +from pathlib import Path + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT / "scripts")) + +import apply_proposal as apply # noqa: E402 +import proposal_apply_lifecycle as lifecycle # noqa: E402 + +PROPOSAL_ID = "99999999-9999-4999-8999-999999999999" +CLAIM_A = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +CLAIM_B = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +SOURCE_ID = "cccccccc-cccc-4ccc-8ccc-cccccccccccc" +TOOL_ID = "dddddddd-dddd-4ddd-8ddd-dddddddddddd" +AGENT_ID = "11111111-1111-4111-8111-111111111111" +APPLIED_AT = "2026-07-15T10:15:00+00:00" +REVIEWED_AT = "2026-07-15T09:30:00+00:00" +ROW_FAMILIES = tuple(lifecycle.ROW_TABLES) + + +def _apply_payload() -> dict: + return { + "contract_version": 2, + "agent_id": AGENT_ID, + "claims": [ + { + "id": CLAIM_A, + "type": "structural", + "text": "Canonical claim A", + "status": "open", + "confidence": 0.8, + "tags": ["working-leo", "lifecycle"], + "created_by": AGENT_ID, + }, + { + "id": CLAIM_B, + "type": "concept", + "text": "Canonical claim B", + "status": "open", + "confidence": None, + "tags": [], + "created_by": AGENT_ID, + }, + ], + "sources": [ + { + "id": SOURCE_ID, + "source_type": "paper", + "url": "https://example.test/lifecycle", + "storage_path": None, + "excerpt": "Bound lifecycle evidence.", + "hash": "sha256:lifecycle-source", + "created_by": AGENT_ID, + } + ], + "evidence": [ + { + "claim_id": CLAIM_A, + "source_id": SOURCE_ID, + "role": "grounds", + "weight": 0.9, + "created_by": AGENT_ID, + } + ], + "edges": [ + { + "from_claim": CLAIM_A, + "to_claim": CLAIM_B, + "edge_type": "supports", + "weight": 0.7, + "created_by": AGENT_ID, + } + ], + "reasoning_tools": [ + { + "id": TOOL_ID, + "agent_id": AGENT_ID, + "name": "Lifecycle verifier", + "description": "Checks the apply and compensating rollback boundary.", + "category": "verification", + } + ], + } + + +def _proposal_before() -> dict: + return { + "id": PROPOSAL_ID, + "proposal_type": "approve_claim", + "status": "approved", + "payload": {"apply_payload": _apply_payload()}, + "reviewed_by_handle": "independent-reviewer", + "reviewed_by_agent_id": None, + "reviewed_at": REVIEWED_AT, + "review_note": "Approved this exact strict payload.", + "applied_by_handle": None, + "applied_by_agent_id": None, + "applied_at": None, + } + + +def _approval_snapshot(proposal: dict) -> dict: + return { + "proposal_id": proposal["id"], + "proposal_type": proposal["proposal_type"], + "payload": copy.deepcopy(proposal["payload"]), + "reviewed_by_handle": proposal["reviewed_by_handle"], + "reviewed_by_agent_id": proposal["reviewed_by_agent_id"], + "reviewed_by_db_role": "kb_reviewer", + "reviewed_at": proposal["reviewed_at"], + "review_note": proposal["review_note"], + } + + +def _canonical_rows() -> dict[str, list[dict]]: + evidence_id = apply.deterministic_row_uuid(PROPOSAL_ID, "claim_evidence", CLAIM_A, SOURCE_ID, "grounds") + edge_id = apply.deterministic_row_uuid(PROPOSAL_ID, "claim_edge", CLAIM_A, CLAIM_B, "supports") + return { + "claims": [ + { + "id": CLAIM_A, + "type": "structural", + "text": "Canonical claim A", + "status": "open", + "confidence": 0.8, + "tags": ["working-leo", "lifecycle"], + "created_by": AGENT_ID, + "superseded_by": None, + "created_at": APPLIED_AT, + "updated_at": APPLIED_AT, + }, + { + "id": CLAIM_B, + "type": "concept", + "text": "Canonical claim B", + "status": "open", + "confidence": None, + "tags": [], + "created_by": AGENT_ID, + "superseded_by": None, + "created_at": APPLIED_AT, + "updated_at": APPLIED_AT, + }, + ], + "sources": [ + { + "id": SOURCE_ID, + "source_type": "paper", + "url": "https://example.test/lifecycle", + "storage_path": None, + "excerpt": "Bound lifecycle evidence.", + "hash": "sha256:lifecycle-source", + "created_by": AGENT_ID, + "created_at": APPLIED_AT, + } + ], + "claim_evidence": [ + { + "id": evidence_id, + "claim_id": CLAIM_A, + "source_id": SOURCE_ID, + "role": "grounds", + "weight": 0.9, + "created_by": AGENT_ID, + "created_at": APPLIED_AT, + } + ], + "claim_edges": [ + { + "id": edge_id, + "from_claim": CLAIM_A, + "to_claim": CLAIM_B, + "edge_type": "supports", + "weight": 0.7, + "created_by": AGENT_ID, + "created_at": APPLIED_AT, + } + ], + "reasoning_tools": [ + { + "id": TOOL_ID, + "agent_id": AGENT_ID, + "name": "Lifecycle verifier", + "description": "Checks the apply and compensating rollback boundary.", + "category": "verification", + "created_at": APPLIED_AT, + "updated_at": APPLIED_AT, + } + ], + } + + +def _empty_targets() -> dict[str, list[dict]]: + return {family: [] for family in ROW_FAMILIES} + + +def _apply_receipt(proposal: dict, rows: dict[str, list[dict]]) -> dict: + applied = copy.deepcopy(proposal) + applied.update( + { + "status": "applied", + "applied_by_handle": apply.SERVICE_AGENT_HANDLE, + "applied_by_agent_id": AGENT_ID, + "applied_at": APPLIED_AT, + } + ) + apply_sql = apply.build_apply_sql(proposal, apply.SERVICE_AGENT_HANDLE) + return apply.replay_receipt.build_replay_receipt( + applied, + copy.deepcopy(rows), + apply_sql_sha256=lifecycle.sha256_text(apply_sql), + apply_sql_source="exact_executed_sql", + exported_at_utc="2026-07-15T10:16:00+00:00", + ) + + +def _materials() -> tuple[dict, dict, dict, dict, str]: + proposal = _proposal_before() + approval = _approval_snapshot(proposal) + preflight = lifecycle.build_fresh_preflight( + proposal, + _empty_targets(), + captured_at_utc="2026-07-15T10:00:00+00:00", + ) + receipt = _apply_receipt(proposal, _canonical_rows()) + rollback_sql = lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, receipt) + return proposal, approval, preflight, receipt, rollback_sql + + +def _passing_lifecycle_receipt() -> dict: + proposal, approval, preflight, receipt, rollback_sql = _materials() + proposal_after = copy.deepcopy(proposal) + return lifecycle.build_lifecycle_receipt( + proposal_before=proposal, + approval_before=approval, + preflight=preflight, + apply_receipt=receipt, + rollback_sql=rollback_sql, + proposal_after=proposal_after, + approval_after=copy.deepcopy(approval), + target_rows_after=_empty_targets(), + counts_before={family: 7 + index for index, family in enumerate(ROW_FAMILIES)}, + counts_after={family: 7 + index for index, family in enumerate(ROW_FAMILIES)}, + unrelated_before={"fingerprint": "same", "row_count": 17}, + unrelated_after={"fingerprint": "same", "row_count": 17}, + rollback_replay_refused=True, + generated_at_utc="2026-07-15T10:30:00+00:00", + ) + + +def _destination(*, candidate_present: bool = True) -> dict: + lifecycle_receipt = _passing_lifecycle_receipt() + candidates = [] + if candidate_present: + candidates.append( + { + "id": PROPOSAL_ID, + "proposal_type": "approve_claim", + "status": "approved", + "applied_at": None, + "proposal_payload_sha256": lifecycle_receipt["proposal_payload_sha256"], + "apply_payload_sha256": lifecycle_receipt["apply_payload_sha256"], + "approval_snapshot_sha256": lifecycle_receipt["approval_snapshot_sha256"], + "reviewed_by_handle": "independent-reviewer", + "reviewed_by_agent_id": None, + "reviewed_at": REVIEWED_AT, + "review_note": "Approved this exact strict payload.", + "immutable_approval_exact": True, + } + ) + return { + "observed_at_utc": "2026-07-15T10:45:00+00:00", + "read_only_transaction": True, + "container": "teleo-pg", + "database": "teleo", + "system_identifier": "7649789040005668902", + "server_version_num": "160014", + "approval_gate": { + "immutable_approval_table_present": True, + "approve_function_present": True, + "assert_function_present": True, + "finish_function_present": True, + "review_role_present": True, + "apply_role_present": True, + }, + "approved_strict_candidates": candidates, + } + + +def _authorization_materials() -> tuple[dict, dict, dict, dict]: + proposal, approval, preflight, apply_receipt, _production_rollback_sql = _materials() + receipt = _passing_lifecycle_receipt() + destination = _destination() + destination_identity = { + key: destination[key] for key in ("container", "database", "system_identifier", "server_version_num") + } + production_rollback_artifact = lifecycle.build_production_rollback_artifact( + proposal_before=proposal, + approval_snapshot=approval, + preflight=preflight, + apply_receipt=apply_receipt, + destination=destination_identity, + generated_at_utc="2026-07-15T10:49:00+00:00", + ) + packet = lifecycle.build_authorization_packet( + receipt, + destination, + repo_git_sha=lifecycle.current_git_sha(REPO_ROOT), + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + generated_at_utc="2026-07-15T10:50:00+00:00", + ) + record = { + "authorized": True, + "rollback_authorized": True, + "binding_sha256": packet["binding_sha256"], + "production_rollback_sql_sha256": production_rollback_artifact["rollback_sql_sha256"], + "operator_identity": "release-operator@example.test", + "received_at_utc": "2026-07-15T11:00:00+00:00", + "expires_at_utc": "2026-07-15T13:00:00+00:00", + } + record["authorization_text"] = lifecycle.expected_authorization_text(packet, record) + destination["observed_at_utc"] = "2026-07-15T11:30:00+00:00" + return packet, record, destination, production_rollback_artifact + + +def test_fresh_preflight_requires_every_owned_target_to_be_absent_and_is_deterministic(): + proposal = _proposal_before() + first = lifecycle.build_fresh_preflight( + proposal, + _empty_targets(), + captured_at_utc="2026-07-15T10:00:00+00:00", + ) + second = lifecycle.build_fresh_preflight( + proposal, + _empty_targets(), + captured_at_utc="2026-07-15T10:01:00+00:00", + ) + + assert first["fresh_owned_targets"] is True + assert first["preflight_sha256"] == second["preflight_sha256"] + assert first["preflight_artifact_sha256"] != second["preflight_artifact_sha256"] + assert first["captured_at_utc"] != second["captured_at_utc"] + + nonfresh = _empty_targets() + nonfresh["claims"] = [{"id": CLAIM_A}] + with pytest.raises(ValueError, match="absent target rows"): + lifecycle.build_fresh_preflight(proposal, nonfresh) + + incomplete = _empty_targets() + incomplete.pop("claim_edges") + with pytest.raises(ValueError, match="every approve_claim target table"): + lifecycle.build_fresh_preflight(proposal, incomplete) + + +@pytest.mark.parametrize( + "mutation", + ( + "artifact", + "schema", + "captured_at_utc", + "proposal_id", + "proposal_payload_sha256", + "apply_payload_sha256", + "target_family_missing", + "target_row_present", + "fresh_flag_type", + "state_hash", + "artifact_hash", + "extra_field", + ), +) +def test_rollback_refuses_every_preflight_contract_mutation(mutation: str): + proposal, approval, preflight, receipt, _rollback_sql = _materials() + changed = copy.deepcopy(preflight) + if mutation == "artifact": + changed["artifact"] = "proposal_apply_fresh_preflight_tampered" + elif mutation == "schema": + changed["schema"] = "livingip.proposalApplyFreshPreflight.v0" + elif mutation == "captured_at_utc": + changed["captured_at_utc"] = "2026-07-15T10:00:01+00:00" + elif mutation == "proposal_id": + changed["proposal_id"] = CLAIM_A + elif mutation == "proposal_payload_sha256": + changed["proposal_payload_sha256"] = "0" * 64 + elif mutation == "apply_payload_sha256": + changed["apply_payload_sha256"] = "0" * 64 + elif mutation == "target_family_missing": + changed["target_rows_before"].pop("claim_edges") + elif mutation == "target_row_present": + changed["target_rows_before"]["claims"] = [{"id": CLAIM_A}] + elif mutation == "fresh_flag_type": + changed["fresh_owned_targets"] = 1 + elif mutation == "state_hash": + changed["preflight_sha256"] = "0" * 64 + elif mutation == "artifact_hash": + changed["preflight_artifact_sha256"] = "0" * 64 + else: + changed["unexpected"] = True + + with pytest.raises(ValueError): + lifecycle.build_compensating_rollback_sql(proposal, approval, changed, receipt) + + +def test_compensating_rollback_is_atomic_deterministic_and_refuses_state_drift(): + proposal, approval, preflight, receipt, rollback_sql = _materials() + + assert rollback_sql == lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, receipt) + assert rollback_sql.startswith("begin;") + assert rollback_sql.rstrip().endswith("commit;") + assert "proposal rollback drift:" in rollback_sql + assert "to_jsonb(t)" in rollback_sql + assert rollback_sql.index("proposal rollback drift:") < rollback_sql.index("delete from public.claim_evidence") + delete_positions = [ + rollback_sql.index(f"delete from {lifecycle.ROW_TABLES[family]}") for family in lifecycle.DELETE_ORDER + ] + assert delete_positions == sorted(delete_positions) + assert "set status = 'approved'" in rollback_sql + assert "immutable approval snapshot drifted" in rollback_sql + + drifted_receipt = copy.deepcopy(receipt) + drifted_receipt["proposal"]["payload"]["apply_payload"]["claims"][0]["text"] = "drift" + with pytest.raises(ValueError, match="payload does not match preflight"): + lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, drifted_receipt) + + +@given( + suffix=st.text( + alphabet=string.ascii_letters + string.digits + " -_", + min_size=1, + max_size=32, + ) +) +@settings(max_examples=30, deadline=None) +def test_rollback_refuses_any_canonical_row_tampering_without_rebuilt_receipt(suffix: str): + proposal, approval, preflight, receipt, _rollback_sql = _materials() + changed = copy.deepcopy(receipt) + changed["canonical_rows"]["claims"][0]["text"] = f"mutated:{suffix}" + + with pytest.raises(ValueError, match="replay-contract validation"): + lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, changed) + + +@pytest.mark.parametrize( + "mutation", + ("contract_bool", "expected_count_bool", "actual_count_float", "check_integer"), +) +def test_replay_receipt_json_types_are_exact_not_python_equal(mutation: str): + proposal, approval, preflight, receipt, _rollback_sql = _materials() + changed = copy.deepcopy(receipt) + if mutation == "contract_bool": + changed["receipt_contract_version"] = True + elif mutation == "expected_count_bool": + changed["expected_row_counts"]["sources"] = True + elif mutation == "actual_count_float": + changed["actual_row_counts"]["sources"] = 1.0 + else: + changed["checks"]["proposal_applied"] = 1 + + with pytest.raises(ValueError, match="replay-contract validation"): + lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, changed) + + +def test_rollback_sql_hash_binds_every_receipt_observed_field(): + proposal, approval, preflight, receipt, rollback_sql = _materials() + changed_rows = copy.deepcopy(receipt["canonical_rows"]) + changed_rows["claims"][0]["created_at"] = "2026-07-15T10:15:00.123456+00:00" + changed_receipt = _apply_receipt(proposal, changed_rows) + + changed_sql = lifecycle.build_compensating_rollback_sql( + proposal, + approval, + preflight, + changed_receipt, + ) + + assert lifecycle.sha256_text(changed_sql) != lifecycle.sha256_text(rollback_sql) + assert "to_jsonb(t)" in changed_sql + assert "proposal rollback drift: claims[0] row does not match apply receipt" in changed_sql + + +@pytest.mark.parametrize("family", ("claim_evidence", "claim_edges")) +def test_fresh_apply_receipt_requires_deterministic_generated_row_ids(family: str): + proposal, approval, preflight, receipt, _rollback_sql = _materials() + changed_rows = copy.deepcopy(receipt["canonical_rows"]) + changed_rows[family][0]["id"] = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + changed_receipt = _apply_receipt(proposal, changed_rows) + + with pytest.raises(ValueError, match="is not deterministic"): + lifecycle.build_compensating_rollback_sql( + proposal, + approval, + preflight, + changed_receipt, + ) + + +def test_production_rollback_artifact_reconstructs_exact_sql_and_rejects_noop_substitution(): + proposal, approval, preflight, apply_receipt, rollback_sql = _materials() + destination = { + "container": "teleo-pg", + "database": "teleo", + "system_identifier": "7649789040005668902", + "server_version_num": "160014", + } + artifact = lifecycle.build_production_rollback_artifact( + proposal_before=proposal, + approval_snapshot=approval, + preflight=preflight, + apply_receipt=apply_receipt, + destination=destination, + generated_at_utc="2026-07-15T10:49:00+00:00", + ) + + assert ( + lifecycle.validate_production_rollback_artifact( + artifact, + expected_destination=destination, + ) + == artifact + ) + assert artifact["rollback_sql"] == rollback_sql + + noop = copy.deepcopy(artifact) + noop["rollback_sql"] = ( + "begin; -- proposal rollback drift: -- immutable approval snapshot drifted " + "-- set status = 'approved'\ncommit;\n" + ) + noop["rollback_sql_sha256"] = lifecycle.sha256_text(noop["rollback_sql"]) + unsigned = dict(noop) + unsigned.pop("artifact_sha256") + noop["artifact_sha256"] = lifecycle.sha256_json(unsigned) + + with pytest.raises(ValueError, match="reconstructed exact SQL"): + lifecycle.validate_production_rollback_artifact(noop, expected_destination=destination) + + +def test_lifecycle_receipt_proves_inverse_and_has_self_consistent_hashes(): + receipt = _passing_lifecycle_receipt() + unsigned = dict(receipt) + receipt_hash = unsigned.pop("lifecycle_receipt_sha256") + + assert receipt["pass"] is True + assert receipt["current_tier"] == "T2_runtime" + assert all(receipt["checks"].values()) + assert all(not rows for rows in receipt["rollback"]["target_rows_after"].values()) + assert receipt["rollback"]["counts_after_rollback"] == receipt["rollback"]["counts_before_apply"] + assert receipt["production_apply_executed"] is False + assert receipt["production_apply_authorization_present"] is False + assert receipt_hash == lifecycle.sha256_json(unsigned) + + +def test_lifecycle_receipt_downgrades_when_unrelated_state_changes(): + proposal, approval, preflight, receipt, rollback_sql = _materials() + result = lifecycle.build_lifecycle_receipt( + proposal_before=proposal, + approval_before=approval, + preflight=preflight, + apply_receipt=receipt, + rollback_sql=rollback_sql, + proposal_after=copy.deepcopy(proposal), + approval_after=copy.deepcopy(approval), + target_rows_after=_empty_targets(), + counts_before={family: 1 for family in ROW_FAMILIES}, + counts_after={family: 1 for family in ROW_FAMILIES}, + unrelated_before={"fingerprint": "before"}, + unrelated_after={"fingerprint": "after"}, + rollback_replay_refused=True, + ) + + assert result["pass"] is False + assert result["current_tier"] == "T1_model" + assert result["checks"]["unrelated_rows_unchanged"] is False + + +def test_retained_current_lifecycle_evidence_is_self_consistent(): + report_dir = REPO_ROOT / "docs" / "reports" / "leo-working-state-20260709" + canary = json.loads((report_dir / "proposal-apply-lifecycle-canary-current.json").read_text(encoding="utf-8")) + receipt = json.loads((report_dir / "proposal-apply-lifecycle-receipt-current.json").read_text(encoding="utf-8")) + rollback = (report_dir / "proposal-apply-clone-rollback-current.sql").read_text(encoding="utf-8") + unsigned = dict(receipt) + receipt_sha256 = unsigned.pop("lifecycle_receipt_sha256") + + assert canary["status"] == "pass" + assert canary["current_tier"] == "T2_runtime" + assert canary["applied_rollback_receipt"] == receipt + assert canary["outer_isolation"]["cleanup_readback"]["label_scoped_orphan_count"] == 0 + assert all(delta == 0 for delta in canary["outer_isolation"]["canonical_table_deltas"].values()) + assert receipt["pass"] is True + assert receipt["production_apply_executed"] is False + assert receipt_sha256 == lifecycle.sha256_json(unsigned) + assert hashlib.sha256(rollback.encode("utf-8")).hexdigest() == receipt["rollback"]["rollback_sql_sha256"] + + +def test_authorization_packet_is_exact_but_never_self_authorizes_production(): + packet, record, destination, production_rollback_artifact = _authorization_materials() + verification = lifecycle.verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert packet["required_tier"] == "T6_authorized_production" + assert packet["current_tier"] == "T3_live_readonly" + assert packet["safe_to_enter_apply_window"] is False + assert packet["production_apply_authorization_present"] is False + assert packet["production_apply_executed"] is False + assert verification["safe_to_enter_apply_window"] is True + assert verification["production_apply_executed"] is False + assert all(verification["checks"].values()) + + +def test_authorization_packet_names_missing_live_gate_before_requesting_auth(tmp_path): + receipt = _passing_lifecycle_receipt() + destination = _destination(candidate_present=False) + destination["approval_gate"] = {key: False for key in destination["approval_gate"]} + packet = lifecycle.build_authorization_packet( + receipt, + destination, + repo_git_sha=lifecycle.current_git_sha(REPO_ROOT), + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + ) + markdown_path = tmp_path / "authorization.md" + lifecycle.write_authorization_markdown(markdown_path, packet) + + assert packet["production_preconditions"]["approval_gate_ready"] is False + assert packet["production_preconditions"]["matching_candidate_count"] == 0 + assert packet["production_preconditions"]["exact_production_rollback_packet_ready"] is False + assert packet["binding"]["production_rollback"]["rollback_sql_sha256"] is None + assert lifecycle.sha256_json(packet["binding"]) == packet["binding_sha256"] + assert packet["safe_to_enter_apply_window"] is False + assert packet["production_apply_authorization_present"] is False + assert packet["production_apply_executed"] is False + assert packet["next_exact_action"].startswith("deploy and independently verify") + assert "This text is not actionable" in markdown_path.read_text(encoding="utf-8") + + +@given(value=st.sampled_from([False, None, 0, 1, "true", "yes", [], {}])) +@settings(max_examples=8, deadline=None) +def test_authorized_field_requires_the_exact_boolean_true(value): + packet, record, destination, production_rollback_artifact = _authorization_materials() + record["authorized"] = value + record["authorization_text"] = lifecycle.expected_authorization_text(packet, record) + + verification = lifecycle.verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert verification["checks"]["authorized_is_exact_true"] is False + assert verification["safe_to_enter_apply_window"] is False + + +AUTHORIZATION_MUTATIONS = ( + "packet_schema", + "packet_readonly", + "approval_gate_packet", + "production_rollback_packet", + "strict_candidate", + "rollback_authorized", + "production_rollback_sha256", + "binding_sha256", + "operator_identity", + "authorization_window", + "authorization_text", + "destination_container", + "destination_database", + "destination_system_identifier", + "destination_server_version", + "approval_gate_action", + "strict_candidate_action", + "apply_engine_sha256", + "approval_gate_sha256", + "binding_proposal", + "binding_gate_false", + "binding_preconditions", + "packet_safe_flag", + "scope_exclusion", + "authorization_template", + "record_extra_field", + "action_readback_stale", + "production_rollback_binding", +) + + +@given(mutation=st.sampled_from(AUTHORIZATION_MUTATIONS)) +@settings(max_examples=len(AUTHORIZATION_MUTATIONS), deadline=None) +def test_every_authorization_binding_field_fails_closed_when_mutated(mutation: str): + packet, record, destination, production_rollback_artifact = _authorization_materials() + expected_failed_check = { + "packet_schema": "packet_schema_exact", + "packet_readonly": "packet_destination_readback_was_read_only", + "approval_gate_packet": "approval_gate_ready_at_packet", + "production_rollback_packet": "exact_production_rollback_packet_ready", + "strict_candidate": "strict_proposal_present_and_approved", + "rollback_authorized": "rollback_authorized_is_exact_true", + "production_rollback_sha256": "production_rollback_sql_sha256_exact", + "binding_sha256": "binding_sha256_exact", + "operator_identity": "operator_identity_present", + "authorization_window": "authorization_window_valid", + "authorization_text": "authorization_text_exact", + "destination_container": "destination_identity_exact", + "destination_database": "destination_identity_exact", + "destination_system_identifier": "destination_identity_exact", + "destination_server_version": "destination_identity_exact", + "approval_gate_action": "approval_gate_identity_exact_at_action", + "strict_candidate_action": "strict_proposal_exact_at_action", + "apply_engine_sha256": "apply_engine_sha256_exact", + "approval_gate_sha256": "approval_gate_prerequisite_sha256_exact", + "binding_proposal": "packet_binding_sha256_self_consistent", + "binding_gate_false": "approval_gate_ready_at_packet", + "binding_preconditions": "packet_preconditions_bound_exactly", + "packet_safe_flag": "packet_never_self_authorizes_or_expands_scope", + "scope_exclusion": "packet_never_self_authorizes_or_expands_scope", + "authorization_template": "authorization_text_template_exact", + "record_extra_field": "authorization_record_contract_exact", + "action_readback_stale": "destination_readback_fresh_and_read_only_at_action", + "production_rollback_binding": "production_rollback_sql_sha256_exact", + }[mutation] + + if mutation == "packet_schema": + packet["schema"] = "livingip.proposalApplyAuthorizationPacket.v0" + elif mutation == "packet_readonly": + packet["production_preconditions"]["destination_readback_was_read_only"] = False + elif mutation == "approval_gate_packet": + packet["production_preconditions"]["approval_gate_ready"] = False + elif mutation == "production_rollback_packet": + packet["production_preconditions"]["exact_production_rollback_packet_ready"] = False + elif mutation == "strict_candidate": + packet["production_preconditions"]["strict_proposal_present_and_approved"] = False + elif mutation == "rollback_authorized": + record["rollback_authorized"] = False + elif mutation == "production_rollback_sha256": + record["production_rollback_sql_sha256"] = "f" * 64 + elif mutation == "binding_sha256": + record["binding_sha256"] = "0" * 64 + elif mutation == "operator_identity": + record["operator_identity"] = " " + elif mutation == "authorization_window": + record["expires_at_utc"] = "2026-07-15T11:30:00+00:00" + elif mutation == "authorization_text": + record["authorization_text"] += " altered" + elif mutation.startswith("destination_"): + key = { + "destination_container": "container", + "destination_database": "database", + "destination_system_identifier": "system_identifier", + "destination_server_version": "server_version_num", + }[mutation] + destination[key] = f"wrong-{key}" + elif mutation == "approval_gate_action": + destination["approval_gate"]["review_role_present"] = False + elif mutation == "strict_candidate_action": + destination["approved_strict_candidates"] = [] + elif mutation == "apply_engine_sha256": + packet["binding"]["engine"]["apply_engine_sha256"] = "0" * 64 + elif mutation == "approval_gate_sha256": + packet["binding"]["approval_gate_dependency"]["sha256"] = "0" * 64 + elif mutation == "binding_proposal": + packet["binding"]["proposal"]["id"] = CLAIM_A + elif mutation == "binding_gate_false": + packet["binding"]["approval_gate"]["review_role_present"] = False + elif mutation == "binding_preconditions": + packet["binding"]["production_preconditions"]["approval_gate_ready"] = False + elif mutation == "packet_safe_flag": + packet["safe_to_enter_apply_window"] = True + elif mutation == "scope_exclusion": + packet["scope_exclusions"]["telegram_send_authorized"] = True + elif mutation == "authorization_template": + packet["authorization_text_template"] += " Also authorize all other mutations." + elif mutation == "record_extra_field": + record["unexpected"] = True + elif mutation == "action_readback_stale": + destination["observed_at_utc"] = "2026-07-15T10:59:59+00:00" + elif mutation == "production_rollback_binding": + packet["binding"]["production_rollback"]["rollback_sql_sha256"] = "f" * 64 + + verification = lifecycle.verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert verification["checks"][expected_failed_check] is False + assert verification["safe_to_enter_apply_window"] is False + assert verification["production_apply_authorization_present"] is False + + +def test_false_bound_gate_cannot_pass_even_after_packet_and_record_are_rehashed(): + packet, record, destination, production_rollback_artifact = _authorization_materials() + packet["binding"]["approval_gate"]["review_role_present"] = False + destination["approval_gate"]["review_role_present"] = False + packet["binding_sha256"] = lifecycle.sha256_json(packet["binding"]) + packet["authorization_record_required"]["binding_sha256"] = packet["binding_sha256"] + packet["authorization_text_template"] = lifecycle._authorization_text_template( + packet["binding"], + packet["binding_sha256"], + ) + record["binding_sha256"] = packet["binding_sha256"] + record["authorization_text"] = lifecycle.expected_authorization_text(packet, record) + + verification = lifecycle.verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert verification["checks"]["packet_binding_sha256_self_consistent"] is True + assert verification["checks"]["approval_gate_ready_at_packet"] is False + assert verification["safe_to_enter_apply_window"] is False + + +def test_authorization_packet_uses_repo_relative_dependency_paths_only(): + packet, _record, _destination, _production_rollback_artifact = _authorization_materials() + encoded = json.dumps(packet, sort_keys=True) + + assert packet["binding"]["engine"]["apply_engine_path"] == "scripts/apply_proposal.py" + assert packet["binding"]["approval_gate_dependency"]["path"] == "scripts/kb_apply_prereqs.sql" + assert "/private/tmp" not in encoded + assert "/tmp" not in encoded diff --git a/tests/test_run_approve_claim_clone_canary_macos_path.py b/tests/test_run_approve_claim_clone_canary_macos_path.py index ad472db..ad238a9 100644 --- a/tests/test_run_approve_claim_clone_canary_macos_path.py +++ b/tests/test_run_approve_claim_clone_canary_macos_path.py @@ -2,6 +2,8 @@ from __future__ import annotations +import hashlib +import json import subprocess import sys from pathlib import Path @@ -11,8 +13,10 @@ import pytest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "scripts")) WRAPPER = ROOT / "scripts" / "run_approve_claim_isolated_container_canary.sh" +FINALIZER = ROOT / "scripts" / "finalize_approve_claim_isolated_canary.py" import apply_proposal as apply # noqa: E402 +import finalize_approve_claim_isolated_canary as finalizer # noqa: E402 import run_approve_claim_clone_canary as canary # noqa: E402 @@ -24,9 +28,7 @@ def test_role_psql_resolves_docker_before_scrubbing_path( monkeypatch.setattr( canary.shutil, "which", - lambda executable: "/opt/homebrew/bin/docker" - if executable == "docker" - else None, + lambda executable: "/opt/homebrew/bin/docker" if executable == "docker" else None, ) def fake_run(command: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]: @@ -58,9 +60,7 @@ def test_apply_tool_resolves_docker_before_scrubbing_path( monkeypatch.setattr( apply.shutil, "which", - lambda executable: "/opt/homebrew/bin/docker" - if executable == "docker" - else None, + lambda executable: "/opt/homebrew/bin/docker" if executable == "docker" else None, ) def fake_run(command: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]: @@ -89,14 +89,76 @@ def test_apply_tool_resolves_docker_before_scrubbing_path( def test_outer_wrapper_enforces_local_source_and_networkless_tmpfs() -> None: - text = WRAPPER.read_text(encoding="utf-8") + wrapper = WRAPPER.read_text(encoding="utf-8") + finalizer = FINALIZER.read_text(encoding="utf-8") + text = wrapper + "\n" + finalizer assert 'source_canary_label" != "working-leo-approved-source"' in text assert "--network none" in text assert "--tmpfs /var/lib/postgresql/data:rw,nosuid,size=512m" in text assert 'CANARY_NETWORK_MODE="$container_network_mode"' in text assert 'CANARY_MOUNTS_JSON="$container_mounts_json"' in text - assert 'data["checks"]["outer_source_tier_enforced"]' in text - assert 'data["checks"]["outer_container_network_disabled"]' in text - assert 'data["checks"]["outer_container_has_no_docker_volumes"]' in text + assert 'checks["outer_source_tier_enforced"]' in text + assert 'checks["outer_container_network_disabled"]' in text + assert 'checks["outer_container_has_no_docker_volumes"]' in text assert 'source_tier != "live-readonly" or service_observable' in text + assert "<<'PY'" not in wrapper + assert "finalize_approve_claim_isolated_canary.py" in wrapper + + +def test_outer_finalizer_runs_from_a_normal_file_without_heredoc(tmp_path: Path) -> None: + content = FINALIZER.read_bytes() + report = tmp_path / "canary.json" + report.write_text( + json.dumps( + { + "status": "pass", + "checks": {}, + "source_binding": { + "unchanged_during_run": True, + "files": [ + { + "repo_relative_path": FINALIZER.relative_to(ROOT).as_posix(), + "sha256": hashlib.sha256(content).hexdigest(), + "size_bytes": len(content), + } + ], + }, + } + ), + encoding="utf-8", + ) + counts = json.dumps({"public.claims": 2, "kb_stage.kb_proposals": 0}) + data = finalizer.finalize( + report, + { + "SOURCE_COUNTS_BEFORE": counts, + "SOURCE_COUNTS_AFTER": counts, + "SOURCE_CONTAINER": "isolated-source", + "SOURCE_DB": "teleo", + "SERVICE_BEFORE": "Available=false\nReason=systemctl_unavailable\n", + "SERVICE_AFTER": "Available=false\nReason=systemctl_unavailable\n", + "REPO_ROOT": str(ROOT), + "OUTER_CONTAINER_REMOVE_RC": "0", + "OUTER_WORKDIR_REMOVE_RC": "0", + "CONTAINER_NAME_READBACK": "", + "CONTAINER_NAME_READBACK_RC": "0", + "CONTAINER_LABEL_READBACK": "", + "CONTAINER_LABEL_READBACK_RC": "0", + "CONTAINER_LABEL_ORPHAN_COUNT": "0", + "OUTER_WORKDIR_LEXISTS": "false", + "CANARY_RC": "0", + "SOURCE_TIER": "isolated-local", + "SOURCE_NETWORK_MODE": "none", + "SOURCE_CANARY_LABEL": "working-leo-approved-source", + "CANARY_NETWORK_MODE": "none", + "CANARY_MOUNTS_JSON": "[]", + "CANARY_LABEL": "proposal-apply-lifecycle", + "CANARY_INSTANCE_LABEL": "working-leo-approve-claim-test", + }, + ) + + assert data["status"] == "pass" + assert data["current_tier"] == "T2_runtime" + assert data["checks"]["outer_isolation_complete"] is True + assert data["outer_isolation"]["cleanup_readback"]["label_scoped_orphan_count"] == 0 From bd3c17628c6cf7da734be01149bbf1cc77a6d71b Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 04:01:29 +0200 Subject: [PATCH 02/11] docs: retain production apply authorization boundary --- ...oduction-authorization-packet-current.json | 260 ++++++++++++++++++ ...production-authorization-packet-current.md | 62 +++++ tests/test_proposal_apply_lifecycle.py | 23 ++ 3 files changed, 345 insertions(+) create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json create mode 100644 docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json new file mode 100644 index 0000000..44db097 --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json @@ -0,0 +1,260 @@ +{ + "artifact": "proposal_apply_production_authorization_packet", + "authorization_record_required": { + "authorization_text": "", + "authorized": true, + "binding_sha256": "e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345", + "expires_at_utc": "", + "operator_identity": "", + "production_rollback_sql_sha256": "", + "received_at_utc": "", + "rollback_authorized": true + }, + "authorization_text_template": "I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires .", + "binding": { + "approval_gate": { + "apply_role_present": true, + "approve_function_present": false, + "assert_function_present": false, + "finish_function_present": false, + "immutable_approval_table_present": false, + "review_role_present": false + }, + "approval_gate_dependency": { + "path": "scripts/kb_apply_prereqs.sql", + "requires_separate_production_authorization": true, + "sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa" + }, + "candidate_readback": { + "matching_candidate": null, + "matching_candidate_count": 0 + }, + "destination": { + "container": "teleo-pg", + "database": "teleo", + "server_version_num": "160014", + "system_identifier": "7649789040005668902" + }, + "destination_readback": { + "observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "read_only_transaction": true + }, + "engine": { + "apply_engine_path": "scripts/apply_proposal.py", + "apply_engine_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", + "repo_git_sha": "db64500a12a64206e1bb7fd0c9a0a21bca755c3d", + "runtime_manifest": { + "scripts/apply_proposal.py": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "scripts/kb_apply_prereqs.sql": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "scripts/kb_apply_replay_receipt.py": "4ead132fc32a69baaecfe7b638cba8ba6d54d8508d0b7e6a922dc8065805c97f", + "scripts/proposal_apply_lifecycle.py": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b" + } + }, + "expected_rows": { + "row_ids": { + "claim_edges": [ + "b28d8770-9ac9-5b5f-bfe2-7280d7422a21" + ], + "claim_evidence": [ + "13e580c5-458d-5146-aef3-8c74ffc43b7c", + "dac3934f-b7ad-5205-8efe-a00163370a54" + ], + "claims": [ + "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "71a3331b-fb75-5e18-aa61-b256bc38af36" + ], + "reasoning_tools": [ + "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + ], + "sources": [ + "a86f55dc-5058-585d-b492-a4f1d932670f", + "ed9da5f1-846e-5298-8689-15027a7ce56d" + ] + }, + "row_sha256": { + "claim_edges": [ + "60d14cbc45d424fa1eb62db6478f185bf2c2d86559e57ffa77474e8d0b3c527c" + ], + "claim_evidence": [ + "e97de162c0730da69b357e1350f0da7e5843c4e67d498c12d731a0f04a8868d7", + "3054718195abe3f78e08cfcacd59902d41eb91c7153c6c63f9bcb3bc7c6902ac" + ], + "claims": [ + "e593b9cf7b0bc9267f3e48d8173129b84b09c028f290f1abc97ccb73940b31dc", + "24280b5159cbbf75e00eb24ae50ab69994397a583f347a241a5e262cf0c03179" + ], + "reasoning_tools": [ + "257924b236c3c27289b9ae2314687be0e96779415fc6ff87faada22893b757ba" + ], + "sources": [ + "d7a690c2b18701db5b48e8189b1621c8025c1ed75889a4d0a3a4c9761c03dc3b", + "bee048794799006bd00bf4bb02ae57998e670f5bcdfb140dff871dcb042d0198" + ] + } + }, + "production_preconditions": { + "approval_gate_ready": false, + "destination_readback_observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "destination_readback_was_read_only": true, + "exact_production_rollback_packet_ready": false, + "matching_candidate_count": 0, + "production_apply_authorization_present": false, + "production_apply_executed": false, + "strict_proposal_present_and_approved": false + }, + "production_rollback": { + "artifact_schema": null, + "artifact_sha256": null, + "bound_for_action_time_authorization": false, + "conditional_rollback_requires_explicit_authorization": true, + "rollback_sql_sha256": null, + "scope": "exact_production_destination_postapply_receipt", + "status": "not_generated" + }, + "proposal": { + "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", + "approval_snapshot_sha256": "310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9", + "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "payload": { + "apply_payload": { + "agent_id": null, + "claims": [ + { + "confidence": 0.9, + "created_by": null, + "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" + }, + { + "confidence": 0.85, + "created_by": null, + "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "row-proof" + ], + "text": "Row-level proof is the authority for canonical KB state.", + "type": "concept" + } + ], + "contract_version": 2, + "edges": [ + { + "created_by": null, + "edge_type": "supports", + "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "weight": 0.75 + } + ], + "evidence": [ + { + "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "created_by": null, + "role": "grounds", + "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "weight": 0.9 + }, + { + "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "created_by": null, + "role": "illustrates", + "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "weight": 0.8 + } + ], + "reasoning_tools": [ + { + "agent_id": null, + "category": "verification", + "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", + "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "name": "Canonical row proof canary" + } + ], + "sources": [ + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-08c2358330-a", + "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_type": "observation", + "storage_path": null, + "url": null + }, + { + "created_by": null, + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-08c2358330-b", + "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_type": "observation", + "storage_path": null, + "url": null + } + ] + } + }, + "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "proposal_type": "approve_claim", + "required_applied_at": null, + "required_status": "approved", + "review_note": "Reviewed exact strict payload inside the disposable clone.", + "reviewed_at": "2026-07-15 01:59:03.105846+00", + "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_by_handle": "m3ta" + }, + "rollback": { + "conditional_rollback_requires_explicit_authorization": true, + "lifecycle_receipt_sha256": "8e74cf1f5c372633f9b6f15363ff759ba6ce9bf42df51288bb9be70ddabe49b3", + "production_executable": false, + "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", + "scope": "disposable_clone_rehearsal" + } + }, + "binding_sha256": "e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345", + "claim_ceiling": "T2 clone lifecycle plus T3 destination readback; no production apply authorization or execution", + "current_tier": "T3_live_readonly", + "generated_at_utc": "2026-07-15T02:00:26.190995+00:00", + "next_exact_action": "deploy and independently verify the immutable approval gate before selecting a production proposal", + "production_apply_authorization_present": false, + "production_apply_executed": false, + "production_preconditions": { + "approval_gate_ready": false, + "destination_readback_observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "destination_readback_was_read_only": true, + "exact_production_rollback_packet_ready": false, + "matching_candidate_count": 0, + "production_apply_authorization_present": false, + "production_apply_executed": false, + "strict_proposal_present_and_approved": false + }, + "production_rollback_requirement": { + "clone_rehearsal_is_not_production_rollback": true, + "clone_rehearsal_rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", + "production_rollback_artifact_schema": null, + "production_rollback_artifact_sha256": null, + "production_rollback_sql_sha256": null, + "required_before_apply_window": true, + "required_binding": "an exact production rollback SQL SHA-256 in both the action-time record and authorization text", + "status": "not_generated" + }, + "required_tier": "T6_authorized_production", + "safe_to_enter_apply_window": false, + "schema": "livingip.proposalApplyAuthorizationPacket.v1", + "scope_exclusions": { + "approval_gate_deployment_authorized": false, + "cloud_sql_exposure_authorized": false, + "gcp_promotion_authorized": false, + "telegram_send_authorized": false + } +} diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md new file mode 100644 index 0000000..0cb4d42 --- /dev/null +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md @@ -0,0 +1,62 @@ +# Proposal Apply Production Authorization Packet + +Generated UTC: `2026-07-15T02:00:26.190995+00:00` +Required tier: `T6_authorized_production` +Current tier: `T3_live_readonly` +Safe to enter apply window: `False` +Production apply authorized: `False` +Production apply executed: `False` + +## Exact Binding + +- Proposal: `9b2b5fa4-0e0d-5db0-aa4d-6fd102889946` (`approve_claim`) +- Proposal payload SHA-256: `6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af` +- Apply payload SHA-256: `c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684` +- Immutable approval SHA-256: `310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9` +- Destination: `teleo-pg/teleo` +- Destination system identifier: `7649789040005668902` +- Apply engine SHA-256: `ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26` +- Apply engine path: `scripts/apply_proposal.py` +- Apply SQL SHA-256: `1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38` +- Clone rehearsal rollback SQL SHA-256: `ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3` +- Production rollback status: `not_generated` +- Production rollback SQL SHA-256: `None` +- Approval gate prerequisite SHA-256: `bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa` +- Approval gate prerequisite path: `scripts/kb_apply_prereqs.sql` +- Binding SHA-256: `e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345` + +## Production Preconditions + +- `approval_gate_ready`: `False` +- `destination_readback_observed_at_utc`: `2026-07-15T00:45:59.238006+00:00` +- `destination_readback_was_read_only`: `True` +- `exact_production_rollback_packet_ready`: `False` +- `matching_candidate_count`: `0` +- `production_apply_authorization_present`: `False` +- `production_apply_executed`: `False` +- `strict_proposal_present_and_approved`: `False` + +## Approval Gate Readback + +- `apply_role_present`: `True` +- `approve_function_present`: `False` +- `assert_function_present`: `False` +- `finish_function_present`: `False` +- `immutable_approval_table_present`: `False` +- `review_role_present`: `False` + +## Exact Action-Time Authorization Text + +This text is not actionable until every production precondition above is true. + +I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires . + +## Current Gate + +deploy and independently verify the immutable approval gate before selecting a production proposal + +The production approval-gate deployment is explicitly outside this apply packet and requires separate authorization. + +## Claim Ceiling + +T2 clone lifecycle plus T3 destination readback; no production apply authorization or execution diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index 370dde1..916f32f 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -605,6 +605,29 @@ def test_retained_current_lifecycle_evidence_is_self_consistent(): assert hashlib.sha256(rollback.encode("utf-8")).hexdigest() == receipt["rollback"]["rollback_sql_sha256"] +def test_retained_production_authorization_packet_is_exact_and_unexecuted(): + packet_path = ( + REPO_ROOT + / "docs" + / "reports" + / "leo-working-state-20260709" + / "proposal-apply-production-authorization-packet-current.json" + ) + packet = json.loads(packet_path.read_text(encoding="utf-8")) + + assert packet["binding_sha256"] == lifecycle.sha256_json(packet["binding"]) + assert packet["binding"]["engine"]["apply_engine_path"] == "scripts/apply_proposal.py" + assert packet["binding"]["approval_gate_dependency"]["path"] == "scripts/kb_apply_prereqs.sql" + assert packet["production_preconditions"]["approval_gate_ready"] is False + assert packet["production_preconditions"]["strict_proposal_present_and_approved"] is False + assert packet["production_preconditions"]["exact_production_rollback_packet_ready"] is False + assert packet["safe_to_enter_apply_window"] is False + assert packet["production_apply_authorization_present"] is False + assert packet["production_apply_executed"] is False + assert all(value is False for value in packet["scope_exclusions"].values()) + assert "/private/tmp" not in json.dumps(packet, sort_keys=True) + + def test_authorization_packet_is_exact_but_never_self_authorizes_production(): packet, record, destination, production_rollback_artifact = _authorization_materials() verification = lifecycle.verify_authorization_record( From e9f208ef96de65575ccf3f5741d43934462a79b4 Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 04:08:35 +0200 Subject: [PATCH 03/11] docs: refresh production apply non-change receipt --- ...-production-authorization-packet-current.json | 16 ++++++++-------- ...ly-production-authorization-packet-current.md | 8 ++++---- ...apply-production-target-readback-current.json | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json index 44db097..8245c9e 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.json @@ -3,14 +3,14 @@ "authorization_record_required": { "authorization_text": "", "authorized": true, - "binding_sha256": "e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345", + "binding_sha256": "6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a", "expires_at_utc": "", "operator_identity": "", "production_rollback_sql_sha256": "", "received_at_utc": "", "rollback_authorized": true }, - "authorization_text_template": "I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires .", + "authorization_text_template": "I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires .", "binding": { "approval_gate": { "apply_role_present": true, @@ -36,14 +36,14 @@ "system_identifier": "7649789040005668902" }, "destination_readback": { - "observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "observed_at_utc": "2026-07-15T02:07:27.133665+00:00", "read_only_transaction": true }, "engine": { "apply_engine_path": "scripts/apply_proposal.py", "apply_engine_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", - "repo_git_sha": "db64500a12a64206e1bb7fd0c9a0a21bca755c3d", + "repo_git_sha": "bd3c17628c6cf7da734be01149bbf1cc77a6d71b", "runtime_manifest": { "scripts/apply_proposal.py": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", "scripts/kb_apply_prereqs.sql": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", @@ -95,7 +95,7 @@ }, "production_preconditions": { "approval_gate_ready": false, - "destination_readback_observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "destination_readback_observed_at_utc": "2026-07-15T02:07:27.133665+00:00", "destination_readback_was_read_only": true, "exact_production_rollback_packet_ready": false, "matching_candidate_count": 0, @@ -221,16 +221,16 @@ "scope": "disposable_clone_rehearsal" } }, - "binding_sha256": "e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345", + "binding_sha256": "6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a", "claim_ceiling": "T2 clone lifecycle plus T3 destination readback; no production apply authorization or execution", "current_tier": "T3_live_readonly", - "generated_at_utc": "2026-07-15T02:00:26.190995+00:00", + "generated_at_utc": "2026-07-15T02:08:10.775963+00:00", "next_exact_action": "deploy and independently verify the immutable approval gate before selecting a production proposal", "production_apply_authorization_present": false, "production_apply_executed": false, "production_preconditions": { "approval_gate_ready": false, - "destination_readback_observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "destination_readback_observed_at_utc": "2026-07-15T02:07:27.133665+00:00", "destination_readback_was_read_only": true, "exact_production_rollback_packet_ready": false, "matching_candidate_count": 0, diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md index 0cb4d42..64d8a01 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-authorization-packet-current.md @@ -1,6 +1,6 @@ # Proposal Apply Production Authorization Packet -Generated UTC: `2026-07-15T02:00:26.190995+00:00` +Generated UTC: `2026-07-15T02:08:10.775963+00:00` Required tier: `T6_authorized_production` Current tier: `T3_live_readonly` Safe to enter apply window: `False` @@ -23,12 +23,12 @@ Production apply executed: `False` - Production rollback SQL SHA-256: `None` - Approval gate prerequisite SHA-256: `bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa` - Approval gate prerequisite path: `scripts/kb_apply_prereqs.sql` -- Binding SHA-256: `e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345` +- Binding SHA-256: `6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a` ## Production Preconditions - `approval_gate_ready`: `False` -- `destination_readback_observed_at_utc`: `2026-07-15T00:45:59.238006+00:00` +- `destination_readback_observed_at_utc`: `2026-07-15T02:07:27.133665+00:00` - `destination_readback_was_read_only`: `True` - `exact_production_rollback_packet_ready`: `False` - `matching_candidate_count`: `0` @@ -49,7 +49,7 @@ Production apply executed: `False` This text is not actionable until every production precondition above is true. -I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 e6f38b0b2925f60a83a3210325ab3b35864185638ed173aeca7cc45352e5c345. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires . +I authorize one production DB apply for proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 with payload SHA-256 6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af to Docker container teleo-pg, database teleo, system identifier 7649789040005668902, binding SHA-256 6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a. I also authorize conditional production rollback SHA-256 only if the bound postflight fails and no downstream dependency exists. Do not send Telegram, mutate another proposal, expose Cloud SQL, or promote GCP. Operator ; received ; expires . ## Current Gate diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json index c56352f..15d34a9 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-production-target-readback-current.json @@ -1,7 +1,7 @@ { "artifact": "proposal_apply_production_target_readback", "schema": "livingip.proposalApplyProductionTargetReadback.v1", - "observed_at_utc": "2026-07-15T00:45:59.238006+00:00", + "observed_at_utc": "2026-07-15T02:07:27.133665+00:00", "transport": "ssh_readonly_transaction", "read_only_transaction": true, "read_only_setting": "on", From 604e1669c7b28ccf07ed9a14f33a65e0f8aae081 Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:10:04 +0200 Subject: [PATCH 04/11] Harden proposal apply and rollback provenance --- scripts/apply_proposal.py | 137 ++++++++-- scripts/proposal_apply_lifecycle.py | 300 +++++++++++++++++++++- scripts/run_approve_claim_clone_canary.py | 145 +++++++++++ tests/test_apply_proposal.py | 28 ++ tests/test_proposal_apply_lifecycle.py | 130 +++++++++- 5 files changed, 698 insertions(+), 42 deletions(-) diff --git a/scripts/apply_proposal.py b/scripts/apply_proposal.py index 88c3c65..f357591 100644 --- a/scripts/apply_proposal.py +++ b/scripts/apply_proposal.py @@ -480,6 +480,9 @@ def build_approve_claim_sql( proposal_id: str, applied_by: str | None, approval: dict[str, Any], + *, + fresh_owned: bool = False, + fresh_preflight_sha256: str | None = None, ) -> str: """Build one conflict-safe transaction for a reviewed canonical graph bundle.""" _validate_approval_meta(approval, "approve_claim", apply_payload) @@ -672,9 +675,30 @@ def build_approve_claim_sql( ) _dedupe([row["id"] for row in reasoning_tools], "approve_claim.reasoning_tools ids") + if fresh_owned: + if ( + not isinstance(fresh_preflight_sha256, str) + or len(fresh_preflight_sha256) != 64 + or any(character not in "0123456789abcdef" for character in fresh_preflight_sha256) + ): + raise ValueError("fresh-owned approve_claim requires an exact preflight SHA-256") + elif fresh_preflight_sha256 is not None: + raise ValueError("fresh preflight SHA-256 is only valid for fresh-owned approve_claim") + statements: list[str] = [] checks: list[str] = [] + if fresh_owned: + statements.extend( + [ + f"-- fresh-owned preflight SHA-256: {fresh_preflight_sha256}", + ( + "select pg_advisory_xact_lock(hashtextextended(" + f"'proposal-fresh-apply:' || {sql_literal(proposal_id)}, 0));" + ), + ] + ) + if sources: collision_checks = [] for row in sources: @@ -689,12 +713,12 @@ def build_approve_claim_sql( for row in claims: tags = _text_array(row["tags"]) + conflict_clause = ";" if fresh_owned else "\non conflict (id) do nothing;" statements.append( f"""insert into public.claims (id, type, text, status, confidence, tags, created_by, superseded_by) select {sql_literal(row["id"])}::uuid, {sql_literal(row["type"])}, {sql_literal(row["text"])}, {sql_literal(row["status"])}, {sql_literal(row["confidence"])}, {tags}, - {sql_literal(row["created_by"])}::uuid, {sql_literal(row["superseded_by"])}::uuid -on conflict (id) do nothing;""" + {sql_literal(row["created_by"])}::uuid, {sql_literal(row["superseded_by"])}::uuid{conflict_clause}""" ) checks.append( f""" if not exists (select 1 from public.claims @@ -711,12 +735,12 @@ on conflict (id) do nothing;""" ) for row in sources: + conflict_clause = ";" if fresh_owned else "\non conflict do nothing;" statements.append( f"""insert into public.sources (id, source_type, url, storage_path, excerpt, hash, created_by) select {sql_literal(row["id"])}::uuid, {sql_literal(row["source_type"])}, {sql_literal(row["url"])}, {sql_literal(row["storage_path"])}, {sql_literal(row["excerpt"])}, {sql_literal(row["hash"])}, - {sql_literal(row["created_by"])}::uuid -on conflict do nothing;""" + {sql_literal(row["created_by"])}::uuid{conflict_clause}""" ) checks.append( f""" if exists (select 1 from public.sources @@ -737,11 +761,11 @@ on conflict do nothing;""" ) for row in reasoning_tools: + conflict_clause = ";" if fresh_owned else "\non conflict (id) do nothing;" statements.append( f"""insert into public.reasoning_tools (id, agent_id, name, description, category) select {sql_literal(row["id"])}::uuid, {sql_literal(row["agent_id"])}::uuid, - {sql_literal(row["name"])}, {sql_literal(row["description"])}, {sql_literal(row["category"])} -on conflict (id) do nothing;""" + {sql_literal(row["name"])}, {sql_literal(row["description"])}, {sql_literal(row["category"])}{conflict_clause}""" ) checks.append( f""" if not exists (select 1 from public.reasoning_tools @@ -755,12 +779,12 @@ on conflict (id) do nothing;""" ) for row in evidence: + conflict_clause = ";" if fresh_owned else "\non conflict (claim_id, source_id, role) do nothing;" statements.append( f"""insert into public.claim_evidence (id, claim_id, source_id, role, weight, created_by) select {sql_literal(row["id"])}::uuid, {sql_literal(row["claim_id"])}::uuid, {sql_literal(row["source_id"])}::uuid, {sql_literal(row["role"])}::evidence_role, {sql_literal(row["weight"])}, - {sql_literal(row["created_by"])}::uuid -on conflict (claim_id, source_id, role) do nothing;""" + {sql_literal(row["created_by"])}::uuid{conflict_clause}""" ) checks.append( f""" -- Accept a legacy receipt id only when exactly one semantic row matches. @@ -790,17 +814,21 @@ on conflict (claim_id, source_id, role) do nothing;""" for row in edges: edge_lock_key = f"claim_edge:{row['from_claim']}:{row['to_claim']}:{row['edge_type']}" + edge_insert_guard = ( + ";" + if fresh_owned + else f"""\n where not exists ( + select 1 from public.claim_edges + where from_claim = {sql_literal(row["from_claim"])}::uuid + and to_claim = {sql_literal(row["to_claim"])}::uuid + and edge_type = {sql_literal(row["edge_type"])}::edge_type);""" + ) statements.append( f"""select pg_advisory_xact_lock(hashtextextended({sql_literal(edge_lock_key)}, 0)); insert into public.claim_edges (id, from_claim, to_claim, edge_type, weight, created_by) select {sql_literal(row["id"])}::uuid, {sql_literal(row["from_claim"])}::uuid, {sql_literal(row["to_claim"])}::uuid, {sql_literal(row["edge_type"])}::edge_type, {sql_literal(row["weight"])}, - {sql_literal(row["created_by"])}::uuid - where not exists ( - select 1 from public.claim_edges - where from_claim = {sql_literal(row["from_claim"])}::uuid - and to_claim = {sql_literal(row["to_claim"])}::uuid - and edge_type = {sql_literal(row["edge_type"])}::edge_type);""" + {sql_literal(row["created_by"])}::uuid{edge_insert_guard}""" ) checks.append( f""" -- Accept a legacy receipt id only when exactly one semantic row matches. @@ -830,17 +858,29 @@ select {sql_literal(row["id"])}::uuid, {sql_literal(row["from_claim"])}::uuid, { canonical = "\n\n".join(statements) ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval) - return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval)) + return _wrap_txn( + canonical, + ledger, + _approval_guard_sql(proposal_id, approval), + serializable=fresh_owned, + ) -def _wrap_txn(canonical_sql: str, ledger_sql: str, approval_guard_sql: str) -> str: +def _wrap_txn( + canonical_sql: str, + ledger_sql: str, + approval_guard_sql: str, + *, + serializable: bool = False, +) -> str: return ( "begin;\n" - "set local standard_conforming_strings = on;\n" - f"{approval_guard_sql}\n" - f"{canonical_sql}\n" - f"{ledger_sql}\n" - "commit;\n" + + ("set transaction isolation level serializable;\n" if serializable else "") + + "set local standard_conforming_strings = on;\n" + + f"{approval_guard_sql}\n" + + f"{canonical_sql}\n" + + f"{ledger_sql}\n" + + "commit;\n" ) @@ -852,7 +892,13 @@ BUILDERS = { } -def build_apply_sql(proposal: dict[str, Any], applied_by: str | None) -> str: +def build_apply_sql( + proposal: dict[str, Any], + applied_by: str | None, + *, + fresh_owned: bool = False, + fresh_preflight_sha256: str | None = None, +) -> str: ptype = proposal["proposal_type"] if ptype not in BUILDERS: raise ValueError(f"apply_proposal cannot apply proposal_type {ptype!r}") @@ -863,6 +909,17 @@ def build_apply_sql(proposal: dict[str, Any], applied_by: str | None) -> str: "proposal payload has no 'apply_payload' strict contract. " "Run the normalizer to produce apply_payload before applying." ) + if fresh_owned and ptype != "approve_claim": + raise ValueError("fresh-owned apply is supported only for approve_claim") + if ptype == "approve_claim": + return build_approve_claim_sql( + apply_payload, + proposal["id"], + applied_by or SERVICE_AGENT_HANDLE, + proposal, + fresh_owned=fresh_owned, + fresh_preflight_sha256=fresh_preflight_sha256, + ) return BUILDERS[ptype]( apply_payload, proposal["id"], @@ -990,7 +1047,7 @@ def capture_replay_receipt( raise RuntimeError("postflight query did not return a JSON object") apply_sql_source = "exact_executed_sql" if apply_sql is None: - apply_sql = build_apply_sql(proposal, proposal.get("applied_by_handle")) + apply_sql = build_apply_sql_for_args(proposal, args, proposal.get("applied_by_handle")) apply_sql_source = "reconstructed_current_engine" receipt = replay_receipt.build_replay_receipt( proposal, @@ -1022,6 +1079,14 @@ def parse_args(argv: list[str]) -> argparse.Namespace: p.add_argument("--db", default=DEFAULT_DB) p.add_argument("--host", default=DEFAULT_HOST) p.add_argument("--role", default=DEFAULT_ROLE) + p.add_argument( + "--fresh-preflight", + type=Path, + help=( + "exact proposal_apply_fresh_preflight JSON; makes approve_claim use strict fresh-owned inserts " + "bound to the timestamped preflight" + ), + ) p.add_argument( "--receipt-only", action="store_true", @@ -1043,6 +1108,28 @@ def parse_args(argv: list[str]) -> argparse.Namespace: return args +def build_apply_sql_for_args( + proposal: dict[str, Any], + args: argparse.Namespace, + applied_by: str | None, +) -> str: + fresh_preflight_path = getattr(args, "fresh_preflight", None) + if fresh_preflight_path is None: + return build_apply_sql(proposal, applied_by) + if not fresh_preflight_path.is_file(): + raise SystemExit(f"fresh preflight file not found: {fresh_preflight_path}") + try: + preflight = json.loads(fresh_preflight_path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as exc: + raise SystemExit(f"fresh preflight is unreadable: {fresh_preflight_path}") from exc + import proposal_apply_lifecycle as lifecycle + + try: + return lifecycle.build_fresh_owned_apply_sql(proposal, preflight, applied_by) + except ValueError as exc: + raise SystemExit(f"fresh preflight refused: {exc}") from exc + + def main(argv: list[str] | None = None) -> int: args = parse_args(sys.argv[1:] if argv is None else argv) @@ -1069,13 +1156,13 @@ def main(argv: list[str] | None = None) -> int: password = load_password(args.secrets_file) proposal = load_proposal(args, password) assert_applyable(proposal) - print(build_apply_sql(proposal, args.applied_by)) + print(build_apply_sql_for_args(proposal, args, args.applied_by)) return 0 password = load_password(args.secrets_file) proposal = load_proposal(args, password) assert_applyable(proposal) - sql = build_apply_sql(proposal, args.applied_by) + sql = build_apply_sql_for_args(proposal, args, args.applied_by) run_psql(args, sql, password) applied_proposal = load_proposal(args, password) try: diff --git a/scripts/proposal_apply_lifecycle.py b/scripts/proposal_apply_lifecycle.py index 9ddb600..03ab6d0 100644 --- a/scripts/proposal_apply_lifecycle.py +++ b/scripts/proposal_apply_lifecycle.py @@ -11,7 +11,9 @@ from __future__ import annotations import argparse import hashlib +import hmac import json +import stat import subprocess import sys from datetime import datetime, timezone @@ -24,11 +26,16 @@ sys.path.insert(0, str(HERE)) import apply_proposal as ap # noqa: E402 import kb_apply_replay_receipt as replay_receipt # noqa: E402 -ROLLBACK_SCHEMA = "livingip.proposalApplyRollback.v1" -LIFECYCLE_SCHEMA = "livingip.proposalApplyLifecycleReceipt.v1" -AUTHORIZATION_SCHEMA = "livingip.proposalApplyAuthorizationPacket.v1" +ROLLBACK_SCHEMA = "livingip.proposalApplyRollback.v2" +LIFECYCLE_SCHEMA = "livingip.proposalApplyLifecycleReceipt.v2" +AUTHORIZATION_SCHEMA = "livingip.proposalApplyAuthorizationPacket.v2" FRESH_PREFLIGHT_SCHEMA = "livingip.proposalApplyFreshPreflight.v1" -PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA = "livingip.proposalApplyProductionRollbackArtifact.v1" +PRODUCTION_ROLLBACK_ARTIFACT_SCHEMA = "livingip.proposalApplyProductionRollbackArtifact.v2" +ATTESTATION_SCHEME = "hmac-sha256-v1" +AUTHORIZATION_ATTESTATION_KEY_SOURCE = "/etc/teleo/secrets/production-apply-authorization-attestation.key" +ACTION_READBACK_ATTESTATION_KEY_SOURCE = "/etc/teleo/secrets/production-apply-action-readback-attestation.key" +DEFAULT_AUTHORIZATION_ATTESTATION_KEY_PATH = Path(AUTHORIZATION_ATTESTATION_KEY_SOURCE) +DEFAULT_ACTION_READBACK_ATTESTATION_KEY_PATH = Path(ACTION_READBACK_ATTESTATION_KEY_SOURCE) RUNTIME_DEPENDENCIES = ( "scripts/proposal_apply_lifecycle.py", @@ -210,6 +217,49 @@ def _require_fresh_preflight(proposal_before: dict[str, Any], preflight: dict[st raise ValueError("fresh preflight contract is internally inconsistent") +def build_fresh_owned_apply_sql( + proposal_before: dict[str, Any], + preflight: dict[str, Any], + applied_by: str | None = None, +) -> str: + """Build strict insert-only SQL bound to the exact timestamped preflight.""" + _require_fresh_preflight(proposal_before, preflight) + return ap.build_apply_sql( + proposal_before, + applied_by or ap.SERVICE_AGENT_HANDLE, + fresh_owned=True, + fresh_preflight_sha256=preflight["preflight_artifact_sha256"], + ) + + +def _load_private_attestation_key(path: Path) -> bytes | None: + """Load an operator-owned key without accepting key material from the record.""" + try: + metadata = path.lstat() + except OSError: + return None + if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISREG(metadata.st_mode): + return None + if stat.S_IMODE(metadata.st_mode) & 0o077: + return None + try: + key = path.read_bytes().strip() + except OSError: + return None + return key if len(key) >= 32 else None + + +def _key_id(key: bytes | None) -> str | None: + return hashlib.sha256(key).hexdigest() if key is not None else None + + +def _verify_hmac(key: bytes | None, payload: dict[str, Any], supplied: Any) -> bool: + if key is None or not is_sha256(supplied): + return False + expected = hmac.new(key, canonical_json(payload).encode("utf-8"), hashlib.sha256).hexdigest() + return hmac.compare_digest(expected, supplied) + + def _require_apply_receipt( proposal_before: dict[str, Any], preflight: dict[str, Any], @@ -292,6 +342,12 @@ def _delete_statement(table: str, rows: list[dict[str, Any]], label: str) -> str end if;""" +def _uuid_array(values: list[str]) -> str: + if not values: + return "array[]::uuid[]" + return "array[" + ", ".join(f"{ap.sql_literal(value)}::uuid" for value in values) + "]::uuid[]" + + def _require_approval_snapshot(proposal_before: dict[str, Any], approval_snapshot: dict[str, Any]) -> None: expected_keys = { "proposal_id", @@ -345,6 +401,10 @@ def build_compensating_rollback_sql( applied_by_agent_id = ap.sql_literal(applied.get("applied_by_agent_id")) applied_at = ap.sql_literal(applied.get("applied_at")) approval_json = ap.sql_literal(canonical_json(approval_snapshot)) + claim_ids = _uuid_array([str(row["id"]) for row in rows["claims"]]) + source_ids = _uuid_array([str(row["id"]) for row in rows["sources"]]) + evidence_ids = _uuid_array([str(row["id"]) for row in rows["claim_evidence"]]) + edge_ids = _uuid_array([str(row["id"]) for row in rows["claim_edges"]]) row_assertions = [] for family in DELETE_ORDER: @@ -362,6 +422,7 @@ do $rollback$ declare affected integer; approval_now jsonb; + downstream_dependency_count integer; begin perform 1 from kb_stage.kb_proposals where id = {proposal_id}::uuid @@ -400,10 +461,30 @@ begin if approval_now is distinct from {approval_json}::jsonb then raise exception 'proposal rollback: immutable approval snapshot drifted'; end if; + select count(*) into downstream_dependency_count + from ( + select ce.id + from public.claim_evidence ce + where (ce.claim_id = any({claim_ids}) or ce.source_id = any({source_ids})) + and ce.id <> all({evidence_ids}) + union all + select edge.id + from public.claim_edges edge + where (edge.from_claim = any({claim_ids}) or edge.to_claim = any({claim_ids})) + and edge.id <> all({edge_ids}) + union all + select claim.id + from public.claims claim + where claim.superseded_by = any({claim_ids}) + and claim.id <> all({claim_ids}) + ) external_dependencies; + if downstream_dependency_count <> 0 then + raise exception 'proposal rollback: % downstream dependenc(ies) exist; rollback quarantined', downstream_dependency_count; + end if; {chr(10).join(row_assertions)} {chr(10).join(deletions)} update kb_stage.kb_proposals - set status = 'approved', + set status = 'canceled', applied_by_handle = null, applied_by_agent_id = null, applied_at = null, @@ -557,6 +638,12 @@ def build_lifecycle_receipt( generated_at_utc: str | None = None, ) -> dict[str, Any]: rows = _require_apply_receipt(proposal_before, preflight, apply_receipt) + expected_fresh_apply_sql = build_fresh_owned_apply_sql( + proposal_before, + preflight, + apply_receipt["proposal"].get("applied_by_handle"), + ) + expected_fresh_apply_sha256 = sha256_text(expected_fresh_apply_sql) expected_rollback_sql = build_compensating_rollback_sql( proposal_before, approval_before, @@ -569,20 +656,23 @@ def build_lifecycle_receipt( expected_after = dict(proposal_before) expected_after.update( { - "status": "approved", + "status": "canceled", "applied_by_handle": None, "applied_by_agent_id": None, "applied_at": None, } ) - ledger_restored = all(proposal_after.get(key) == value for key, value in expected_after.items()) + ledger_quarantined = all(proposal_after.get(key) == value for key, value in expected_after.items()) checks = { "fresh_owned_targets": preflight.get("fresh_owned_targets") is True, "apply_receipt_replay_ready": apply_receipt.get("replay_ready") is True, + "fresh_owned_preflight_consumed_by_apply": ( + apply_receipt["apply_engine"].get("apply_sql_sha256") == expected_fresh_apply_sha256 + ), "apply_rows_have_exact_ids": all(rows[name] == apply_receipt["canonical_rows"][name] for name in ROW_TABLES), "rollback_target_rows_absent": target_rows_absent, "rollback_counts_restored": counts_after == counts_before, - "rollback_ledger_restored_to_approved": ledger_restored, + "rollback_ledger_quarantined_from_worker": ledger_quarantined, "immutable_approval_unchanged": approval_after == approval_before, "unrelated_rows_unchanged": unrelated_after == unrelated_before, "rollback_replay_refused_without_mutation": rollback_replay_refused is True, @@ -618,6 +708,7 @@ def build_lifecycle_receipt( "fresh_preflight_artifact_sha256": preflight["preflight_artifact_sha256"], "apply_receipt_sha256": sha256_json(apply_receipt), "apply_sql_sha256": apply_receipt["apply_engine"]["apply_sql_sha256"], + "fresh_owned_apply_sql_sha256": expected_fresh_apply_sha256, "applied_row_ids": _row_ids(rows), "applied_row_sha256": {name: [sha256_json(row) for row in table_rows] for name, table_rows in rows.items()}, "rollback": { @@ -672,6 +763,7 @@ def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: "fresh_preflight_artifact_sha256", "apply_receipt_sha256", "apply_sql_sha256", + "fresh_owned_apply_sql_sha256", "applied_row_ids", "applied_row_sha256", "rollback", @@ -718,9 +810,12 @@ def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: "fresh_preflight_artifact_sha256", "apply_receipt_sha256", "apply_sql_sha256", + "fresh_owned_apply_sql_sha256", ) if any(not is_sha256(lifecycle_receipt.get(field)) for field in hash_fields): raise ValueError("lifecycle receipt is missing an exact SHA-256 binding") + if lifecycle_receipt.get("apply_sql_sha256") != lifecycle_receipt.get("fresh_owned_apply_sql_sha256"): + raise ValueError("lifecycle receipt apply SQL did not consume the fresh-owned preflight") row_ids = lifecycle_receipt.get("applied_row_ids") row_hashes = lifecycle_receipt.get("applied_row_sha256") if ( @@ -747,6 +842,7 @@ def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: or set(target_rows_after) != set(ROW_TABLES) or any(not isinstance(rows, list) or rows for rows in target_rows_after.values()) or rollback.get("counts_before_apply") != rollback.get("counts_after_rollback") + or (rollback.get("proposal_after") or {}).get("status") != "canceled" ): raise ValueError("lifecycle receipt does not prove exact rollback cleanup") @@ -917,6 +1013,12 @@ def build_authorization_packet( else None ) observed_at_utc = destination_readback.get("observed_at_utc") + downstream_dependency_count = destination_readback.get("downstream_dependency_count") + downstream_dependency_readback_valid = ( + isinstance(downstream_dependency_count, int) + and not isinstance(downstream_dependency_count, bool) + and downstream_dependency_count >= 0 + ) destination_readback_was_read_only = ( destination_readback.get("read_only_transaction") is True and _parse_utc(observed_at_utc) is not None ) @@ -926,6 +1028,7 @@ def build_authorization_packet( "approval_gate_ready": approval_gate_ready, "strict_proposal_present_and_approved": len(matching) == 1, "matching_candidate_count": len(matching), + "zero_downstream_dependencies": (downstream_dependency_readback_valid and downstream_dependency_count == 0), "exact_production_rollback_packet_ready": production_rollback_sha256 is not None, "production_apply_authorization_present": False, "production_apply_executed": False, @@ -949,6 +1052,14 @@ def build_authorization_packet( "destination_readback": { "observed_at_utc": observed_at_utc, "read_only_transaction": destination_readback.get("read_only_transaction"), + "downstream_dependency_count": downstream_dependency_count, + }, + "attestation_policy": { + "scheme": ATTESTATION_SCHEME, + "authorization_key_source": AUTHORIZATION_ATTESTATION_KEY_SOURCE, + "action_readback_key_source": ACTION_READBACK_ATTESTATION_KEY_SOURCE, + "separate_operator_owned_keys_required": True, + "locally_synthesized_records_refused": True, }, "approval_gate": bound_gate, "candidate_readback": { @@ -1010,6 +1121,22 @@ def build_authorization_packet( "received_at_utc": "", "expires_at_utc": "", "authorization_text": "", + "authorization_provenance": { + "scheme": ATTESTATION_SCHEME, + "source": "codex_platform_user_message", + "source_event_id": "", + "source_event_sha256": "", + "key_id": "", + "attestation_hmac_sha256": "", + }, + "action_readback_provenance": { + "scheme": ATTESTATION_SCHEME, + "collector": "teleo_production_readonly_collector", + "receipt_id": "", + "observed_destination_sha256": "", + "key_id": "", + "attestation_hmac_sha256": "", + }, }, "authorization_text_template": _authorization_text_template(binding, binding_sha256), "safe_to_enter_apply_window": False, @@ -1044,6 +1171,8 @@ def build_authorization_packet( if not matching else "generate and retain the exact production rollback SQL" if production_rollback_sha256 is None + else "collect an independently attested zero-dependency action-time readback" + if not production_preconditions["zero_downstream_dependencies"] else "obtain the exact action-time authorization record" ), "claim_ceiling": ( @@ -1080,6 +1209,59 @@ def _parse_utc(value: Any) -> datetime | None: return parsed.astimezone(timezone.utc) +def action_readback_projection(observed_destination: dict[str, Any]) -> dict[str, Any]: + """Canonical action-time DB readback covered by the independent attestation.""" + return { + "observed_at_utc": observed_destination.get("observed_at_utc"), + "read_only_transaction": observed_destination.get("read_only_transaction"), + "container": observed_destination.get("container"), + "database": observed_destination.get("database"), + "system_identifier": observed_destination.get("system_identifier"), + "server_version_num": observed_destination.get("server_version_num"), + "approval_gate": observed_destination.get("approval_gate"), + "approved_strict_candidates": observed_destination.get("approved_strict_candidates"), + "downstream_dependency_count": observed_destination.get("downstream_dependency_count"), + } + + +def authorization_attestation_payload(packet: dict[str, Any], record: dict[str, Any]) -> dict[str, Any]: + provenance = record.get("authorization_provenance") + provenance = provenance if isinstance(provenance, dict) else {} + return { + "scheme": ATTESTATION_SCHEME, + "binding_sha256": packet.get("binding_sha256"), + "authorized": record.get("authorized"), + "rollback_authorized": record.get("rollback_authorized"), + "production_rollback_sql_sha256": record.get("production_rollback_sql_sha256"), + "operator_identity": record.get("operator_identity"), + "received_at_utc": record.get("received_at_utc"), + "expires_at_utc": record.get("expires_at_utc"), + "authorization_text": record.get("authorization_text"), + "source": provenance.get("source"), + "source_event_id": provenance.get("source_event_id"), + "source_event_sha256": provenance.get("source_event_sha256"), + "key_id": provenance.get("key_id"), + } + + +def action_readback_attestation_payload( + packet: dict[str, Any], + observed_destination: dict[str, Any], + record: dict[str, Any], +) -> dict[str, Any]: + provenance = record.get("action_readback_provenance") + provenance = provenance if isinstance(provenance, dict) else {} + return { + "scheme": ATTESTATION_SCHEME, + "binding_sha256": packet.get("binding_sha256"), + "collector": provenance.get("collector"), + "receipt_id": provenance.get("receipt_id"), + "observed_destination_sha256": provenance.get("observed_destination_sha256"), + "key_id": provenance.get("key_id"), + "readback": action_readback_projection(observed_destination), + } + + def verify_authorization_record( packet: dict[str, Any], record: dict[str, Any], @@ -1232,6 +1414,8 @@ def verify_authorization_record( "received_at_utc", "expires_at_utc", "authorization_text", + "authorization_provenance", + "action_readback_provenance", } expected_record_template = { "authorized": True, @@ -1246,6 +1430,22 @@ def verify_authorization_record( "received_at_utc": "", "expires_at_utc": "", "authorization_text": "", + "authorization_provenance": { + "scheme": ATTESTATION_SCHEME, + "source": "codex_platform_user_message", + "source_event_id": "", + "source_event_sha256": "", + "key_id": "", + "attestation_hmac_sha256": "", + }, + "action_readback_provenance": { + "scheme": ATTESTATION_SCHEME, + "collector": "teleo_production_readonly_collector", + "receipt_id": "", + "observed_destination_sha256": "", + "key_id": "", + "attestation_hmac_sha256": "", + }, } try: expected_record_text = expected_authorization_text(packet, record) @@ -1281,6 +1481,75 @@ def verify_authorization_record( and received <= action_observed_at <= now and observed_destination.get("read_only_transaction") is True ) + bound_attestation_policy = ( + binding.get("attestation_policy") if isinstance(binding.get("attestation_policy"), dict) else {} + ) + expected_attestation_policy = { + "scheme": ATTESTATION_SCHEME, + "authorization_key_source": AUTHORIZATION_ATTESTATION_KEY_SOURCE, + "action_readback_key_source": ACTION_READBACK_ATTESTATION_KEY_SOURCE, + "separate_operator_owned_keys_required": True, + "locally_synthesized_records_refused": True, + } + authorization_provenance = ( + record.get("authorization_provenance") if isinstance(record.get("authorization_provenance"), dict) else {} + ) + action_readback_provenance = ( + record.get("action_readback_provenance") if isinstance(record.get("action_readback_provenance"), dict) else {} + ) + authorization_key = _load_private_attestation_key(DEFAULT_AUTHORIZATION_ATTESTATION_KEY_PATH) + action_readback_key = _load_private_attestation_key(DEFAULT_ACTION_READBACK_ATTESTATION_KEY_PATH) + authorization_provenance_contract = { + "scheme", + "source", + "source_event_id", + "source_event_sha256", + "key_id", + "attestation_hmac_sha256", + } + action_readback_provenance_contract = { + "scheme", + "collector", + "receipt_id", + "observed_destination_sha256", + "key_id", + "attestation_hmac_sha256", + } + authorization_provenance_valid = ( + set(authorization_provenance) == authorization_provenance_contract + and authorization_provenance.get("scheme") == ATTESTATION_SCHEME + and authorization_provenance.get("source") == "codex_platform_user_message" + and isinstance(authorization_provenance.get("source_event_id"), str) + and bool(authorization_provenance.get("source_event_id", "").strip()) + and authorization_provenance.get("source_event_sha256") + == sha256_text(str(record.get("authorization_text") or "")) + and authorization_provenance.get("key_id") == _key_id(authorization_key) + and _verify_hmac( + authorization_key, + authorization_attestation_payload(packet, record), + authorization_provenance.get("attestation_hmac_sha256"), + ) + ) + action_projection = action_readback_projection(observed_destination) + action_readback_provenance_valid = ( + set(action_readback_provenance) == action_readback_provenance_contract + and action_readback_provenance.get("scheme") == ATTESTATION_SCHEME + and action_readback_provenance.get("collector") == "teleo_production_readonly_collector" + and isinstance(action_readback_provenance.get("receipt_id"), str) + and bool(action_readback_provenance.get("receipt_id", "").strip()) + and action_readback_provenance.get("observed_destination_sha256") == sha256_json(action_projection) + and action_readback_provenance.get("key_id") == _key_id(action_readback_key) + and authorization_key is not None + and action_readback_key is not None + and not hmac.compare_digest(authorization_key, action_readback_key) + and _verify_hmac( + action_readback_key, + action_readback_attestation_payload(packet, observed_destination, record), + action_readback_provenance.get("attestation_hmac_sha256"), + ) + ) + bound_dependency_count = bound_destination_readback.get("downstream_dependency_count") + action_dependency_count = observed_destination.get("downstream_dependency_count") checks = { "packet_schema_exact": ( packet.get("artifact") == "proposal_apply_production_authorization_packet" @@ -1293,6 +1562,9 @@ def verify_authorization_record( "packet_preconditions_bound_exactly": ( canonical_json(packet_preconditions) == canonical_json(bound_preconditions) ), + "independent_attestation_policy_bound": ( + canonical_json(bound_attestation_policy) == canonical_json(expected_attestation_policy) + ), "proposal_binding_self_consistent": proposal_binding_self_consistent, "packet_destination_readback_was_read_only": ( packet_preconditions.get("destination_readback_was_read_only") is True @@ -1313,6 +1585,11 @@ def verify_authorization_record( and packet_preconditions.get("matching_candidate_count") == 1 and bound_candidate_exact ), + "zero_downstream_dependencies_at_packet": ( + packet_preconditions.get("zero_downstream_dependencies") is True + and bound_dependency_count == 0 + and not isinstance(bound_dependency_count, bool) + ), "packet_never_self_authorizes_or_expands_scope": ( packet.get("safe_to_enter_apply_window") is False and packet.get("production_apply_authorization_present") is False @@ -1342,10 +1619,15 @@ def verify_authorization_record( ), "authorization_text_exact": bool(expected_record_text) and record.get("authorization_text") == expected_record_text, + "authorization_provenance_independently_attested": authorization_provenance_valid, + "action_readback_provenance_independently_attested": action_readback_provenance_valid, "destination_identity_exact": destination_matches, "destination_readback_fresh_and_read_only_at_action": action_readback_fresh, "approval_gate_identity_exact_at_action": gate_matches, "strict_proposal_exact_at_action": len(matching_candidates) == 1, + "zero_downstream_dependencies_at_action": ( + action_dependency_count == 0 and not isinstance(action_dependency_count, bool) + ), "apply_engine_sha256_exact": ( apply_engine_path.is_file() and apply_engine_relative == bound_engine.get("apply_engine_path") @@ -1359,7 +1641,7 @@ def verify_authorization_record( ), } return { - "schema": "livingip.proposalApplyAuthorizationVerification.v1", + "schema": "livingip.proposalApplyAuthorizationVerification.v2", "checks": checks, "safe_to_enter_apply_window": all(checks.values()), "production_apply_authorization_present": all(checks.values()), diff --git a/scripts/run_approve_claim_clone_canary.py b/scripts/run_approve_claim_clone_canary.py index 87c4de2..2ea28e6 100644 --- a/scripts/run_approve_claim_clone_canary.py +++ b/scripts/run_approve_claim_clone_canary.py @@ -1095,6 +1095,7 @@ def _apply( *, dry_run: bool = False, receipt_out: Path | None = None, + fresh_preflight: Path | None = None, ) -> subprocess.CompletedProcess[str]: command = [ sys.executable, @@ -1115,6 +1116,8 @@ def _apply( ] if receipt_out is not None: command.extend(["--receipt-out", str(receipt_out)]) + if fresh_preflight is not None: + command.extend(["--fresh-preflight", str(fresh_preflight)]) if dry_run: command.append("--dry-run") return _run(command, check=False) @@ -1766,11 +1769,69 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: result["clone_counts_before_apply"] = _base_counts(args.container, clone_db) with tempfile.TemporaryDirectory(prefix="leo-proposal-apply-receipt-") as receipt_dir: private_receipt_path = Path(receipt_dir) / "apply-receipt.json" + fresh_preflight_path = Path(receipt_dir) / "fresh-preflight.json" + fresh_preflight_path.write_text( + json.dumps(fresh_preflight, indent=2, sort_keys=True) + "\n", + encoding="utf-8", + ) + fresh_preflight_path.chmod(0o600) + intervening_claim = expected_rows["claims"][0] + intervening_tags = ( + "array[" + ", ".join(ap.sql_literal(tag) for tag in intervening_claim["tags"]) + "]::text[]" + ) + _psql( + args.container, + clone_db, + f"""insert into public.claims + (id, type, text, status, confidence, tags, created_by, superseded_by) +values + ({ap.sql_literal(intervening_claim["id"])}::uuid, + {ap.sql_literal(intervening_claim["type"])}, + {ap.sql_literal(intervening_claim["text"])}, + {ap.sql_literal(intervening_claim["status"])}, + {ap.sql_literal(intervening_claim["confidence"])}, + {intervening_tags}, + {ap.sql_literal(intervening_claim["created_by"])}::uuid, + {ap.sql_literal(intervening_claim["superseded_by"])}::uuid);""", + tuples=False, + ) + intervening_apply = _apply( + args, + fixture["proposal_id"], + clone_db, + fresh_preflight=fresh_preflight_path, + ) + intervening_row_after = _psql( + args.container, + clone_db, + f"select count(*) from public.claims where id = {ap.sql_literal(intervening_claim['id'])}::uuid;", + ) + proposal_after_intervening_apply = _proposal_readback( + args.container, + clone_db, + fixture["proposal_id"], + ) + result["intervening_exact_row_refusal"] = { + "returncode": intervening_apply.returncode, + "strict_insert_refused": intervening_apply.returncode != 0, + "intervening_row_preserved": intervening_row_after.strip() == "1", + "proposal_remained_approved": ( + proposal_after_intervening_apply is not None + and proposal_after_intervening_apply.get("status") == "approved" + ), + } + _psql( + args.container, + clone_db, + f"delete from public.claims where id = {ap.sql_literal(intervening_claim['id'])}::uuid;", + tuples=False, + ) first_apply = _apply( args, fixture["proposal_id"], clone_db, receipt_out=private_receipt_path, + fresh_preflight=fresh_preflight_path, ) result["first_apply"] = _apply_command_readback(first_apply) if first_apply.returncode != 0 or not private_receipt_path.is_file(): @@ -1815,6 +1876,62 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "rollback_sql_sha256": lifecycle.sha256_text(rollback_sql), "execution_authority": "disposable_clone_admin_only", } + downstream_claim_id = str( + uuid.uuid5(uuid.NAMESPACE_URL, f"working-leo:rollback-dependency:{fixture['proposal_id']}") + ) + downstream_target_claim_id = str(payload["claims"][0]["id"]) + _psql( + args.container, + clone_db, + f"""insert into public.claims + (id, type, text, status, confidence, tags, created_by, superseded_by) +values + ({ap.sql_literal(downstream_claim_id)}::uuid, 'structural', + 'External dependency that must survive refused proposal rollback.', 'open', null, + array['working-leo','rollback-dependency']::text[], null, + {ap.sql_literal(downstream_target_claim_id)}::uuid);""", + tuples=False, + ) + dependency_rollback = _run( + [ + "docker", + "exec", + "-i", + args.container, + "psql", + "-U", + "postgres", + "-d", + clone_db, + "-v", + "ON_ERROR_STOP=1", + ], + input_text=rollback_sql, + check=False, + ) + dependency_after_refusal = _psql( + args.container, + clone_db, + f"select count(*) from public.claims where id = {ap.sql_literal(downstream_claim_id)}::uuid;", + ) + targets_after_dependency_refusal = _exact_bundle_readback(args.container, clone_db, payload) + proposal_after_dependency_refusal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) + result["downstream_dependency_rollback_refusal"] = { + "returncode": dependency_rollback.returncode, + "dependency_refusal": "downstream dependenc" in dependency_rollback.stderr.lower(), + "dependency_row_preserved": dependency_after_refusal.strip() == "1", + "proposal_remained_applied": ( + proposal_after_dependency_refusal is not None + and proposal_after_dependency_refusal.get("status") == "applied" + ), + "owned_rows_preserved": targets_after_dependency_refusal == result["row_readback"], + } + _psql( + args.container, + clone_db, + f"delete from public.claims where id = {ap.sql_literal(downstream_claim_id)}::uuid;", + tuples=False, + ) _psql(args.container, clone_db, rollback_sql, tuples=False) rollback_proposal = _proposal_readback(args.container, clone_db, fixture["proposal_id"]) rollback_approval = _approval_snapshot_readback(args.container, clone_db, fixture["proposal_id"]) @@ -1859,6 +1976,12 @@ def run_canary(args: argparse.Namespace) -> dict[str, Any]: "state_unchanged": rollback_replay_state_unchanged, "stderr": rollback_replay.stderr.strip(), } + post_rollback_apply = _apply(args, fixture["proposal_id"], clone_db) + result["post_rollback_worker_apply"] = { + "returncode": post_rollback_apply.returncode, + "terminal_status_refusal": "only 'approved' proposals apply" in post_rollback_apply.stderr, + "proposal_status": (rollback_proposal or {}).get("status"), + } lifecycle_receipt = lifecycle.build_lifecycle_receipt( proposal_before=approved_proposal, approval_before=approved_snapshot, @@ -2047,6 +2170,14 @@ drop database if exists {clone_db}; result.get("fresh_owned_preflight", {}).get("fresh_owned_targets") is True and result.get("target_rows_before_apply") == _empty_bundle_readback(payload) ), + "intervening_exact_row_refused_without_adoption": all( + result.get("intervening_exact_row_refusal", {}).get(key) is True + for key in ( + "strict_insert_refused", + "intervening_row_preserved", + "proposal_remained_approved", + ) + ), "compensating_rollback_receipt_passes": ( result.get("applied_rollback_receipt", {}).get("pass") is True and result.get("applied_rollback_receipt", {}).get("current_tier") == "T2_runtime" @@ -2055,6 +2186,20 @@ drop database if exists {clone_db}; result.get("rollback_replay", {}).get("refused") is True and result.get("rollback_replay", {}).get("state_unchanged") is True ), + "rollback_refuses_downstream_dependencies_without_deletion": all( + result.get("downstream_dependency_rollback_refusal", {}).get(key) is True + for key in ( + "dependency_refusal", + "dependency_row_preserved", + "proposal_remained_applied", + "owned_rows_preserved", + ) + ), + "post_rollback_worker_reapply_refused": ( + result.get("post_rollback_worker_apply", {}).get("returncode", 0) != 0 + and result.get("post_rollback_worker_apply", {}).get("terminal_status_refusal") is True + and result.get("post_rollback_worker_apply", {}).get("proposal_status") == "canceled" + ), "payload_projection_exact": result.get("row_readback") == expected_rows, "clone_apply_table_deltas_exact": (result.get("clone_apply_table_deltas") == expected_table_deltas), "apply_transition_exact": ( diff --git a/tests/test_apply_proposal.py b/tests/test_apply_proposal.py index 8f79873..96bf7e1 100644 --- a/tests/test_apply_proposal.py +++ b/tests/test_apply_proposal.py @@ -378,6 +378,34 @@ def test_apply_sql_locks_and_binds_approval_before_canonical_write(): assert "Reviewed exact strict payload." in sql +def test_fresh_owned_apply_uses_strict_inserts_and_binds_preflight_hash(): + payload = _approve_claim_bundle() + proposal = { + "id": "99999999-9999-4999-8999-999999999999", + "proposal_type": "approve_claim", + "status": "approved", + "payload": {"apply_payload": payload}, + "reviewed_by_handle": "m3ta", + "reviewed_by_agent_id": None, + "reviewed_at": "2026-07-10T00:00:00+00:00", + "review_note": "Reviewed exact strict payload.", + } + preflight_sha256 = "a" * 64 + + sql = ap.build_apply_sql( + proposal, + "kb-apply", + fresh_owned=True, + fresh_preflight_sha256=preflight_sha256, + ) + + assert preflight_sha256 in sql + assert "set transaction isolation level serializable" in sql.lower() + assert "on conflict" not in sql.lower() + assert "where not exists" not in sql.lower() + assert sql.index("set transaction isolation level serializable") < sql.index("kb_stage.assert_approved_proposal") + + def test_build_apply_sql_requires_review_provenance(): proposal = { "id": "99999999-9999-4999-8999-999999999999", diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index 916f32f..d05fd00 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -4,6 +4,7 @@ from __future__ import annotations import copy import hashlib +import hmac import json import string import sys @@ -31,6 +32,18 @@ REVIEWED_AT = "2026-07-15T09:30:00+00:00" ROW_FAMILIES = tuple(lifecycle.ROW_TABLES) +@pytest.fixture(autouse=True) +def _trusted_attestation_keys(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + authorization_key = tmp_path / "authorization-attestation.key" + action_readback_key = tmp_path / "action-readback-attestation.key" + authorization_key.write_bytes(b"authorization-attestation-test-key-0001") + action_readback_key.write_bytes(b"action-readback-attestation-test-key-0002") + authorization_key.chmod(0o600) + action_readback_key.chmod(0o600) + monkeypatch.setattr(lifecycle, "DEFAULT_AUTHORIZATION_ATTESTATION_KEY_PATH", authorization_key) + monkeypatch.setattr(lifecycle, "DEFAULT_ACTION_READBACK_ATTESTATION_KEY_PATH", action_readback_key) + + def _apply_payload() -> dict: return { "contract_version": 2, @@ -207,7 +220,7 @@ def _empty_targets() -> dict[str, list[dict]]: return {family: [] for family in ROW_FAMILIES} -def _apply_receipt(proposal: dict, rows: dict[str, list[dict]]) -> dict: +def _apply_receipt(proposal: dict, rows: dict[str, list[dict]], preflight: dict) -> dict: applied = copy.deepcopy(proposal) applied.update( { @@ -217,7 +230,7 @@ def _apply_receipt(proposal: dict, rows: dict[str, list[dict]]) -> dict: "applied_at": APPLIED_AT, } ) - apply_sql = apply.build_apply_sql(proposal, apply.SERVICE_AGENT_HANDLE) + apply_sql = lifecycle.build_fresh_owned_apply_sql(proposal, preflight, apply.SERVICE_AGENT_HANDLE) return apply.replay_receipt.build_replay_receipt( applied, copy.deepcopy(rows), @@ -235,7 +248,7 @@ def _materials() -> tuple[dict, dict, dict, dict, str]: _empty_targets(), captured_at_utc="2026-07-15T10:00:00+00:00", ) - receipt = _apply_receipt(proposal, _canonical_rows()) + receipt = _apply_receipt(proposal, _canonical_rows(), preflight) rollback_sql = lifecycle.build_compensating_rollback_sql(proposal, approval, preflight, receipt) return proposal, approval, preflight, receipt, rollback_sql @@ -243,6 +256,14 @@ def _materials() -> tuple[dict, dict, dict, dict, str]: def _passing_lifecycle_receipt() -> dict: proposal, approval, preflight, receipt, rollback_sql = _materials() proposal_after = copy.deepcopy(proposal) + proposal_after.update( + { + "status": "canceled", + "applied_by_handle": None, + "applied_by_agent_id": None, + "applied_at": None, + } + ) return lifecycle.build_lifecycle_receipt( proposal_before=proposal, approval_before=approval, @@ -297,6 +318,7 @@ def _destination(*, candidate_present: bool = True) -> dict: "apply_role_present": True, }, "approved_strict_candidates": candidates, + "downstream_dependency_count": 0, } @@ -332,8 +354,38 @@ def _authorization_materials() -> tuple[dict, dict, dict, dict]: "received_at_utc": "2026-07-15T11:00:00+00:00", "expires_at_utc": "2026-07-15T13:00:00+00:00", } - record["authorization_text"] = lifecycle.expected_authorization_text(packet, record) destination["observed_at_utc"] = "2026-07-15T11:30:00+00:00" + record["authorization_text"] = lifecycle.expected_authorization_text(packet, record) + authorization_key = lifecycle.DEFAULT_AUTHORIZATION_ATTESTATION_KEY_PATH.read_bytes().strip() + action_readback_key = lifecycle.DEFAULT_ACTION_READBACK_ATTESTATION_KEY_PATH.read_bytes().strip() + record["authorization_provenance"] = { + "scheme": lifecycle.ATTESTATION_SCHEME, + "source": "codex_platform_user_message", + "source_event_id": "codex-user-event-019f-test", + "source_event_sha256": lifecycle.sha256_text(record["authorization_text"]), + "key_id": hashlib.sha256(authorization_key).hexdigest(), + "attestation_hmac_sha256": "", + } + record["authorization_provenance"]["attestation_hmac_sha256"] = hmac.new( + authorization_key, + lifecycle.canonical_json(lifecycle.authorization_attestation_payload(packet, record)).encode("utf-8"), + hashlib.sha256, + ).hexdigest() + record["action_readback_provenance"] = { + "scheme": lifecycle.ATTESTATION_SCHEME, + "collector": "teleo_production_readonly_collector", + "receipt_id": "production-readback-019f-test", + "observed_destination_sha256": lifecycle.sha256_json(lifecycle.action_readback_projection(destination)), + "key_id": hashlib.sha256(action_readback_key).hexdigest(), + "attestation_hmac_sha256": "", + } + record["action_readback_provenance"]["attestation_hmac_sha256"] = hmac.new( + action_readback_key, + lifecycle.canonical_json(lifecycle.action_readback_attestation_payload(packet, destination, record)).encode( + "utf-8" + ), + hashlib.sha256, + ).hexdigest() return packet, record, destination, production_rollback_artifact @@ -366,6 +418,25 @@ def test_fresh_preflight_requires_every_owned_target_to_be_absent_and_is_determi lifecycle.build_fresh_preflight(proposal, incomplete) +def test_fresh_owned_apply_consumes_timestamped_preflight_and_never_adopts_conflicts(): + proposal, _approval, preflight, _receipt, _rollback_sql = _materials() + + strict_sql = lifecycle.build_fresh_owned_apply_sql(proposal, preflight, apply.SERVICE_AGENT_HANDLE) + ordinary_sql = apply.build_apply_sql(proposal, apply.SERVICE_AGENT_HANDLE) + + assert preflight["preflight_artifact_sha256"] in strict_sql + assert "set transaction isolation level serializable" in strict_sql.lower() + assert "proposal-fresh-apply:" in strict_sql + assert "on conflict" not in strict_sql.lower() + assert "where not exists" not in strict_sql.lower() + assert "on conflict" in ordinary_sql.lower() + + stale = copy.deepcopy(preflight) + stale["captured_at_utc"] = "1970-01-01T00:00:00+00:00" + with pytest.raises(ValueError, match="artifact hash"): + lifecycle.build_fresh_owned_apply_sql(proposal, stale, apply.SERVICE_AGENT_HANDLE) + + @pytest.mark.parametrize( "mutation", ( @@ -428,7 +499,9 @@ def test_compensating_rollback_is_atomic_deterministic_and_refuses_state_drift() rollback_sql.index(f"delete from {lifecycle.ROW_TABLES[family]}") for family in lifecycle.DELETE_ORDER ] assert delete_positions == sorted(delete_positions) - assert "set status = 'approved'" in rollback_sql + assert "set status = 'canceled'" in rollback_sql + assert "downstream_dependency_count" in rollback_sql + assert "downstream dependenc(ies) exist" in rollback_sql assert "immutable approval snapshot drifted" in rollback_sql drifted_receipt = copy.deepcopy(receipt) @@ -478,7 +551,7 @@ def test_rollback_sql_hash_binds_every_receipt_observed_field(): proposal, approval, preflight, receipt, rollback_sql = _materials() changed_rows = copy.deepcopy(receipt["canonical_rows"]) changed_rows["claims"][0]["created_at"] = "2026-07-15T10:15:00.123456+00:00" - changed_receipt = _apply_receipt(proposal, changed_rows) + changed_receipt = _apply_receipt(proposal, changed_rows, preflight) changed_sql = lifecycle.build_compensating_rollback_sql( proposal, @@ -497,7 +570,7 @@ def test_fresh_apply_receipt_requires_deterministic_generated_row_ids(family: st proposal, approval, preflight, receipt, _rollback_sql = _materials() changed_rows = copy.deepcopy(receipt["canonical_rows"]) changed_rows[family][0]["id"] = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" - changed_receipt = _apply_receipt(proposal, changed_rows) + changed_receipt = _apply_receipt(proposal, changed_rows, preflight) with pytest.raises(ValueError, match="is not deterministic"): lifecycle.build_compensating_rollback_sql( @@ -537,7 +610,7 @@ def test_production_rollback_artifact_reconstructs_exact_sql_and_rejects_noop_su noop = copy.deepcopy(artifact) noop["rollback_sql"] = ( "begin; -- proposal rollback drift: -- immutable approval snapshot drifted " - "-- set status = 'approved'\ncommit;\n" + "-- set status = 'canceled'\ncommit;\n" ) noop["rollback_sql_sha256"] = lifecycle.sha256_text(noop["rollback_sql"]) unsigned = dict(noop) @@ -649,6 +722,47 @@ def test_authorization_packet_is_exact_but_never_self_authorizes_production(): assert all(verification["checks"].values()) +def test_locally_synthesized_authorization_record_and_readback_cannot_self_authorize(): + packet, record, destination, production_rollback_artifact = _authorization_materials() + forged = copy.deepcopy(record) + forged["operator_identity"] = "forged-by-local-caller" + forged["authorization_text"] = lifecycle.expected_authorization_text(packet, forged) + forged["authorization_provenance"]["source_event_sha256"] = lifecycle.sha256_text(forged["authorization_text"]) + forged["authorization_provenance"]["attestation_hmac_sha256"] = "0" * 64 + forged["action_readback_provenance"]["attestation_hmac_sha256"] = "0" * 64 + + verification = lifecycle.verify_authorization_record( + packet, + forged, + observed_destination=copy.deepcopy(destination), + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert verification["checks"]["authorization_provenance_independently_attested"] is False + assert verification["checks"]["action_readback_provenance_independently_attested"] is False + assert verification["safe_to_enter_apply_window"] is False + + +def test_action_time_downstream_dependency_is_bound_and_fails_closed(): + packet, record, destination, production_rollback_artifact = _authorization_materials() + destination["downstream_dependency_count"] = 1 + + verification = lifecycle.verify_authorization_record( + packet, + record, + observed_destination=destination, + apply_engine_path=REPO_ROOT / "scripts" / "apply_proposal.py", + production_rollback_artifact=production_rollback_artifact, + now=datetime(2026, 7, 15, 12, 0, tzinfo=timezone.utc), + ) + + assert verification["checks"]["zero_downstream_dependencies_at_action"] is False + assert verification["checks"]["action_readback_provenance_independently_attested"] is False + assert verification["safe_to_enter_apply_window"] is False + + def test_authorization_packet_names_missing_live_gate_before_requesting_auth(tmp_path): receipt = _passing_lifecycle_receipt() destination = _destination(candidate_present=False) From ed827626db066e34342e6a1f13b008a1a923ad47 Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:14:47 +0200 Subject: [PATCH 05/11] Support legacy claim evidence fingerprints --- scripts/run_approve_claim_clone_canary.py | 3 ++- tests/test_run_approve_claim_clone_canary.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/run_approve_claim_clone_canary.py b/scripts/run_approve_claim_clone_canary.py index 2ea28e6..c2e6d55 100644 --- a/scripts/run_approve_claim_clone_canary.py +++ b/scripts/run_approve_claim_clone_canary.py @@ -45,6 +45,7 @@ SECURITY_DEFINER_ARGUMENT_TYPES = { "assert_approved_proposal": "uuid, text, jsonb, text, uuid, timestamp with time zone, text", "finish_approved_proposal": "uuid, text, jsonb, text, uuid, timestamp with time zone, text, text", } +CLAIM_EVIDENCE_FINGERPRINT_ORDER = "ce.claim_id::text, ce.source_id::text, ce.role::text" def _run( @@ -976,7 +977,7 @@ select json_build_object( 'public.agents', {fingerprint("public.agents", "a", "true", "a.id::text")}, 'public.claims', {fingerprint("public.claims", "c", f"not ({claim_predicate})", "c.id::text")}, 'public.sources', {fingerprint("public.sources", "s", f"not ({source_predicate})", "s.id::text")}, - 'public.claim_evidence', {fingerprint("public.claim_evidence", "ce", f"not ({evidence_predicate})", "ce.id::text")}, + 'public.claim_evidence', {fingerprint("public.claim_evidence", "ce", f"not ({evidence_predicate})", CLAIM_EVIDENCE_FINGERPRINT_ORDER)}, 'public.claim_edges', {fingerprint("public.claim_edges", "e", f"not ({edge_predicate})", "e.id::text")}, 'public.reasoning_tools', {fingerprint("public.reasoning_tools", "rt", f"not ({tool_predicate})", "rt.id::text")}, 'kb_stage.kb_proposals', {fingerprint("kb_stage.kb_proposals", "p", f"p.id <> {ap.sql_literal(proposal_id)}::uuid", "p.id::text")}, diff --git a/tests/test_run_approve_claim_clone_canary.py b/tests/test_run_approve_claim_clone_canary.py index a978da0..ad0eccf 100644 --- a/tests/test_run_approve_claim_clone_canary.py +++ b/tests/test_run_approve_claim_clone_canary.py @@ -13,6 +13,11 @@ sys.path.insert(0, str(ROOT / "scripts")) import run_approve_claim_clone_canary as canary # noqa: E402 +def test_unrelated_fingerprint_orders_legacy_claim_evidence_by_composite_key() -> None: + assert canary.CLAIM_EVIDENCE_FINGERPRINT_ORDER == ("ce.claim_id::text, ce.source_id::text, ce.role::text") + assert "ce.id" not in canary.CLAIM_EVIDENCE_FINGERPRINT_ORDER + + def _passing_result(expected_rows: dict, expected_deltas: dict) -> dict: proposal_id = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" return { From 000bda06c28fd3f380521e73409bb2e84420b16c Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:20:34 +0200 Subject: [PATCH 06/11] Apply evidence against the live composite schema --- scripts/apply_proposal.py | 16 ++---- scripts/proposal_apply_lifecycle.py | 76 +++++++++++++++++--------- tests/test_apply_proposal.py | 4 ++ tests/test_proposal_apply_lifecycle.py | 26 +++++++-- 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/scripts/apply_proposal.py b/scripts/apply_proposal.py index f357591..90aaaf2 100644 --- a/scripts/apply_proposal.py +++ b/scripts/apply_proposal.py @@ -439,10 +439,9 @@ def build_attach_evidence_sql( if role not in EVIDENCE_ROLES: raise ValueError(f"attach_evidence.evidence[{i}].role must be one of {sorted(EVIDENCE_ROLES)}") weight = _weight(ev.get("weight"), f"attach_evidence.evidence[{i}].weight") - row_id = deterministic_row_uuid(proposal_id, "claim_evidence", claim_id, source_id, role) statements.append( - f"""insert into public.claim_evidence (id, claim_id, source_id, role, weight) -select {sql_literal(row_id)}::uuid, {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid, + f"""insert into public.claim_evidence (claim_id, source_id, role, weight) +select {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid, {sql_literal(role)}::evidence_role, {sql_literal(weight)} on conflict (claim_id, source_id, role) do nothing;""" ) @@ -594,13 +593,6 @@ def build_approve_claim_sql( raise ValueError(f"{path}.role must be one of {sorted(EVIDENCE_ROLES)}") evidence.append( { - "id": deterministic_row_uuid( - proposal_id, - "claim_evidence", - _uuid(row.get("claim_id"), f"{path}.claim_id"), - _uuid(row.get("source_id"), f"{path}.source_id"), - role, - ), "claim_id": _uuid(row.get("claim_id"), f"{path}.claim_id"), "source_id": _uuid(row.get("source_id"), f"{path}.source_id"), "role": role, @@ -781,8 +773,8 @@ select {sql_literal(row["id"])}::uuid, {sql_literal(row["agent_id"])}::uuid, for row in evidence: conflict_clause = ";" if fresh_owned else "\non conflict (claim_id, source_id, role) do nothing;" statements.append( - f"""insert into public.claim_evidence (id, claim_id, source_id, role, weight, created_by) -select {sql_literal(row["id"])}::uuid, {sql_literal(row["claim_id"])}::uuid, {sql_literal(row["source_id"])}::uuid, + f"""insert into public.claim_evidence (claim_id, source_id, role, weight, created_by) +select {sql_literal(row["claim_id"])}::uuid, {sql_literal(row["source_id"])}::uuid, {sql_literal(row["role"])}::evidence_role, {sql_literal(row["weight"])}, {sql_literal(row["created_by"])}::uuid{conflict_clause}""" ) diff --git a/scripts/proposal_apply_lifecycle.py b/scripts/proposal_apply_lifecycle.py index 03ab6d0..cc0e79b 100644 --- a/scripts/proposal_apply_lifecycle.py +++ b/scripts/proposal_apply_lifecycle.py @@ -69,6 +69,14 @@ DELETE_ORDER = ( ) +def canonical_row_key(family: str, row: dict[str, Any]) -> str | None: + if family == "claim_evidence": + values = (row.get("claim_id"), row.get("source_id"), row.get("role")) + return "|".join(str(value) for value in values) if all(values) else None + identifier = row.get("id") + return str(identifier) if identifier else None + + def canonical_json(value: Any) -> str: return json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True) @@ -288,9 +296,9 @@ def _require_apply_receipt( for name, table_rows in rows.items(): if not isinstance(table_rows, list) or any(not isinstance(row, dict) for row in table_rows): raise ValueError(f"apply receipt {name} rows are malformed") - identifiers = [row.get("id") for row in table_rows] - if any(not identifier for identifier in identifiers) or len(set(identifiers)) != len(identifiers): - raise ValueError(f"apply receipt {name} rows require unique persisted ids") + row_keys = [canonical_row_key(name, row) for row in table_rows] + if any(not row_key for row_key in row_keys) or len(set(row_keys)) != len(row_keys): + raise ValueError(f"apply receipt {name} rows require unique canonical keys") try: replay_receipt.validate_replay_receipt( apply_receipt, @@ -299,16 +307,6 @@ def _require_apply_receipt( except ValueError as exc: raise ValueError("apply receipt failed full replay-contract validation") from exc proposal_id = str(proposal_before.get("id")) - for row in rows["claim_evidence"]: - expected_id = ap.deterministic_row_uuid( - proposal_id, - "claim_evidence", - row.get("claim_id"), - row.get("source_id"), - row.get("role"), - ) - if row.get("id") != expected_id: - raise ValueError("fresh apply receipt evidence id is not deterministic") for row in rows["claim_edges"]: expected_id = ap.deterministic_row_uuid( proposal_id, @@ -322,8 +320,29 @@ def _require_apply_receipt( return rows -def _row_assertion(table: str, row: dict[str, Any], label: str) -> str: +def _evidence_predicate(alias: str, rows: list[dict[str, Any]]) -> str: + if not rows: + return "false" + return ( + "(" + + " or ".join( + f"({alias}.claim_id = {ap.sql_literal(row['claim_id'])}::uuid " + f"and {alias}.source_id = {ap.sql_literal(row['source_id'])}::uuid " + f"and {alias}.role = {ap.sql_literal(row['role'])}::evidence_role)" + for row in rows + ) + + ")" + ) + + +def _row_assertion(family: str, table: str, row: dict[str, Any], label: str) -> str: row_json = ap.sql_literal(canonical_json(row)) + if family == "claim_evidence": + predicate = _evidence_predicate("t", [row]) + return f""" if (select count(*) from {table} t + where {predicate} and to_jsonb(t) = {row_json}::jsonb) <> 1 then + raise exception 'proposal rollback drift: {label} row does not match apply receipt'; + end if;""" row_id = ap.sql_literal(row["id"]) return f""" if (select count(*) from {table} t where t.id = {row_id}::uuid and to_jsonb(t) = {row_json}::jsonb) <> 1 then @@ -331,9 +350,16 @@ def _row_assertion(table: str, row: dict[str, Any], label: str) -> str: end if;""" -def _delete_statement(table: str, rows: list[dict[str, Any]], label: str) -> str: +def _delete_statement(family: str, table: str, rows: list[dict[str, Any]], label: str) -> str: if not rows: return f" -- no {label} rows owned by this proposal" + if family == "claim_evidence": + predicate = _evidence_predicate("target", rows) + return f""" delete from {table} target where {predicate}; + get diagnostics affected = row_count; + if affected <> {len(rows)} then + raise exception 'proposal rollback count mismatch for {label}: expected {len(rows)}, got %', affected; + end if;""" identifiers = ", ".join(f"{ap.sql_literal(row['id'])}::uuid" for row in rows) return f""" delete from {table} where id in ({identifiers}); get diagnostics affected = row_count; @@ -403,16 +429,16 @@ def build_compensating_rollback_sql( approval_json = ap.sql_literal(canonical_json(approval_snapshot)) claim_ids = _uuid_array([str(row["id"]) for row in rows["claims"]]) source_ids = _uuid_array([str(row["id"]) for row in rows["sources"]]) - evidence_ids = _uuid_array([str(row["id"]) for row in rows["claim_evidence"]]) + owned_evidence_predicate = _evidence_predicate("ce", rows["claim_evidence"]) edge_ids = _uuid_array([str(row["id"]) for row in rows["claim_edges"]]) row_assertions = [] for family in DELETE_ORDER: table = ROW_TABLES[family] row_assertions.extend( - _row_assertion(table, row, f"{family}[{index}]") for index, row in enumerate(rows[family]) + _row_assertion(family, table, row, f"{family}[{index}]") for index, row in enumerate(rows[family]) ) - deletions = [_delete_statement(ROW_TABLES[family], rows[family], family) for family in DELETE_ORDER] + deletions = [_delete_statement(family, ROW_TABLES[family], rows[family], family) for family in DELETE_ORDER] return f"""begin; set local standard_conforming_strings = on; @@ -466,7 +492,7 @@ begin select ce.id from public.claim_evidence ce where (ce.claim_id = any({claim_ids}) or ce.source_id = any({source_ids})) - and ce.id <> all({evidence_ids}) + and not ({owned_evidence_predicate}) union all select edge.id from public.claim_edges edge @@ -616,8 +642,8 @@ def validate_production_rollback_artifact( return artifact -def _row_ids(rows: dict[str, list[dict[str, Any]]]) -> dict[str, list[str]]: - return {name: sorted(str(row["id"]) for row in table_rows) for name, table_rows in rows.items()} +def _row_keys(rows: dict[str, list[dict[str, Any]]]) -> dict[str, list[str]]: + return {name: sorted(str(canonical_row_key(name, row)) for row in table_rows) for name, table_rows in rows.items()} def build_lifecycle_receipt( @@ -709,7 +735,7 @@ def build_lifecycle_receipt( "apply_receipt_sha256": sha256_json(apply_receipt), "apply_sql_sha256": apply_receipt["apply_engine"]["apply_sql_sha256"], "fresh_owned_apply_sql_sha256": expected_fresh_apply_sha256, - "applied_row_ids": _row_ids(rows), + "applied_row_keys": _row_keys(rows), "applied_row_sha256": {name: [sha256_json(row) for row in table_rows] for name, table_rows in rows.items()}, "rollback": { "schema": ROLLBACK_SCHEMA, @@ -764,7 +790,7 @@ def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: "apply_receipt_sha256", "apply_sql_sha256", "fresh_owned_apply_sql_sha256", - "applied_row_ids", + "applied_row_keys", "applied_row_sha256", "rollback", "checks", @@ -816,7 +842,7 @@ def _require_lifecycle_receipt(lifecycle_receipt: dict[str, Any]) -> None: raise ValueError("lifecycle receipt is missing an exact SHA-256 binding") if lifecycle_receipt.get("apply_sql_sha256") != lifecycle_receipt.get("fresh_owned_apply_sql_sha256"): raise ValueError("lifecycle receipt apply SQL did not consume the fresh-owned preflight") - row_ids = lifecycle_receipt.get("applied_row_ids") + row_ids = lifecycle_receipt.get("applied_row_keys") row_hashes = lifecycle_receipt.get("applied_row_sha256") if ( not isinstance(row_ids, dict) @@ -1097,7 +1123,7 @@ def build_authorization_packet( "conditional_rollback_requires_explicit_authorization": True, }, "expected_rows": { - "row_ids": lifecycle_receipt["applied_row_ids"], + "row_keys": lifecycle_receipt["applied_row_keys"], "row_sha256": lifecycle_receipt["applied_row_sha256"], }, "production_preconditions": production_preconditions, diff --git a/tests/test_apply_proposal.py b/tests/test_apply_proposal.py index 96bf7e1..65dad6f 100644 --- a/tests/test_apply_proposal.py +++ b/tests/test_apply_proposal.py @@ -149,6 +149,8 @@ def test_attach_evidence_sql_with_source_id(): payload = {"evidence": [{"claim_id": CLAIM_A, "source_id": SOURCE_A, "role": "grounds", "weight": 0.78}]} sql = ap.build_attach_evidence_sql(payload, "pid-3", None, _approval_meta("attach_evidence", payload)) assert "insert into public.claim_evidence" in sql + assert "public.claim_evidence (id," not in sql + assert "public.claim_evidence (claim_id, source_id, role, weight)" in sql assert "::evidence_role" in sql assert "not exists" in sql @@ -251,6 +253,8 @@ def test_approve_claim_bundle_sql_is_atomic_and_row_verified(): assert "insert into public.claims" in sql assert "insert into public.sources" in sql assert "insert into public.claim_evidence" in sql + assert "public.claim_evidence (id," not in sql + assert "public.claim_evidence (claim_id, source_id, role, weight, created_by)" in sql assert "insert into public.claim_edges" in sql assert "insert into public.reasoning_tools" in sql assert "source hash collision" in sql diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index d05fd00..a5cad00 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -139,7 +139,6 @@ def _approval_snapshot(proposal: dict) -> dict: def _canonical_rows() -> dict[str, list[dict]]: - evidence_id = apply.deterministic_row_uuid(PROPOSAL_ID, "claim_evidence", CLAIM_A, SOURCE_ID, "grounds") edge_id = apply.deterministic_row_uuid(PROPOSAL_ID, "claim_edge", CLAIM_A, CLAIM_B, "supports") return { "claims": [ @@ -182,7 +181,6 @@ def _canonical_rows() -> dict[str, list[dict]]: ], "claim_evidence": [ { - "id": evidence_id, "claim_id": CLAIM_A, "source_id": SOURCE_ID, "role": "grounds", @@ -565,11 +563,10 @@ def test_rollback_sql_hash_binds_every_receipt_observed_field(): assert "proposal rollback drift: claims[0] row does not match apply receipt" in changed_sql -@pytest.mark.parametrize("family", ("claim_evidence", "claim_edges")) -def test_fresh_apply_receipt_requires_deterministic_generated_row_ids(family: str): +def test_fresh_apply_receipt_requires_deterministic_generated_edge_ids(): proposal, approval, preflight, receipt, _rollback_sql = _materials() changed_rows = copy.deepcopy(receipt["canonical_rows"]) - changed_rows[family][0]["id"] = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + changed_rows["claim_edges"][0]["id"] = "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" changed_receipt = _apply_receipt(proposal, changed_rows, preflight) with pytest.raises(ValueError, match="is not deterministic"): @@ -581,6 +578,25 @@ def test_fresh_apply_receipt_requires_deterministic_generated_row_ids(family: st ) +def test_fresh_apply_receipt_uses_composite_claim_evidence_key_without_id(): + proposal, approval, preflight, receipt, _rollback_sql = _materials() + evidence = receipt["canonical_rows"]["claim_evidence"][0] + + assert "id" not in evidence + assert lifecycle.canonical_row_key("claim_evidence", evidence) == f"{CLAIM_A}|{SOURCE_ID}|grounds" + + changed_rows = copy.deepcopy(receipt["canonical_rows"]) + changed_rows["claim_evidence"].append(copy.deepcopy(evidence)) + changed_receipt = _apply_receipt(proposal, changed_rows, preflight) + with pytest.raises(ValueError, match=r"unique canonical keys|replay-contract validation"): + lifecycle.build_compensating_rollback_sql( + proposal, + approval, + preflight, + changed_receipt, + ) + + def test_production_rollback_artifact_reconstructs_exact_sql_and_rejects_noop_substitution(): proposal, approval, preflight, apply_receipt, rollback_sql = _materials() destination = { From 8ee04f1cda5aec7d6b8789513af047e8e5c34f2a Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:25:19 +0200 Subject: [PATCH 07/11] Test composite evidence rollback identity --- tests/test_proposal_apply_lifecycle.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index a5cad00..a6294d0 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -585,10 +585,9 @@ def test_fresh_apply_receipt_uses_composite_claim_evidence_key_without_id(): assert "id" not in evidence assert lifecycle.canonical_row_key("claim_evidence", evidence) == f"{CLAIM_A}|{SOURCE_ID}|grounds" - changed_rows = copy.deepcopy(receipt["canonical_rows"]) - changed_rows["claim_evidence"].append(copy.deepcopy(evidence)) - changed_receipt = _apply_receipt(proposal, changed_rows, preflight) - with pytest.raises(ValueError, match=r"unique canonical keys|replay-contract validation"): + changed_receipt = copy.deepcopy(receipt) + changed_receipt["canonical_rows"]["claim_evidence"].append(copy.deepcopy(evidence)) + with pytest.raises(ValueError, match="unique canonical keys"): lifecycle.build_compensating_rollback_sql( proposal, approval, From 0125fbff12a4018d4fb0c9ca4ed0531df1a5ee8c Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:28:59 +0200 Subject: [PATCH 08/11] Use composite evidence keys in rollback dependencies --- scripts/proposal_apply_lifecycle.py | 2 +- tests/test_proposal_apply_lifecycle.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/proposal_apply_lifecycle.py b/scripts/proposal_apply_lifecycle.py index cc0e79b..90cf91d 100644 --- a/scripts/proposal_apply_lifecycle.py +++ b/scripts/proposal_apply_lifecycle.py @@ -489,7 +489,7 @@ begin end if; select count(*) into downstream_dependency_count from ( - select ce.id + select ce.claim_id from public.claim_evidence ce where (ce.claim_id = any({claim_ids}) or ce.source_id = any({source_ids})) and not ({owned_evidence_predicate}) diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index a6294d0..879876e 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -499,6 +499,8 @@ def test_compensating_rollback_is_atomic_deterministic_and_refuses_state_drift() assert delete_positions == sorted(delete_positions) assert "set status = 'canceled'" in rollback_sql assert "downstream_dependency_count" in rollback_sql + assert "select ce.claim_id" in rollback_sql + assert "select ce.id" not in rollback_sql assert "downstream dependenc(ies) exist" in rollback_sql assert "immutable approval snapshot drifted" in rollback_sql From 0ce09dbc785afaeadab3929325a3c0b9f30c2720 Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:32:03 +0200 Subject: [PATCH 09/11] Retain VPS-schema proposal lifecycle proof --- ...oposal-apply-lifecycle-canary-current.json | 1072 +++++++++-------- ...posal-apply-lifecycle-receipt-current.json | 102 +- 2 files changed, 608 insertions(+), 566 deletions(-) diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json index d494493..fbcd79b 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json @@ -1,67 +1,69 @@ { "applied_rollback_receipt": { - "applied_row_ids": { + "applied_row_keys": { "claim_edges": [ - "b28d8770-9ac9-5b5f-bfe2-7280d7422a21" + "3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8" ], "claim_evidence": [ - "13e580c5-458d-5146-aef3-8c74ffc43b7c", - "dac3934f-b7ad-5205-8efe-a00163370a54" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb|bf697d93-8b77-5e2b-a6c0-0825e5ba76fd|grounds", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95|7a2198b6-16b2-52c6-a641-7ad59826e5bf|illustrates" ], "claims": [ - "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "71a3331b-fb75-5e18-aa61-b256bc38af36" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" ], "reasoning_tools": [ - "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + "41b58d96-37f6-526c-b021-58f1dbcfdb6c" ], "sources": [ - "a86f55dc-5058-585d-b492-a4f1d932670f", - "ed9da5f1-846e-5298-8689-15027a7ce56d" + "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" ] }, "applied_row_sha256": { "claim_edges": [ - "60d14cbc45d424fa1eb62db6478f185bf2c2d86559e57ffa77474e8d0b3c527c" + "65e5186be950498bd8ff8ef2043804181ec5bef02c9c1bb36a965dd9410e8b5b" ], "claim_evidence": [ - "e97de162c0730da69b357e1350f0da7e5843c4e67d498c12d731a0f04a8868d7", - "3054718195abe3f78e08cfcacd59902d41eb91c7153c6c63f9bcb3bc7c6902ac" + "9164b7c63641e5cbf5422f50299490053d547ba6ce1108c970b1ebfb89dc8e25", + "c098ddaadc9b7d14e3f0d48f844b88750fc7529813a20762240557abcdb1391b" ], "claims": [ - "e593b9cf7b0bc9267f3e48d8173129b84b09c028f290f1abc97ccb73940b31dc", - "24280b5159cbbf75e00eb24ae50ab69994397a583f347a241a5e262cf0c03179" + "e8cb8a99124bcc1f98fb0316132155c4db6d9dd12879f40a0ece82cc97e54085", + "4ffd395e8534ab7c9d565147667c8e207eacf70dbfcae6e8959e9b9203e4429f" ], "reasoning_tools": [ - "257924b236c3c27289b9ae2314687be0e96779415fc6ff87faada22893b757ba" + "355dee4df27c89809daa214fde69fdfb9f15fc2a29f3985582fe69d7bd797598" ], "sources": [ - "d7a690c2b18701db5b48e8189b1621c8025c1ed75889a4d0a3a4c9761c03dc3b", - "bee048794799006bd00bf4bb02ae57998e670f5bcdfb140dff871dcb042d0198" + "cea718e74eb3d2c2672491e2e6fc523c4c4a4ae3060babbb24652f8004a2c7fd", + "d31a88fff760ed8d5985a2557f20524a372a0ea94893b7ad1aa1d24e6fe58050" ] }, - "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", - "apply_receipt_sha256": "2aa65fe4509c6699af34e418de27c0225efe751223aaebf3f9b545fa159c754e", - "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", - "approval_snapshot_sha256": "310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9", + "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", + "apply_receipt_sha256": "456247af33d4222f76c47c0a4e9228135d7a46c2c04c0f9c928b6bae5f30cde8", + "apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", + "approval_snapshot_sha256": "ae28ff3694a19603b562f3233772ea68371702f22732026c75c33af944428dab", "artifact": "proposal_apply_lifecycle_receipt", "checks": { "apply_receipt_replay_ready": true, "apply_rows_have_exact_ids": true, + "fresh_owned_preflight_consumed_by_apply": true, "fresh_owned_targets": true, "immutable_approval_unchanged": true, "rollback_counts_restored": true, - "rollback_ledger_restored_to_approved": true, + "rollback_ledger_quarantined_from_worker": true, "rollback_replay_refused_without_mutation": true, "rollback_sql_exact_for_bound_rows": true, "rollback_target_rows_absent": true, "unrelated_rows_unchanged": true }, "current_tier": "T2_runtime", - "fresh_preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", - "fresh_preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", - "generated_at_utc": "2026-07-15T01:59:05.526171+00:00", - "lifecycle_receipt_sha256": "8e74cf1f5c372633f9b6f15363ff759ba6ce9bf42df51288bb9be70ddabe49b3", + "fresh_owned_apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", + "fresh_preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", + "fresh_preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", + "generated_at_utc": "2026-07-15T03:30:13.458916+00:00", + "lifecycle_receipt_sha256": "6a94df2a04b9b71f931d23d5e5fba3aa295395f9ef636f490bcffdd43d1af697", "pass": true, "production_apply_authorization_present": false, "production_apply_executed": false, @@ -69,7 +71,7 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -77,7 +79,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -90,7 +92,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -106,24 +108,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -132,7 +134,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -140,8 +142,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -149,8 +151,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -160,12 +162,12 @@ }, "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "approved" }, - "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", "required_tier": "T2_runtime", "rollback": { "counts_after_rollback": { @@ -195,16 +197,16 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", - "status": "approved" + "status": "canceled" }, - "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", - "schema": "livingip.proposalApplyRollback.v1", + "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "schema": "livingip.proposalApplyRollback.v2", "target_rows_after": { "claim_edges": [], "claim_evidence": [], @@ -213,16 +215,16 @@ "sources": [] } }, - "schema": "livingip.proposalApplyLifecycleReceipt.v1", + "schema": "livingip.proposalApplyLifecycleReceipt.v2", "strongest_claim_allowed": "deterministic disposable-clone apply and compensating rollback" }, "apply_transition": { "applied_readback": { - "applied_at": "2026-07-15 01:59:04.449051+00", + "applied_at": "2026-07-15 03:30:10.578016+00", "applied_by_agent_id": "44444444-4444-4444-4444-444444444444", "applied_by_handle": "kb-apply", "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -230,7 +232,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -243,7 +245,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -259,24 +261,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -285,7 +287,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -293,8 +295,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -302,8 +304,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -314,8 +316,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "applied" @@ -325,7 +327,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -333,7 +335,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -346,7 +348,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -362,24 +364,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -388,7 +390,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -396,8 +398,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -405,8 +407,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -417,8 +419,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -433,7 +435,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -446,7 +448,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -462,24 +464,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -488,7 +490,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -496,8 +498,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -505,8 +507,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -514,11 +516,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" } @@ -534,8 +536,9 @@ "conflict_transaction_rolled_back_exactly": true, "first_apply_succeeded": true, "fresh_owned_preflight_exact": true, - "gateway_process_unchanged": null, + "gateway_process_unchanged": true, "idempotent_replay_refused": true, + "intervening_exact_row_refused_without_adoption": true, "kb_apply_cannot_mutate_immutable_approval": true, "kb_apply_cannot_mutate_proposal_approval": true, "kb_apply_cannot_mutate_proposal_payload": true, @@ -557,9 +560,11 @@ "outer_workdir_absent_independent_readback": true, "payload_agents_seeded_exactly": true, "payload_projection_exact": true, + "post_rollback_worker_reapply_refused": true, "proposal_exact_after_permission_probes": true, "review_transition_exact": true, "reviewer_agent_seeded_exactly": true, + "rollback_refuses_downstream_dependencies_without_deletion": true, "rollback_replay_refused_without_mutation": true, "security_definer_dependencies_ready": true, "source_binding_independently_verified": true, @@ -604,7 +609,7 @@ "public.sources": 1 }, "clone_created": true, - "clone_database": "teleo_approve_claim_isolated_08c2358330", + "clone_database": "teleo_approve_claim_isolated_4d6107db5d", "clone_dropped": true, "clone_prerequisite_sanitization": { "clone_sql_sha256": "a02a03a704954058745d8cee4d25597bb8eaeee2ae211d4f9be4fe055f3d98ec", @@ -616,7 +621,7 @@ "conflict_apply": { "returncode": 1, "source_hash_collision_refusal": true, - "stderr": "psql failed (3)\nSTDOUT:\n\n\nSTDERR:\nERROR: approve_claim: source hash collision for source 980ac481-1fa3-508f-b093-95de4ff4f8bc\nCONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE" + "stderr": "psql failed (3)\nSTDOUT:\n\n\nSTDERR:\nERROR: approve_claim: source hash collision for source 4d393879-78d4-59e1-a41a-498c5fa8e1cb\nCONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE" }, "conflict_readback": { "canonical_rows": { @@ -635,7 +640,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", "status": "open", "superseded_by": null, "tags": [ @@ -653,8 +658,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", - "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", + "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", "source_type": "observation", "storage_path": null, "url": null @@ -662,11 +667,11 @@ ] } }, - "proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", + "proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:06.046049+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -676,7 +681,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", "payload": { "apply_payload": { "agent_id": null, @@ -684,7 +689,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", "status": "open", "superseded_by": null, "tags": [ @@ -702,8 +707,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", - "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", + "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", "source_type": "observation", "storage_path": null, "url": null @@ -714,8 +719,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:06.046049+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-conflict-canary", "status": "approved" @@ -728,7 +733,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", "payload": { "apply_payload": { "agent_id": null, @@ -736,7 +741,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", "status": "open", "superseded_by": null, "tags": [ @@ -754,8 +759,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", - "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", + "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", "source_type": "observation", "storage_path": null, "url": null @@ -766,8 +771,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:06.046049+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-conflict-canary", "status": "approved" @@ -782,7 +787,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", "status": "open", "superseded_by": null, "tags": [ @@ -800,8 +805,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", - "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", + "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", "source_type": "observation", "storage_path": null, "url": null @@ -809,11 +814,11 @@ ] } }, - "proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", + "proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:06.046049+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -823,7 +828,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "7cb1468f-861c-5a85-ae32-470d891af133", + "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", "payload": { "apply_payload": { "agent_id": null, @@ -831,7 +836,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", + "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", "status": "open", "superseded_by": null, "tags": [ @@ -849,8 +854,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-c4893cfb-8725-510e-ae01-ef01e8c99723", - "id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", + "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", + "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", "source_type": "observation", "storage_path": null, "url": null @@ -870,10 +875,10 @@ "review_apply": { "returncode": 0, "stderr": "", - "stdout": "{\"id\": \"7cb1468f-861c-5a85-ae32-470d891af133\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 01:59:06.046049+00\", \"reviewed_by_agent_id\": \"11111111-1111-4111-8111-111111111111\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + "stdout": "{\"id\": \"3e80ebda-c58d-5d4a-aaba-c2140371c1f4\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:30:14.021982+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" } }, - "current_tier": "T2_runtime", + "current_tier": "T3_live_readonly", "dependencies": { "apply_role": "kb_apply", "apply_script": "scripts/apply_proposal.py", @@ -904,6 +909,13 @@ "kb_stage.finish_approved_proposal" ] }, + "downstream_dependency_rollback_refusal": { + "dependency_refusal": true, + "dependency_row_preserved": true, + "owned_rows_preserved": true, + "proposal_remained_applied": true, + "returncode": 3 + }, "external_claim_seed": { "clone_rows": [], "exact_clone_copy": true, @@ -913,31 +925,31 @@ "first_apply": { "result": { "applied": true, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", - "replay_material_sha256": "767fe35fc91b4cd9b82287e828d6a6a86521bd82f23b651e9a91db977c55af59", + "replay_material_sha256": "3583ba36b109a0269c4c495fba325fe419a4776238959cadd49f67b4831520c6", "replay_ready": true }, "returncode": 0, "stderr": "" }, "fixture_ids": { - "conflict_claim_id": "3543c9a6-9439-5f56-9d1d-60268ea53a10", - "conflict_proposal_id": "7cb1468f-861c-5a85-ae32-470d891af133", - "conflict_source_id": "980ac481-1fa3-508f-b093-95de4ff4f8bc", - "permission_claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", - "permission_source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946" + "conflict_claim_id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "conflict_proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "conflict_source_id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "permission_claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", + "permission_source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d" }, "fresh_owned_preflight": { - "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", + "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", "artifact": "proposal_apply_fresh_preflight", - "captured_at_utc": "2026-07-15T01:59:04.091167+00:00", + "captured_at_utc": "2026-07-15T03:30:09.318963+00:00", "fresh_owned_targets": true, - "preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", - "preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", - "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", + "preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", "proposal_type": "approve_claim", "schema": "livingip.proposalApplyFreshPreflight.v1", "target_rows_before": { @@ -948,19 +960,25 @@ "sources": [] } }, - "gateway_process_observable": false, - "generated_at_utc": "2026-07-15T01:59:02.013207+00:00", + "gateway_process_observable": true, + "generated_at_utc": "2026-07-15T03:30:04.429291+00:00", "idempotent_replay": { "already_applied_refusal": true, "returncode": 1, - "stderr": "proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 is already applied (idempotent no-op)" + "stderr": "proposal 0b5cfd03-8c1f-509a-b1e1-a05e45164d8d is already applied (idempotent no-op)" + }, + "intervening_exact_row_refusal": { + "intervening_row_preserved": true, + "proposal_remained_approved": true, + "returncode": 1, + "strict_insert_refused": true }, "kb_apply_claim_evidence_update_probe": { "after": { - "claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", + "claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", "created_by": null, "role": "grounds", - "source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", + "source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", "weight": 0.42 }, "attempt": { @@ -970,10 +988,10 @@ "stdout": "" }, "before": { - "claim_id": "199b9d5e-904a-52cf-9f2c-3ee97f3f54b4", + "claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", "created_by": null, "role": "grounds", - "source_id": "c4893cfb-8725-510e-ae01-ef01e8c99723", + "source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", "weight": 0.42 }, "exact_row_unchanged": true @@ -984,7 +1002,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -992,7 +1010,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1005,7 +1023,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1021,24 +1039,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1047,7 +1065,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1055,8 +1073,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1064,8 +1082,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1076,8 +1094,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -1093,7 +1111,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -1101,7 +1119,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1114,7 +1132,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1130,24 +1148,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1156,7 +1174,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1164,8 +1182,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1173,8 +1191,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1185,8 +1203,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -1200,7 +1218,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1213,7 +1231,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1229,24 +1247,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1255,7 +1273,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1263,8 +1281,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1272,8 +1290,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1281,11 +1299,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -1297,7 +1315,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1310,7 +1328,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1326,24 +1344,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1352,7 +1370,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1360,8 +1378,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1369,8 +1387,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1378,11 +1396,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -1408,7 +1426,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -1416,7 +1434,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1429,7 +1447,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1445,24 +1463,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1471,7 +1489,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1479,8 +1497,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1488,8 +1506,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1500,14 +1518,14 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" }, "build_returncode": 0, - "built_sql_sha256": "19f5dd6c27f293bfdc89adee59ffa99beb4503dba5aaa6291c9808ff16769ee7", + "built_sql_sha256": "ca785dbaf04dc37ff25b563a42ae2f645780562df3aba1a41b1711b9b83d694f", "built_sql_uses_assert_approved_proposal": true, "built_sql_uses_finish_approved_proposal": true, "canonical_rows_unchanged": true, @@ -1519,7 +1537,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1532,7 +1550,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1548,24 +1566,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1574,7 +1592,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1582,8 +1600,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1591,8 +1609,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1600,11 +1618,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -1616,7 +1634,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1629,7 +1647,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1645,24 +1663,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1671,7 +1689,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1679,8 +1697,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1688,8 +1706,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1697,11 +1715,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -1713,7 +1731,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1726,7 +1744,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1742,24 +1760,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1768,7 +1786,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1776,8 +1794,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1785,8 +1803,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1794,11 +1812,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -1808,7 +1826,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -1816,7 +1834,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1829,7 +1847,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1845,24 +1863,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1871,7 +1889,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1879,8 +1897,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1888,8 +1906,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -1901,8 +1919,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -1912,7 +1930,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -1920,7 +1938,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -1933,7 +1951,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -1949,24 +1967,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -1975,7 +1993,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -1983,8 +2001,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -1992,8 +2010,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2005,8 +2023,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -2019,7 +2037,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2032,7 +2050,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2048,24 +2066,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2074,7 +2092,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2082,8 +2100,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2091,8 +2109,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2100,11 +2118,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -2113,7 +2131,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -2121,7 +2139,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2134,7 +2152,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2150,24 +2168,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2176,7 +2194,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2184,8 +2202,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2193,8 +2211,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2205,8 +2223,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -2221,7 +2239,7 @@ "stale_apply_refused": true, "stale_execute": { "returncode": 3, - "stderr": "ERROR: assert_approved_proposal: proposal 9b2b5fa4-0e0d-5db0-aa4d-6fd102889946 is not the exact immutable approved snapshot\nCONTEXT: PL/pgSQL function kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamp with time zone,text) line 22 at RAISE", + "stderr": "ERROR: assert_approved_proposal: proposal 0b5cfd03-8c1f-509a-b1e1-a05e45164d8d is not the exact immutable approved snapshot\nCONTEXT: PL/pgSQL function kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamp with time zone,text) line 22 at RAISE", "stdout": "" } }, @@ -2249,7 +2267,7 @@ }, "container_isolation": { "canary_label": "proposal-apply-lifecycle", - "instance_label": "working-leo-approve-claim-6715-44544", + "instance_label": "working-leo-approve-claim-1281-2032206", "lifecycle_labeled": true, "network_disabled": true, "network_mode": "none", @@ -2257,39 +2275,47 @@ "volume_mounts": [] }, "service_after": { - "Available": "false", - "Reason": "systemctl_unavailable" + "ActiveState": "active", + "Available": "true", + "ExecMainStartTimestamp": "Tue 2026-07-14 22:59:43 UTC", + "MainPID": "347406", + "NRestarts": "0", + "SubState": "running" }, "service_before": { - "Available": "false", - "Reason": "systemctl_unavailable" + "ActiveState": "active", + "Available": "true", + "ExecMainStartTimestamp": "Tue 2026-07-14 22:59:43 UTC", + "MainPID": "347406", + "NRestarts": "0", + "SubState": "running" }, "service_gate_passes": true, - "service_observable": false, - "service_required": false, - "service_stable": null, + "service_observable": true, + "service_required": true, + "service_stable": true, "source_boundary": { - "canary_label": "working-leo-approved-source", - "network_mode": "none", - "source_tier": "isolated-local", + "canary_label": "", + "network_mode": "bridge", + "source_tier": "live-readonly", "tier_enforced": true }, - "source_container": "leo-proposal-lifecycle-source-20260715", + "source_container": "teleo-pg", "source_counts_after": { - "kb_stage.kb_proposals": 0, - "public.claim_edges": 0, - "public.claim_evidence": 0, - "public.claims": 2, - "public.reasoning_tools": 0, - "public.sources": 0 + "kb_stage.kb_proposals": 29, + "public.claim_edges": 4916, + "public.claim_evidence": 4670, + "public.claims": 1837, + "public.reasoning_tools": 17, + "public.sources": 4145 }, "source_counts_before": { - "kb_stage.kb_proposals": 0, - "public.claim_edges": 0, - "public.claim_evidence": 0, - "public.claims": 2, - "public.reasoning_tools": 0, - "public.sources": 0 + "kb_stage.kb_proposals": 29, + "public.claim_edges": 4916, + "public.claim_evidence": 4670, + "public.claims": 1837, + "public.reasoning_tools": 17, + "public.sources": 4145 }, "source_counts_unchanged": true, "source_database": "teleo" @@ -2306,24 +2332,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "claim_evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2331,7 +2357,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2344,7 +2370,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2360,7 +2386,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2368,8 +2394,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2377,8 +2403,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2393,19 +2419,25 @@ "public.reasoning_tools": 1, "public.sources": 2 }, - "payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684" + "payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02" + }, + "post_rollback_worker_apply": { + "proposal_status": "canceled", + "returncode": 1, + "terminal_status_refusal": true }, "post_run_cleanup": { - "gateway_active_state": null, - "gateway_main_pid": null, - "gateway_process_observable": false, - "gateway_restart_count": null, - "gateway_sub_state": null, + "gateway_active_state": "active", + "gateway_main_pid": "347406", + "gateway_process_observable": true, + "gateway_restart_count": "0", + "gateway_sub_state": "running", "leftover_clone_database_count": 0 }, - "required_tier": "T2_runtime", + "required_tier": "T3_live_readonly", "required_tiers": [ - "T2_runtime" + "T2_runtime", + "T3_live_readonly" ], "review_transition": { "approved_readback": { @@ -2413,7 +2445,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -2421,7 +2453,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2434,7 +2466,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2450,24 +2482,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2476,7 +2508,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2484,8 +2516,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2493,8 +2525,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2505,8 +2537,8 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" @@ -2521,7 +2553,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2534,7 +2566,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2550,24 +2582,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2576,7 +2608,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2584,8 +2616,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2593,8 +2625,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2602,11 +2634,11 @@ ] } }, - "proposal_id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" }, @@ -2616,7 +2648,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -2624,7 +2656,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2637,7 +2669,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2653,24 +2685,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2679,7 +2711,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2687,8 +2719,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -2696,8 +2728,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2717,7 +2749,7 @@ "review_apply": { "returncode": 0, "stderr": "", - "stdout": "{\"id\": \"9b2b5fa4-0e0d-5db0-aa4d-6fd102889946\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 01:59:03.105846+00\", \"reviewed_by_agent_id\": \"11111111-1111-4111-8111-111111111111\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + "stdout": "{\"id\": \"0b5cfd03-8c1f-509a-b1e1-a05e45164d8d\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:30:07.092864+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" }, "review_dry_run": { "returncode": 0, @@ -2728,51 +2760,51 @@ "reviewer_agent_seed": { "clone_row": { "handle": "m3ta", - "id": "11111111-1111-4111-8111-111111111111", + "id": "99999999-9999-9999-9999-999999999999", "kind": "human" }, "exact_clone_copy": true, "reviewer_handle": "m3ta", "source_row": { "handle": "m3ta", - "id": "11111111-1111-4111-8111-111111111111", + "id": "99999999-9999-9999-9999-999999999999", "kind": "human" } }, "rollback_plan": { "execution_authority": "disposable_clone_admin_only", - "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", - "schema": "livingip.proposalApplyRollback.v1" + "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "schema": "livingip.proposalApplyRollback.v2" }, "rollback_replay": { "refused": true, "returncode": 3, "state_unchanged": true, - "stderr": "ERROR: proposal rollback: applied ledger does not match apply receipt\nCONTEXT: PL/pgSQL function inline_code_block line 26 at RAISE" + "stderr": "ERROR: proposal rollback: applied ledger does not match apply receipt\nCONTEXT: PL/pgSQL function inline_code_block line 27 at RAISE" }, "row_readback": { "claim_edges": [ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "claim_evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -2780,7 +2812,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -2793,7 +2825,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -2809,7 +2841,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -2817,8 +2849,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -2826,15 +2858,15 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null } ] }, - "runtime_scope": "isolated_postgres_container_from_readonly_local_fixture", + "runtime_scope": "isolated_postgres_container_from_readonly_live_schema", "schema": "working-leo.approve-claim-clone-canary.v3", "security_definer_readback": { "functions": [ @@ -2892,22 +2924,30 @@ "unexpected_overloads": [] }, "service_after": { - "available": false, - "reason": "systemctl_unavailable", - "returncode": 127 + "ActiveState": "active", + "ExecMainStartTimestamp": "Tue 2026-07-14 22:59:43 UTC", + "MainPID": "347406", + "NRestarts": "0", + "SubState": "running", + "available": true, + "returncode": 0 }, "service_before": { - "available": false, - "reason": "systemctl_unavailable", - "returncode": 127 + "ActiveState": "active", + "ExecMainStartTimestamp": "Tue 2026-07-14 22:59:43 UTC", + "MainPID": "347406", + "NRestarts": "0", + "SubState": "running", + "available": true, + "returncode": 0 }, - "service_restarted": null, + "service_restarted": false, "source_binding": { "files": [ { "repo_relative_path": "scripts/apply_proposal.py", - "sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", - "size_bytes": 47270 + "sha256": "9b95601753203c167190c4a33a05bd36fd68178cfc4cbd76be7c0c69e103b52f", + "size_bytes": 50074 }, { "repo_relative_path": "scripts/approve_proposal.py", @@ -2926,13 +2966,13 @@ }, { "repo_relative_path": "scripts/proposal_apply_lifecycle.py", - "sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", - "size_bytes": 71314 + "sha256": "1122cc3a02a93ca1a41d6088a4852b3f4f47efa5c7a373c19c46605cff4853e6", + "size_bytes": 86177 }, { "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", - "sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", - "size_bytes": 88340 + "sha256": "66f176712c9aa3d3dc8f18b6313b8ca393f2e93c0acce2b4d2344d97905c55c7", + "size_bytes": 94909 }, { "repo_relative_path": "scripts/run_approve_claim_isolated_container_canary.sh", @@ -2944,11 +2984,11 @@ "all_match": true, "files": [ { - "actual_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", - "expected_sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", + "actual_sha256": "9b95601753203c167190c4a33a05bd36fd68178cfc4cbd76be7c0c69e103b52f", + "expected_sha256": "9b95601753203c167190c4a33a05bd36fd68178cfc4cbd76be7c0c69e103b52f", "matches": true, "repo_relative_path": "scripts/apply_proposal.py", - "size_bytes": 47270 + "size_bytes": 50074 }, { "actual_sha256": "e991498264bd0f49755dfef809212fa7151a668ce479b100d830e447775a9fe0", @@ -2972,18 +3012,18 @@ "size_bytes": 42602 }, { - "actual_sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", - "expected_sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", + "actual_sha256": "1122cc3a02a93ca1a41d6088a4852b3f4f47efa5c7a373c19c46605cff4853e6", + "expected_sha256": "1122cc3a02a93ca1a41d6088a4852b3f4f47efa5c7a373c19c46605cff4853e6", "matches": true, "repo_relative_path": "scripts/proposal_apply_lifecycle.py", - "size_bytes": 71314 + "size_bytes": 86177 }, { - "actual_sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", - "expected_sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", + "actual_sha256": "66f176712c9aa3d3dc8f18b6313b8ca393f2e93c0acce2b4d2344d97905c55c7", + "expected_sha256": "66f176712c9aa3d3dc8f18b6313b8ca393f2e93c0acce2b4d2344d97905c55c7", "matches": true, "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", - "size_bytes": 88340 + "size_bytes": 94909 }, { "actual_sha256": "ed81a8f8c05d516809bb54c80d82786ed941dc1cf87150f25addc935685c72bb", @@ -2997,8 +3037,8 @@ "post_run_files": [ { "repo_relative_path": "scripts/apply_proposal.py", - "sha256": "ca2c0a0c1031393c95a26102d57339654d2363f4c51cdf39aabb9071d0ca6c26", - "size_bytes": 47270 + "sha256": "9b95601753203c167190c4a33a05bd36fd68178cfc4cbd76be7c0c69e103b52f", + "size_bytes": 50074 }, { "repo_relative_path": "scripts/approve_proposal.py", @@ -3017,13 +3057,13 @@ }, { "repo_relative_path": "scripts/proposal_apply_lifecycle.py", - "sha256": "a643b83b55c9e76f545ebafb9582d6d07ff432600c1b66004cc7440d7ac1963b", - "size_bytes": 71314 + "sha256": "1122cc3a02a93ca1a41d6088a4852b3f4f47efa5c7a373c19c46605cff4853e6", + "size_bytes": 86177 }, { "repo_relative_path": "scripts/run_approve_claim_clone_canary.py", - "sha256": "bd7ae232b20ff77f15560d7bd07b929f419fb615425c9970fb00afc8080d86ef", - "size_bytes": 88340 + "sha256": "66f176712c9aa3d3dc8f18b6313b8ca393f2e93c0acce2b4d2344d97905c55c7", + "size_bytes": 94909 }, { "repo_relative_path": "scripts/run_approve_claim_isolated_container_canary.sh", @@ -3113,7 +3153,7 @@ "kb_stage.kb_proposals": 0, "public.claim_edges": 0, "public.claim_evidence": 0, - "public.claims": 2, + "public.claims": 1837, "public.reasoning_tools": 0, "public.sources": 0 }, @@ -3121,7 +3161,7 @@ "kb_stage.kb_proposals": 0, "public.claim_edges": 0, "public.claim_evidence": 0, - "public.claims": 2, + "public.claims": 1837, "public.reasoning_tools": 0, "public.sources": 0 }, @@ -3157,64 +3197,64 @@ "public.claim_edges": [ { "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36" + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" } ], "public.claim_evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d" + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f" + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf" } ], "public.claims": [ - "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "71a3331b-fb75-5e18-aa61-b256bc38af36" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" ], "public.reasoning_tools": [ - "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + "41b58d96-37f6-526c-b021-58f1dbcfdb6c" ], "public.sources": [ - "a86f55dc-5058-585d-b492-a4f1d932670f", - "ed9da5f1-846e-5298-8689-15027a7ce56d" + "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" ] }, "expected": { "public.claim_edges": [ { "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36" + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" } ], "public.claim_evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d" + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f" + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf" } ], "public.claims": [ - "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "71a3331b-fb75-5e18-aa61-b256bc38af36" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" ], "public.reasoning_tools": [ - "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + "41b58d96-37f6-526c-b021-58f1dbcfdb6c" ], "public.sources": [ - "a86f55dc-5058-585d-b492-a4f1d932670f", - "ed9da5f1-846e-5298-8689-15027a7ce56d" + "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" ] } }, @@ -3232,9 +3272,9 @@ }, "pass": true, "proposal": { - "applied_at": "2026-07-15 01:59:04.449051+00", + "applied_at": "2026-07-15 03:30:10.578016+00", "applied_by_handle": "kb-apply", - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "status": "applied" }, "rollback_cleanup": { @@ -3297,7 +3337,7 @@ "row_count": 0 }, "public.agents": { - "content_md5": "56bbdd947ace3bd545744a2995795702", + "content_md5": "d67081359e7ec2fa2101b26f3e1b3f75", "row_count": 2 }, "public.claim_edges": { @@ -3305,11 +3345,11 @@ "row_count": 0 }, "public.claim_evidence": { - "content_md5": "bc66b511bcc4926bb9065f98b41ce8ae", + "content_md5": "da01cd47b5562650406f21a18aaea9b6", "row_count": 1 }, "public.claims": { - "content_md5": "5cfbe5bd4ed3dc24adab29cb39f0b594", + "content_md5": "01ad0f2d690600be6a1988899c3e743e", "row_count": 1 }, "public.reasoning_tools": { @@ -3317,7 +3357,7 @@ "row_count": 0 }, "public.sources": { - "content_md5": "592f899d41dfeeecdb449402eb97ebd3", + "content_md5": "18a42c193671894196c47d58da8da024", "row_count": 1 } } diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json index e5a2a3d..b3e663d 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json @@ -1,66 +1,68 @@ { - "applied_row_ids": { + "applied_row_keys": { "claim_edges": [ - "b28d8770-9ac9-5b5f-bfe2-7280d7422a21" + "3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8" ], "claim_evidence": [ - "13e580c5-458d-5146-aef3-8c74ffc43b7c", - "dac3934f-b7ad-5205-8efe-a00163370a54" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb|bf697d93-8b77-5e2b-a6c0-0825e5ba76fd|grounds", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95|7a2198b6-16b2-52c6-a641-7ad59826e5bf|illustrates" ], "claims": [ - "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "71a3331b-fb75-5e18-aa61-b256bc38af36" + "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" ], "reasoning_tools": [ - "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0" + "41b58d96-37f6-526c-b021-58f1dbcfdb6c" ], "sources": [ - "a86f55dc-5058-585d-b492-a4f1d932670f", - "ed9da5f1-846e-5298-8689-15027a7ce56d" + "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" ] }, "applied_row_sha256": { "claim_edges": [ - "60d14cbc45d424fa1eb62db6478f185bf2c2d86559e57ffa77474e8d0b3c527c" + "65e5186be950498bd8ff8ef2043804181ec5bef02c9c1bb36a965dd9410e8b5b" ], "claim_evidence": [ - "e97de162c0730da69b357e1350f0da7e5843c4e67d498c12d731a0f04a8868d7", - "3054718195abe3f78e08cfcacd59902d41eb91c7153c6c63f9bcb3bc7c6902ac" + "9164b7c63641e5cbf5422f50299490053d547ba6ce1108c970b1ebfb89dc8e25", + "c098ddaadc9b7d14e3f0d48f844b88750fc7529813a20762240557abcdb1391b" ], "claims": [ - "e593b9cf7b0bc9267f3e48d8173129b84b09c028f290f1abc97ccb73940b31dc", - "24280b5159cbbf75e00eb24ae50ab69994397a583f347a241a5e262cf0c03179" + "e8cb8a99124bcc1f98fb0316132155c4db6d9dd12879f40a0ece82cc97e54085", + "4ffd395e8534ab7c9d565147667c8e207eacf70dbfcae6e8959e9b9203e4429f" ], "reasoning_tools": [ - "257924b236c3c27289b9ae2314687be0e96779415fc6ff87faada22893b757ba" + "355dee4df27c89809daa214fde69fdfb9f15fc2a29f3985582fe69d7bd797598" ], "sources": [ - "d7a690c2b18701db5b48e8189b1621c8025c1ed75889a4d0a3a4c9761c03dc3b", - "bee048794799006bd00bf4bb02ae57998e670f5bcdfb140dff871dcb042d0198" + "cea718e74eb3d2c2672491e2e6fc523c4c4a4ae3060babbb24652f8004a2c7fd", + "d31a88fff760ed8d5985a2557f20524a372a0ea94893b7ad1aa1d24e6fe58050" ] }, - "apply_payload_sha256": "c89bc03ce7714f325293329a0bf95eaba0a56c596ef021d731b48dab0447c684", - "apply_receipt_sha256": "2aa65fe4509c6699af34e418de27c0225efe751223aaebf3f9b545fa159c754e", - "apply_sql_sha256": "1a7d65870e415ee8891b6dd84732a29bcee00412c10862d3d1db4b191a8ade38", - "approval_snapshot_sha256": "310b54030e26ed43d7226f2e803610586e80d21ff064c67e11ea21e93ef40bd9", + "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", + "apply_receipt_sha256": "456247af33d4222f76c47c0a4e9228135d7a46c2c04c0f9c928b6bae5f30cde8", + "apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", + "approval_snapshot_sha256": "ae28ff3694a19603b562f3233772ea68371702f22732026c75c33af944428dab", "artifact": "proposal_apply_lifecycle_receipt", "checks": { "apply_receipt_replay_ready": true, "apply_rows_have_exact_ids": true, + "fresh_owned_preflight_consumed_by_apply": true, "fresh_owned_targets": true, "immutable_approval_unchanged": true, "rollback_counts_restored": true, - "rollback_ledger_restored_to_approved": true, + "rollback_ledger_quarantined_from_worker": true, "rollback_replay_refused_without_mutation": true, "rollback_sql_exact_for_bound_rows": true, "rollback_target_rows_absent": true, "unrelated_rows_unchanged": true }, "current_tier": "T2_runtime", - "fresh_preflight_artifact_sha256": "1d5e7eed7355aa94ecfa213422e6178aecdeee70628994596e852bd7569d6a2d", - "fresh_preflight_sha256": "29a80dc9422af45fd067e98621442d31c60161f34deb5845aa410659a9c5de3a", - "generated_at_utc": "2026-07-15T01:59:05.526171+00:00", - "lifecycle_receipt_sha256": "8e74cf1f5c372633f9b6f15363ff759ba6ce9bf42df51288bb9be70ddabe49b3", + "fresh_owned_apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", + "fresh_preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", + "fresh_preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", + "generated_at_utc": "2026-07-15T03:30:13.458916+00:00", + "lifecycle_receipt_sha256": "6a94df2a04b9b71f931d23d5e5fba3aa295395f9ef636f490bcffdd43d1af697", "pass": true, "production_apply_authorization_present": false, "production_apply_executed": false, @@ -68,7 +70,7 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "payload": { "apply_payload": { "agent_id": null, @@ -76,7 +78,7 @@ { "confidence": 0.9, "created_by": null, - "id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "status": "open", "superseded_by": null, "tags": [ @@ -89,7 +91,7 @@ { "confidence": 0.85, "created_by": null, - "id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "status": "open", "superseded_by": null, "tags": [ @@ -105,24 +107,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", - "to_claim": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "weight": 0.75 } ], "evidence": [ { - "claim_id": "38dead14-6b1d-5909-99c4-3c45ad2dd21f", + "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", "created_by": null, "role": "grounds", - "source_id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "weight": 0.9 }, { - "claim_id": "71a3331b-fb75-5e18-aa61-b256bc38af36", + "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", "created_by": null, "role": "illustrates", - "source_id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "weight": 0.8 } ], @@ -131,7 +133,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0", + "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", "name": "Canonical row proof canary" } ], @@ -139,8 +141,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-08c2358330-a", - "id": "ed9da5f1-846e-5298-8689-15027a7ce56d", + "hash": "approve-claim-canary-4d6107db5d-a", + "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", "source_type": "observation", "storage_path": null, "url": null @@ -148,8 +150,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-08c2358330-b", - "id": "a86f55dc-5058-585d-b492-a4f1d932670f", + "hash": "approve-claim-canary-4d6107db5d-b", + "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", "source_type": "observation", "storage_path": null, "url": null @@ -159,12 +161,12 @@ }, "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "approved" }, - "proposal_payload_sha256": "6fba5e8e105a28dfaf5733ff7c9f85a20d31d653add0bc4a0f81e4b08de803af", + "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", "required_tier": "T2_runtime", "rollback": { "counts_after_rollback": { @@ -194,16 +196,16 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "9b2b5fa4-0e0d-5db0-aa4d-6fd102889946", + "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 01:59:03.105846+00", - "reviewed_by_agent_id": "11111111-1111-4111-8111-111111111111", + "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", - "status": "approved" + "status": "canceled" }, - "rollback_sql_sha256": "ef2464a6802426509333861cf0768ca64184901ab7bd2030529e7356a35d9cb3", - "schema": "livingip.proposalApplyRollback.v1", + "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "schema": "livingip.proposalApplyRollback.v2", "target_rows_after": { "claim_edges": [], "claim_evidence": [], @@ -212,6 +214,6 @@ "sources": [] } }, - "schema": "livingip.proposalApplyLifecycleReceipt.v1", + "schema": "livingip.proposalApplyLifecycleReceipt.v2", "strongest_claim_allowed": "deterministic disposable-clone apply and compensating rollback" } From 224a448bb195be610aaec2f4423105f2bf10284d Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:34:16 +0200 Subject: [PATCH 10/11] Verify retained live-schema lifecycle proof --- .../proposal-apply-clone-rollback-current.sql | 73 ++++++++++++------- tests/test_proposal_apply_lifecycle.py | 16 +++- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql index 299b52b..caea6a2 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql +++ b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql @@ -1,31 +1,32 @@ begin; set local standard_conforming_strings = on; set local lock_timeout = '5s'; -select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946', 0)); +select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d', 0)); do $rollback$ declare affected integer; approval_now jsonb; + downstream_dependency_count integer; begin perform 1 from kb_stage.kb_proposals - where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid for update; if not found then raise exception 'proposal rollback: proposal row missing'; end if; if not exists ( select 1 from kb_stage.kb_proposals - where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid and proposal_type = 'approve_claim' and status = 'applied' - and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb and reviewed_by_handle is not distinct from E'm3ta' - and reviewed_by_agent_id is not distinct from E'11111111-1111-4111-8111-111111111111'::uuid - and reviewed_at is not distinct from E'2026-07-15 01:59:03.105846+00'::timestamptz + and reviewed_by_agent_id is not distinct from E'99999999-9999-9999-9999-999999999999'::uuid + and reviewed_at is not distinct from E'2026-07-15 03:30:07.092864+00'::timestamptz and review_note is not distinct from E'Reviewed exact strict payload inside the disposable clone.' and applied_by_handle is not distinct from E'kb-apply' and applied_by_agent_id is not distinct from E'44444444-4444-4444-4444-444444444444'::uuid - and applied_at is not distinct from E'2026-07-15 01:59:04.449051+00'::timestamptz + and applied_at is not distinct from E'2026-07-15 03:30:10.578016+00'::timestamptz ) then raise exception 'proposal rollback: applied ledger does not match apply receipt'; end if; @@ -40,77 +41,97 @@ begin 'review_note', review_note ) into approval_now from kb_stage.kb_proposal_approvals - where proposal_id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid; - if approval_now is distinct from E'{"payload":{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}},"proposal_id":"9b2b5fa4-0e0d-5db0-aa4d-6fd102889946","proposal_type":"approve_claim","review_note":"Reviewed exact strict payload inside the disposable clone.","reviewed_at":"2026-07-15 01:59:03.105846+00","reviewed_by_agent_id":"11111111-1111-4111-8111-111111111111","reviewed_by_db_role":"kb_review","reviewed_by_handle":"m3ta"}'::jsonb then + where proposal_id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid; + if approval_now is distinct from E'{"payload":{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}},"proposal_id":"0b5cfd03-8c1f-509a-b1e1-a05e45164d8d","proposal_type":"approve_claim","review_note":"Reviewed exact strict payload inside the disposable clone.","reviewed_at":"2026-07-15 03:30:07.092864+00","reviewed_by_agent_id":"99999999-9999-9999-9999-999999999999","reviewed_by_db_role":"kb_review","reviewed_by_handle":"m3ta"}'::jsonb then raise exception 'proposal rollback: immutable approval snapshot drifted'; end if; + select count(*) into downstream_dependency_count + from ( + select ce.claim_id + from public.claim_evidence ce + where (ce.claim_id = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) or ce.source_id = any(array[E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid, E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid]::uuid[])) + and not (((ce.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and ce.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and ce.role = E'grounds'::evidence_role) or (ce.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and ce.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and ce.role = E'illustrates'::evidence_role))) + union all + select edge.id + from public.claim_edges edge + where (edge.from_claim = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) or edge.to_claim = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[])) + and edge.id <> all(array[E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid]::uuid[]) + union all + select claim.id + from public.claims claim + where claim.superseded_by = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) + and claim.id <> all(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) + ) external_dependencies; + if downstream_dependency_count <> 0 then + raise exception 'proposal rollback: % downstream dependenc(ies) exist; rollback quarantined', downstream_dependency_count; + end if; if (select count(*) from public.claim_evidence t - where t.id = E'dac3934f-b7ad-5205-8efe-a00163370a54'::uuid and to_jsonb(t) = E'{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"dac3934f-b7ad-5205-8efe-a00163370a54","role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9}'::jsonb) <> 1 then + where ((t.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and t.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and t.role = E'grounds'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_evidence[0] row does not match apply receipt'; end if; if (select count(*) from public.claim_evidence t - where t.id = E'13e580c5-458d-5146-aef3-8c74ffc43b7c'::uuid and to_jsonb(t) = E'{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"13e580c5-458d-5146-aef3-8c74ffc43b7c","role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}'::jsonb) <> 1 then + where ((t.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and t.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and t.role = E'illustrates'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_evidence[1] row does not match apply receipt'; end if; if (select count(*) from public.claim_edges t - where t.id = E'b28d8770-9ac9-5b5f-bfe2-7280d7422a21'::uuid and to_jsonb(t) = E'{"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","id":"b28d8770-9ac9-5b5f-bfe2-7280d7422a21","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}'::jsonb) <> 1 then + where t.id = E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid and to_jsonb(t) = E'{"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","id":"3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_edges[0] row does not match apply receipt'; end if; if (select count(*) from public.reasoning_tools t - where t.id = E'2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0'::uuid and to_jsonb(t) = E'{"agent_id":null,"category":"verification","created_at":"2026-07-15T01:59:04.44165+00:00","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}'::jsonb) <> 1 then + where t.id = E'41b58d96-37f6-526c-b021-58f1dbcfdb6c'::uuid and to_jsonb(t) = E'{"agent_id":null,"category":"verification","created_at":"2026-07-15T03:30:10.562997+00:00","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: reasoning_tools[0] row does not match apply receipt'; end if; if (select count(*) from public.sources t - where t.id = E'ed9da5f1-846e-5298-8689-15027a7ce56d'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + where t.id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then raise exception 'proposal rollback drift: sources[0] row does not match apply receipt'; end if; if (select count(*) from public.sources t - where t.id = E'a86f55dc-5058-585d-b492-a4f1d932670f'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + where t.id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then raise exception 'proposal rollback drift: sources[1] row does not match apply receipt'; end if; if (select count(*) from public.claims t - where t.id = E'71a3331b-fb75-5e18-aa61-b256bc38af36'::uuid and to_jsonb(t) = E'{"confidence":0.85,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept","updated_at":"2026-07-15T01:59:04.44165+00:00"}'::jsonb) <> 1 then + where t.id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and to_jsonb(t) = E'{"confidence":0.85,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept","updated_at":"2026-07-15T03:30:10.562997+00:00"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claims[0] row does not match apply receipt'; end if; if (select count(*) from public.claims t - where t.id = E'38dead14-6b1d-5909-99c4-3c45ad2dd21f'::uuid and to_jsonb(t) = E'{"confidence":0.9,"created_at":"2026-07-15T01:59:04.44165+00:00","created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural","updated_at":"2026-07-15T01:59:04.44165+00:00"}'::jsonb) <> 1 then + where t.id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and to_jsonb(t) = E'{"confidence":0.9,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural","updated_at":"2026-07-15T03:30:10.562997+00:00"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claims[1] row does not match apply receipt'; end if; - delete from public.claim_evidence where id in (E'dac3934f-b7ad-5205-8efe-a00163370a54'::uuid, E'13e580c5-458d-5146-aef3-8c74ffc43b7c'::uuid); + delete from public.claim_evidence target where ((target.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and target.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and target.role = E'grounds'::evidence_role) or (target.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and target.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and target.role = E'illustrates'::evidence_role)); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for claim_evidence: expected 2, got %', affected; end if; - delete from public.claim_edges where id in (E'b28d8770-9ac9-5b5f-bfe2-7280d7422a21'::uuid); + delete from public.claim_edges where id in (E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid); get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback count mismatch for claim_edges: expected 1, got %', affected; end if; - delete from public.reasoning_tools where id in (E'2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0'::uuid); + delete from public.reasoning_tools where id in (E'41b58d96-37f6-526c-b021-58f1dbcfdb6c'::uuid); get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback count mismatch for reasoning_tools: expected 1, got %', affected; end if; - delete from public.sources where id in (E'ed9da5f1-846e-5298-8689-15027a7ce56d'::uuid, E'a86f55dc-5058-585d-b492-a4f1d932670f'::uuid); + delete from public.sources where id in (E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid, E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for sources: expected 2, got %', affected; end if; - delete from public.claims where id in (E'71a3331b-fb75-5e18-aa61-b256bc38af36'::uuid, E'38dead14-6b1d-5909-99c4-3c45ad2dd21f'::uuid); + delete from public.claims where id in (E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for claims: expected 2, got %', affected; end if; update kb_stage.kb_proposals - set status = 'approved', + set status = 'canceled', applied_by_handle = null, applied_by_agent_id = null, applied_at = null, updated_at = now() - where id = E'9b2b5fa4-0e0d-5db0-aa4d-6fd102889946'::uuid + where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid and status = 'applied' - and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"71a3331b-fb75-5e18-aa61-b256bc38af36","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","to_claim":"71a3331b-fb75-5e18-aa61-b256bc38af36","weight":0.75}],"evidence":[{"claim_id":"38dead14-6b1d-5909-99c4-3c45ad2dd21f","created_by":null,"role":"grounds","source_id":"ed9da5f1-846e-5298-8689-15027a7ce56d","weight":0.9},{"claim_id":"71a3331b-fb75-5e18-aa61-b256bc38af36","created_by":null,"role":"illustrates","source_id":"a86f55dc-5058-585d-b492-a4f1d932670f","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"2b8a01ea-125c-5d90-a9b9-39ccb0a1c9e0","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-08c2358330-a","id":"ed9da5f1-846e-5298-8689-15027a7ce56d","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-08c2358330-b","id":"a86f55dc-5058-585d-b492-a4f1d932670f","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb - and applied_at is not distinct from E'2026-07-15 01:59:04.449051+00'::timestamptz; + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and applied_at is not distinct from E'2026-07-15 03:30:10.578016+00'::timestamptz; get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback: expected one applied ledger row, got %', affected; diff --git a/tests/test_proposal_apply_lifecycle.py b/tests/test_proposal_apply_lifecycle.py index 879876e..c0390ee 100644 --- a/tests/test_proposal_apply_lifecycle.py +++ b/tests/test_proposal_apply_lifecycle.py @@ -685,10 +685,20 @@ def test_retained_current_lifecycle_evidence_is_self_consistent(): receipt_sha256 = unsigned.pop("lifecycle_receipt_sha256") assert canary["status"] == "pass" - assert canary["current_tier"] == "T2_runtime" + assert canary["current_tier"] == "T3_live_readonly" + assert canary["runtime_scope"] == "isolated_postgres_container_from_readonly_live_schema" assert canary["applied_rollback_receipt"] == receipt - assert canary["outer_isolation"]["cleanup_readback"]["label_scoped_orphan_count"] == 0 - assert all(delta == 0 for delta in canary["outer_isolation"]["canonical_table_deltas"].values()) + outer = canary["outer_isolation"] + assert outer["source_counts_before"] == outer["source_counts_after"] + assert outer["source_counts_before"]["public.claims"] == 1837 + assert outer["source_counts_before"]["public.claim_evidence"] == 4670 + assert outer["source_counts_before"]["kb_stage.kb_proposals"] == 29 + assert outer["service_stable"] is True + assert outer["cleanup_readback"]["label_scoped_orphan_count"] == 0 + assert all(delta == 0 for delta in outer["canonical_table_deltas"].values()) + assert canary["checks"]["intervening_exact_row_refused_without_adoption"] is True + assert canary["checks"]["rollback_refuses_downstream_dependencies_without_deletion"] is True + assert canary["checks"]["post_rollback_worker_reapply_refused"] is True assert receipt["pass"] is True assert receipt["production_apply_executed"] is False assert receipt_sha256 == lifecycle.sha256_json(unsigned) From c216e0cbb5ad5a5e13c6231c768b587095de448a Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 06:00:12 +0200 Subject: [PATCH 11/11] Refresh proposal lifecycle proof on current main --- .../proposal-apply-clone-rollback-current.sql | 60 +- ...oposal-apply-lifecycle-canary-current.json | 944 +++++++++--------- ...posal-apply-lifecycle-receipt-current.json | 88 +- 3 files changed, 546 insertions(+), 546 deletions(-) diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql index caea6a2..46f7097 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql +++ b/docs/reports/leo-working-state-20260709/proposal-apply-clone-rollback-current.sql @@ -1,7 +1,7 @@ begin; set local standard_conforming_strings = on; set local lock_timeout = '5s'; -select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d', 0)); +select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b', 0)); do $rollback$ declare affected integer; @@ -9,24 +9,24 @@ declare downstream_dependency_count integer; begin perform 1 from kb_stage.kb_proposals - where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid + where id = E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b'::uuid for update; if not found then raise exception 'proposal rollback: proposal row missing'; end if; if not exists ( select 1 from kb_stage.kb_proposals - where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid + where id = E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b'::uuid and proposal_type = 'approve_claim' and status = 'applied' - and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"b4d0a944-8f11-5516-80ca-bc680f0059ad","to_claim":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","weight":0.75}],"evidence":[{"claim_id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","created_by":null,"role":"grounds","source_id":"3953271f-7df5-5674-99b0-980b1b3534e6","weight":0.9},{"claim_id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","created_by":null,"role":"illustrates","source_id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"a32a7252-d39f-5ee9-873a-a82b56a6bb08","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-e315c2518c-a","id":"3953271f-7df5-5674-99b0-980b1b3534e6","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-e315c2518c-b","id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb and reviewed_by_handle is not distinct from E'm3ta' and reviewed_by_agent_id is not distinct from E'99999999-9999-9999-9999-999999999999'::uuid - and reviewed_at is not distinct from E'2026-07-15 03:30:07.092864+00'::timestamptz + and reviewed_at is not distinct from E'2026-07-15 03:59:09.091704+00'::timestamptz and review_note is not distinct from E'Reviewed exact strict payload inside the disposable clone.' and applied_by_handle is not distinct from E'kb-apply' and applied_by_agent_id is not distinct from E'44444444-4444-4444-4444-444444444444'::uuid - and applied_at is not distinct from E'2026-07-15 03:30:10.578016+00'::timestamptz + and applied_at is not distinct from E'2026-07-15 03:59:12.452878+00'::timestamptz ) then raise exception 'proposal rollback: applied ledger does not match apply receipt'; end if; @@ -41,83 +41,83 @@ begin 'review_note', review_note ) into approval_now from kb_stage.kb_proposal_approvals - where proposal_id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid; - if approval_now is distinct from E'{"payload":{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}},"proposal_id":"0b5cfd03-8c1f-509a-b1e1-a05e45164d8d","proposal_type":"approve_claim","review_note":"Reviewed exact strict payload inside the disposable clone.","reviewed_at":"2026-07-15 03:30:07.092864+00","reviewed_by_agent_id":"99999999-9999-9999-9999-999999999999","reviewed_by_db_role":"kb_review","reviewed_by_handle":"m3ta"}'::jsonb then + where proposal_id = E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b'::uuid; + if approval_now is distinct from E'{"payload":{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"b4d0a944-8f11-5516-80ca-bc680f0059ad","to_claim":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","weight":0.75}],"evidence":[{"claim_id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","created_by":null,"role":"grounds","source_id":"3953271f-7df5-5674-99b0-980b1b3534e6","weight":0.9},{"claim_id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","created_by":null,"role":"illustrates","source_id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"a32a7252-d39f-5ee9-873a-a82b56a6bb08","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-e315c2518c-a","id":"3953271f-7df5-5674-99b0-980b1b3534e6","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-e315c2518c-b","id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","source_type":"observation","storage_path":null,"url":null}]}},"proposal_id":"edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b","proposal_type":"approve_claim","review_note":"Reviewed exact strict payload inside the disposable clone.","reviewed_at":"2026-07-15 03:59:09.091704+00","reviewed_by_agent_id":"99999999-9999-9999-9999-999999999999","reviewed_by_db_role":"kb_review","reviewed_by_handle":"m3ta"}'::jsonb then raise exception 'proposal rollback: immutable approval snapshot drifted'; end if; select count(*) into downstream_dependency_count from ( select ce.claim_id from public.claim_evidence ce - where (ce.claim_id = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) or ce.source_id = any(array[E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid, E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid]::uuid[])) - and not (((ce.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and ce.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and ce.role = E'grounds'::evidence_role) or (ce.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and ce.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and ce.role = E'illustrates'::evidence_role))) + where (ce.claim_id = any(array[E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid]::uuid[]) or ce.source_id = any(array[E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid, E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid]::uuid[])) + and not (((ce.claim_id = E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid and ce.source_id = E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid and ce.role = E'illustrates'::evidence_role) or (ce.claim_id = E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid and ce.source_id = E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid and ce.role = E'grounds'::evidence_role))) union all select edge.id from public.claim_edges edge - where (edge.from_claim = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) or edge.to_claim = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[])) - and edge.id <> all(array[E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid]::uuid[]) + where (edge.from_claim = any(array[E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid]::uuid[]) or edge.to_claim = any(array[E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid]::uuid[])) + and edge.id <> all(array[E'cd799806-18e8-5e8c-959c-5f9c267654a7'::uuid]::uuid[]) union all select claim.id from public.claims claim - where claim.superseded_by = any(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) - and claim.id <> all(array[E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid]::uuid[]) + where claim.superseded_by = any(array[E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid]::uuid[]) + and claim.id <> all(array[E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid]::uuid[]) ) external_dependencies; if downstream_dependency_count <> 0 then raise exception 'proposal rollback: % downstream dependenc(ies) exist; rollback quarantined', downstream_dependency_count; end if; if (select count(*) from public.claim_evidence t - where ((t.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and t.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and t.role = E'grounds'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9}'::jsonb) <> 1 then + where ((t.claim_id = E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid and t.source_id = E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid and t.role = E'illustrates'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"role":"illustrates","source_id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","weight":0.8}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_evidence[0] row does not match apply receipt'; end if; if (select count(*) from public.claim_evidence t - where ((t.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and t.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and t.role = E'illustrates'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}'::jsonb) <> 1 then + where ((t.claim_id = E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid and t.source_id = E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid and t.role = E'grounds'::evidence_role)) and to_jsonb(t) = E'{"claim_id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"role":"grounds","source_id":"3953271f-7df5-5674-99b0-980b1b3534e6","weight":0.9}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_evidence[1] row does not match apply receipt'; end if; if (select count(*) from public.claim_edges t - where t.id = E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid and to_jsonb(t) = E'{"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","id":"3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}'::jsonb) <> 1 then + where t.id = E'cd799806-18e8-5e8c-959c-5f9c267654a7'::uuid and to_jsonb(t) = E'{"created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"edge_type":"supports","from_claim":"b4d0a944-8f11-5516-80ca-bc680f0059ad","id":"cd799806-18e8-5e8c-959c-5f9c267654a7","to_claim":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","weight":0.75}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claim_edges[0] row does not match apply receipt'; end if; if (select count(*) from public.reasoning_tools t - where t.id = E'41b58d96-37f6-526c-b021-58f1dbcfdb6c'::uuid and to_jsonb(t) = E'{"agent_id":null,"category":"verification","created_at":"2026-07-15T03:30:10.562997+00:00","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}'::jsonb) <> 1 then + where t.id = E'a32a7252-d39f-5ee9-873a-a82b56a6bb08'::uuid and to_jsonb(t) = E'{"agent_id":null,"category":"verification","created_at":"2026-07-15T03:59:12.43629+00:00","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"a32a7252-d39f-5ee9-873a-a82b56a6bb08","name":"Canonical row proof canary"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: reasoning_tools[0] row does not match apply receipt'; end if; if (select count(*) from public.sources t - where t.id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + where t.id = E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-e315c2518c-a","id":"3953271f-7df5-5674-99b0-980b1b3534e6","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then raise exception 'proposal rollback drift: sources[0] row does not match apply receipt'; end if; if (select count(*) from public.sources t - where t.id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then + where t.id = E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid and to_jsonb(t) = E'{"captured_at":null,"created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-e315c2518c-b","id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","source_type":"observation","storage_path":null,"url":null}'::jsonb) <> 1 then raise exception 'proposal rollback drift: sources[1] row does not match apply receipt'; end if; if (select count(*) from public.claims t - where t.id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and to_jsonb(t) = E'{"confidence":0.85,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept","updated_at":"2026-07-15T03:30:10.562997+00:00"}'::jsonb) <> 1 then + where t.id = E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid and to_jsonb(t) = E'{"confidence":0.85,"created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept","updated_at":"2026-07-15T03:59:12.43629+00:00"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claims[0] row does not match apply receipt'; end if; if (select count(*) from public.claims t - where t.id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and to_jsonb(t) = E'{"confidence":0.9,"created_at":"2026-07-15T03:30:10.562997+00:00","created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural","updated_at":"2026-07-15T03:30:10.562997+00:00"}'::jsonb) <> 1 then + where t.id = E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid and to_jsonb(t) = E'{"confidence":0.9,"created_at":"2026-07-15T03:59:12.43629+00:00","created_by":null,"id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural","updated_at":"2026-07-15T03:59:12.43629+00:00"}'::jsonb) <> 1 then raise exception 'proposal rollback drift: claims[1] row does not match apply receipt'; end if; - delete from public.claim_evidence target where ((target.claim_id = E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid and target.source_id = E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid and target.role = E'grounds'::evidence_role) or (target.claim_id = E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid and target.source_id = E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid and target.role = E'illustrates'::evidence_role)); + delete from public.claim_evidence target where ((target.claim_id = E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid and target.source_id = E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid and target.role = E'illustrates'::evidence_role) or (target.claim_id = E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid and target.source_id = E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid and target.role = E'grounds'::evidence_role)); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for claim_evidence: expected 2, got %', affected; end if; - delete from public.claim_edges where id in (E'3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8'::uuid); + delete from public.claim_edges where id in (E'cd799806-18e8-5e8c-959c-5f9c267654a7'::uuid); get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback count mismatch for claim_edges: expected 1, got %', affected; end if; - delete from public.reasoning_tools where id in (E'41b58d96-37f6-526c-b021-58f1dbcfdb6c'::uuid); + delete from public.reasoning_tools where id in (E'a32a7252-d39f-5ee9-873a-a82b56a6bb08'::uuid); get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback count mismatch for reasoning_tools: expected 1, got %', affected; end if; - delete from public.sources where id in (E'bf697d93-8b77-5e2b-a6c0-0825e5ba76fd'::uuid, E'7a2198b6-16b2-52c6-a641-7ad59826e5bf'::uuid); + delete from public.sources where id in (E'3953271f-7df5-5674-99b0-980b1b3534e6'::uuid, E'3d31345d-a4f7-52a7-af4a-0034f99a8123'::uuid); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for sources: expected 2, got %', affected; end if; - delete from public.claims where id in (E'4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95'::uuid, E'32cc5b57-0d89-58aa-9cc1-f9e0c63947fb'::uuid); + delete from public.claims where id in (E'a9dd972a-b867-56f7-b3c9-3913dd9a0abe'::uuid, E'b4d0a944-8f11-5516-80ca-bc680f0059ad'::uuid); get diagnostics affected = row_count; if affected <> 2 then raise exception 'proposal rollback count mismatch for claims: expected 2, got %', affected; @@ -128,10 +128,10 @@ begin applied_by_agent_id = null, applied_at = null, updated_at = now() - where id = E'0b5cfd03-8c1f-509a-b1e1-a05e45164d8d'::uuid + where id = E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b'::uuid and status = 'applied' - and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","to_claim":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","weight":0.75}],"evidence":[{"claim_id":"32cc5b57-0d89-58aa-9cc1-f9e0c63947fb","created_by":null,"role":"grounds","source_id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","weight":0.9},{"claim_id":"4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95","created_by":null,"role":"illustrates","source_id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"41b58d96-37f6-526c-b021-58f1dbcfdb6c","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-4d6107db5d-a","id":"bf697d93-8b77-5e2b-a6c0-0825e5ba76fd","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-4d6107db5d-b","id":"7a2198b6-16b2-52c6-a641-7ad59826e5bf","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb - and applied_at is not distinct from E'2026-07-15 03:30:10.578016+00'::timestamptz; + and payload = E'{"apply_payload":{"agent_id":null,"claims":[{"confidence":0.9,"created_by":null,"id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","status":"open","superseded_by":null,"tags":["working-leo","clone-canary"],"text":"An approved strict proposal can create exact canonical rows atomically.","type":"structural"},{"confidence":0.85,"created_by":null,"id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","status":"open","superseded_by":null,"tags":["working-leo","row-proof"],"text":"Row-level proof is the authority for canonical KB state.","type":"concept"}],"contract_version":2,"edges":[{"created_by":null,"edge_type":"supports","from_claim":"b4d0a944-8f11-5516-80ca-bc680f0059ad","to_claim":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","weight":0.75}],"evidence":[{"claim_id":"b4d0a944-8f11-5516-80ca-bc680f0059ad","created_by":null,"role":"grounds","source_id":"3953271f-7df5-5674-99b0-980b1b3534e6","weight":0.9},{"claim_id":"a9dd972a-b867-56f7-b3c9-3913dd9a0abe","created_by":null,"role":"illustrates","source_id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","weight":0.8}],"reasoning_tools":[{"agent_id":null,"category":"verification","description":"Verify approved proposal to canonical graph lifecycle in a disposable clone.","id":"a32a7252-d39f-5ee9-873a-a82b56a6bb08","name":"Canonical row proof canary"}],"sources":[{"created_by":null,"excerpt":"Disposable clone lifecycle canary source A.","hash":"approve-claim-canary-e315c2518c-a","id":"3953271f-7df5-5674-99b0-980b1b3534e6","source_type":"observation","storage_path":null,"url":null},{"created_by":null,"excerpt":"Disposable clone lifecycle canary source B.","hash":"approve-claim-canary-e315c2518c-b","id":"3d31345d-a4f7-52a7-af4a-0034f99a8123","source_type":"observation","storage_path":null,"url":null}]}}'::jsonb + and applied_at is not distinct from E'2026-07-15 03:59:12.452878+00'::timestamptz; get diagnostics affected = row_count; if affected <> 1 then raise exception 'proposal rollback: expected one applied ledger row, got %', affected; diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json index fbcd79b..3259037 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-canary-current.json @@ -2,48 +2,48 @@ "applied_rollback_receipt": { "applied_row_keys": { "claim_edges": [ - "3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8" + "cd799806-18e8-5e8c-959c-5f9c267654a7" ], "claim_evidence": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb|bf697d93-8b77-5e2b-a6c0-0825e5ba76fd|grounds", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95|7a2198b6-16b2-52c6-a641-7ad59826e5bf|illustrates" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe|3d31345d-a4f7-52a7-af4a-0034f99a8123|illustrates", + "b4d0a944-8f11-5516-80ca-bc680f0059ad|3953271f-7df5-5674-99b0-980b1b3534e6|grounds" ], "claims": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "b4d0a944-8f11-5516-80ca-bc680f0059ad" ], "reasoning_tools": [ - "41b58d96-37f6-526c-b021-58f1dbcfdb6c" + "a32a7252-d39f-5ee9-873a-a82b56a6bb08" ], "sources": [ - "7a2198b6-16b2-52c6-a641-7ad59826e5bf", - "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "3953271f-7df5-5674-99b0-980b1b3534e6", + "3d31345d-a4f7-52a7-af4a-0034f99a8123" ] }, "applied_row_sha256": { "claim_edges": [ - "65e5186be950498bd8ff8ef2043804181ec5bef02c9c1bb36a965dd9410e8b5b" + "aae7ed87c66cf58136f2b0027ae1cddc9092cd64bfc8e617cd7746b2306274c5" ], "claim_evidence": [ - "9164b7c63641e5cbf5422f50299490053d547ba6ce1108c970b1ebfb89dc8e25", - "c098ddaadc9b7d14e3f0d48f844b88750fc7529813a20762240557abcdb1391b" + "388f3363173efda00f0688fab77fe0ce2baf62035220b843be1adea1f1c70f7f", + "55838cb722f7158cbdbdc3b79212e764f9fa6014771985aec3c1c7856967db07" ], "claims": [ - "e8cb8a99124bcc1f98fb0316132155c4db6d9dd12879f40a0ece82cc97e54085", - "4ffd395e8534ab7c9d565147667c8e207eacf70dbfcae6e8959e9b9203e4429f" + "75fe4543c9c3194612b1cf98b074ff7e361da17c9bcd59f9b6f085c2c0861277", + "5914923936817eff6d7e5c824c94c18ae6392b7a6e80c87ace2e547865b173eb" ], "reasoning_tools": [ - "355dee4df27c89809daa214fde69fdfb9f15fc2a29f3985582fe69d7bd797598" + "990dacb7b77cec117d9ee4a7630625a8782d06dfd549340b3269b8332c170576" ], "sources": [ - "cea718e74eb3d2c2672491e2e6fc523c4c4a4ae3060babbb24652f8004a2c7fd", - "d31a88fff760ed8d5985a2557f20524a372a0ea94893b7ad1aa1d24e6fe58050" + "585edbec2f98ec127041cdd662506a1494ea402f7e25ac0082dbda98197bf130", + "a8d2eead7cb3e563869978570173e2af753dfe131d4b7cfcf6dd419ffbb427e5" ] }, - "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", - "apply_receipt_sha256": "456247af33d4222f76c47c0a4e9228135d7a46c2c04c0f9c928b6bae5f30cde8", - "apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", - "approval_snapshot_sha256": "ae28ff3694a19603b562f3233772ea68371702f22732026c75c33af944428dab", + "apply_payload_sha256": "e033bd4e742dfa0dad7d26e2f2b1f18eb71996541cdbc575bb2d4504c045e36f", + "apply_receipt_sha256": "ac99a2a315cc8e6e214e0f2f69d1a23413da9cfd8629c202b61a678ffda6d7ca", + "apply_sql_sha256": "b52cd47182dc0f542a394147201bb3a125518f8a4bc1a7fc44f2b0caa39c4a1b", + "approval_snapshot_sha256": "1f9d0a58ad236908da931c7489fe14ee855d0f13c4d72eb5b218370e116e2096", "artifact": "proposal_apply_lifecycle_receipt", "checks": { "apply_receipt_replay_ready": true, @@ -59,11 +59,11 @@ "unrelated_rows_unchanged": true }, "current_tier": "T2_runtime", - "fresh_owned_apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", - "fresh_preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", - "fresh_preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", - "generated_at_utc": "2026-07-15T03:30:13.458916+00:00", - "lifecycle_receipt_sha256": "6a94df2a04b9b71f931d23d5e5fba3aa295395f9ef636f490bcffdd43d1af697", + "fresh_owned_apply_sql_sha256": "b52cd47182dc0f542a394147201bb3a125518f8a4bc1a7fc44f2b0caa39c4a1b", + "fresh_preflight_artifact_sha256": "2312c91d82ee378d4a53136b8e307900c97d0611d9f12098e799cb6de5d30077", + "fresh_preflight_sha256": "90facb2ca62feb1d3c7a242e84427ab402cf57148eaba40ec700f3cc4896d20f", + "generated_at_utc": "2026-07-15T03:59:15.412413+00:00", + "lifecycle_receipt_sha256": "4254f363b0c6115ecf07856c6e6a9879b43840e688aa73211cb9eff893b36c06", "pass": true, "production_apply_authorization_present": false, "production_apply_executed": false, @@ -71,7 +71,7 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -79,7 +79,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -92,7 +92,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -108,24 +108,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -134,7 +134,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -142,8 +142,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -151,8 +151,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -162,12 +162,12 @@ }, "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "approved" }, - "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", + "proposal_payload_sha256": "cf2676db5a64142d07a7b46f02f1ba38bfa8cca69d03484bbcaa5eeb7002af71", "required_tier": "T2_runtime", "rollback": { "counts_after_rollback": { @@ -197,15 +197,15 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "canceled" }, - "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "rollback_sql_sha256": "50758dab3f998289a879cedb4a3f4535814e70c7f4dde417812092b9fe194901", "schema": "livingip.proposalApplyRollback.v2", "target_rows_after": { "claim_edges": [], @@ -220,11 +220,11 @@ }, "apply_transition": { "applied_readback": { - "applied_at": "2026-07-15 03:30:10.578016+00", + "applied_at": "2026-07-15 03:59:12.452878+00", "applied_by_agent_id": "44444444-4444-4444-4444-444444444444", "applied_by_handle": "kb-apply", "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -232,7 +232,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -245,7 +245,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -261,24 +261,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -287,7 +287,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -295,8 +295,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -304,8 +304,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -316,7 +316,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -327,7 +327,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -335,7 +335,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -348,7 +348,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -364,24 +364,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -390,7 +390,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -398,8 +398,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -407,8 +407,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -419,7 +419,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -435,7 +435,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -448,7 +448,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -464,24 +464,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -490,7 +490,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -498,8 +498,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -507,8 +507,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -516,10 +516,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -609,19 +609,19 @@ "public.sources": 1 }, "clone_created": true, - "clone_database": "teleo_approve_claim_isolated_4d6107db5d", + "clone_database": "teleo_approve_claim_isolated_e315c2518c", "clone_dropped": true, "clone_prerequisite_sanitization": { - "clone_sql_sha256": "a02a03a704954058745d8cee4d25597bb8eaeee2ae211d4f9be4fe055f3d98ec", + "clone_sql_sha256": "1a2120c20d24cf261fcde7e76fee7981f311e16a63328c7117c8eaf2355a73c4", "cluster_role_ddl_removed": true, "removed_alter_role_statements": 3, "removed_create_role_statements": 2, - "source_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa" + "source_sha256": "d51c4b3462aac09baf68b3ca1b2255275b91a5a976f3f45ace5ed0870511e36a" }, "conflict_apply": { "returncode": 1, "source_hash_collision_refusal": true, - "stderr": "psql failed (3)\nSTDOUT:\n\n\nSTDERR:\nERROR: approve_claim: source hash collision for source 4d393879-78d4-59e1-a41a-498c5fa8e1cb\nCONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE" + "stderr": "psql failed (3)\nSTDOUT:\n\n\nSTDERR:\nERROR: approve_claim: source hash collision for source 7c01ac05-81f3-5567-b830-7e600a1731ae\nCONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE" }, "conflict_readback": { "canonical_rows": { @@ -640,7 +640,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "id": "eefe4100-92ee-5881-8b86-34e18e781a8a", "status": "open", "superseded_by": null, "tags": [ @@ -658,8 +658,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", - "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "hash": "approve-claim-permission-probe-03bc88e3-e708-504f-96af-61d764bc29f7", + "id": "7c01ac05-81f3-5567-b830-7e600a1731ae", "source_type": "observation", "storage_path": null, "url": null @@ -667,10 +667,10 @@ ] } }, - "proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "proposal_id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_at": "2026-07-15 03:59:15.971674+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -681,7 +681,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", "payload": { "apply_payload": { "agent_id": null, @@ -689,7 +689,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "id": "eefe4100-92ee-5881-8b86-34e18e781a8a", "status": "open", "superseded_by": null, "tags": [ @@ -707,8 +707,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", - "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "hash": "approve-claim-permission-probe-03bc88e3-e708-504f-96af-61d764bc29f7", + "id": "7c01ac05-81f3-5567-b830-7e600a1731ae", "source_type": "observation", "storage_path": null, "url": null @@ -719,7 +719,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_at": "2026-07-15 03:59:15.971674+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-conflict-canary", @@ -733,7 +733,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", "payload": { "apply_payload": { "agent_id": null, @@ -741,7 +741,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "id": "eefe4100-92ee-5881-8b86-34e18e781a8a", "status": "open", "superseded_by": null, "tags": [ @@ -759,8 +759,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", - "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "hash": "approve-claim-permission-probe-03bc88e3-e708-504f-96af-61d764bc29f7", + "id": "7c01ac05-81f3-5567-b830-7e600a1731ae", "source_type": "observation", "storage_path": null, "url": null @@ -771,7 +771,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_at": "2026-07-15 03:59:15.971674+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-conflict-canary", @@ -787,7 +787,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "id": "eefe4100-92ee-5881-8b86-34e18e781a8a", "status": "open", "superseded_by": null, "tags": [ @@ -805,8 +805,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", - "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "hash": "approve-claim-permission-probe-03bc88e3-e708-504f-96af-61d764bc29f7", + "id": "7c01ac05-81f3-5567-b830-7e600a1731ae", "source_type": "observation", "storage_path": null, "url": null @@ -814,10 +814,10 @@ ] } }, - "proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "proposal_id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:14.021982+00", + "reviewed_at": "2026-07-15 03:59:15.971674+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -828,7 +828,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", + "id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", "payload": { "apply_payload": { "agent_id": null, @@ -836,7 +836,7 @@ { "confidence": 0.5, "created_by": null, - "id": "3025315d-fca3-55f7-99f3-95d5588fddb4", + "id": "eefe4100-92ee-5881-8b86-34e18e781a8a", "status": "open", "superseded_by": null, "tags": [ @@ -854,8 +854,8 @@ { "created_by": null, "excerpt": "Conflicting source id.", - "hash": "approve-claim-permission-probe-1438f592-0378-594a-9b9a-87dfb2a30cc0", - "id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", + "hash": "approve-claim-permission-probe-03bc88e3-e708-504f-96af-61d764bc29f7", + "id": "7c01ac05-81f3-5567-b830-7e600a1731ae", "source_type": "observation", "storage_path": null, "url": null @@ -875,7 +875,7 @@ "review_apply": { "returncode": 0, "stderr": "", - "stdout": "{\"id\": \"3e80ebda-c58d-5d4a-aaba-c2140371c1f4\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:30:14.021982+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + "stdout": "{\"id\": \"a8d82e27-665b-5200-8ce4-6644e4e4f6d3\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:59:15.971674+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" } }, "current_tier": "T3_live_readonly", @@ -925,31 +925,31 @@ "first_apply": { "result": { "applied": true, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", - "replay_material_sha256": "3583ba36b109a0269c4c495fba325fe419a4776238959cadd49f67b4831520c6", + "replay_material_sha256": "b6be0bf8a61d73744d3cf88b9fa3afadc0fadcecc2abf1dfefd98863a8072376", "replay_ready": true }, "returncode": 0, "stderr": "" }, "fixture_ids": { - "conflict_claim_id": "3025315d-fca3-55f7-99f3-95d5588fddb4", - "conflict_proposal_id": "3e80ebda-c58d-5d4a-aaba-c2140371c1f4", - "conflict_source_id": "4d393879-78d4-59e1-a41a-498c5fa8e1cb", - "permission_claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", - "permission_source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d" + "conflict_claim_id": "eefe4100-92ee-5881-8b86-34e18e781a8a", + "conflict_proposal_id": "a8d82e27-665b-5200-8ce4-6644e4e4f6d3", + "conflict_source_id": "7c01ac05-81f3-5567-b830-7e600a1731ae", + "permission_claim_id": "98994dee-d338-5e5d-b9d7-7538f07dc3a3", + "permission_source_id": "03bc88e3-e708-504f-96af-61d764bc29f7", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b" }, "fresh_owned_preflight": { - "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", + "apply_payload_sha256": "e033bd4e742dfa0dad7d26e2f2b1f18eb71996541cdbc575bb2d4504c045e36f", "artifact": "proposal_apply_fresh_preflight", - "captured_at_utc": "2026-07-15T03:30:09.318963+00:00", + "captured_at_utc": "2026-07-15T03:59:11.231179+00:00", "fresh_owned_targets": true, - "preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", - "preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", - "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", + "preflight_artifact_sha256": "2312c91d82ee378d4a53136b8e307900c97d0611d9f12098e799cb6de5d30077", + "preflight_sha256": "90facb2ca62feb1d3c7a242e84427ab402cf57148eaba40ec700f3cc4896d20f", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", + "proposal_payload_sha256": "cf2676db5a64142d07a7b46f02f1ba38bfa8cca69d03484bbcaa5eeb7002af71", "proposal_type": "approve_claim", "schema": "livingip.proposalApplyFreshPreflight.v1", "target_rows_before": { @@ -961,11 +961,11 @@ } }, "gateway_process_observable": true, - "generated_at_utc": "2026-07-15T03:30:04.429291+00:00", + "generated_at_utc": "2026-07-15T03:59:06.550402+00:00", "idempotent_replay": { "already_applied_refusal": true, "returncode": 1, - "stderr": "proposal 0b5cfd03-8c1f-509a-b1e1-a05e45164d8d is already applied (idempotent no-op)" + "stderr": "proposal edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b is already applied (idempotent no-op)" }, "intervening_exact_row_refusal": { "intervening_row_preserved": true, @@ -975,10 +975,10 @@ }, "kb_apply_claim_evidence_update_probe": { "after": { - "claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", + "claim_id": "98994dee-d338-5e5d-b9d7-7538f07dc3a3", "created_by": null, "role": "grounds", - "source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", + "source_id": "03bc88e3-e708-504f-96af-61d764bc29f7", "weight": 0.42 }, "attempt": { @@ -988,10 +988,10 @@ "stdout": "" }, "before": { - "claim_id": "3a5dc7cb-bd20-56a0-8d56-a68acc01c429", + "claim_id": "98994dee-d338-5e5d-b9d7-7538f07dc3a3", "created_by": null, "role": "grounds", - "source_id": "1438f592-0378-594a-9b9a-87dfb2a30cc0", + "source_id": "03bc88e3-e708-504f-96af-61d764bc29f7", "weight": 0.42 }, "exact_row_unchanged": true @@ -1002,7 +1002,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -1010,7 +1010,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1023,7 +1023,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1039,24 +1039,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1065,7 +1065,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1073,8 +1073,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1082,8 +1082,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1094,7 +1094,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -1111,7 +1111,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -1119,7 +1119,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1132,7 +1132,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1148,24 +1148,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1174,7 +1174,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1182,8 +1182,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1191,8 +1191,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1203,7 +1203,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -1218,7 +1218,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1231,7 +1231,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1247,24 +1247,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1273,7 +1273,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1281,8 +1281,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1290,8 +1290,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1299,10 +1299,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -1315,7 +1315,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1328,7 +1328,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1344,24 +1344,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1370,7 +1370,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1378,8 +1378,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1387,8 +1387,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1396,10 +1396,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -1426,7 +1426,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -1434,7 +1434,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1447,7 +1447,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1463,24 +1463,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1489,7 +1489,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1497,8 +1497,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1506,8 +1506,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1518,14 +1518,14 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", "status": "approved" }, "build_returncode": 0, - "built_sql_sha256": "ca785dbaf04dc37ff25b563a42ae2f645780562df3aba1a41b1711b9b83d694f", + "built_sql_sha256": "e95a0ce47019fb4ee62ab0fea48b304f5c21bdec4620296fb5a11772e1c3c44a", "built_sql_uses_assert_approved_proposal": true, "built_sql_uses_finish_approved_proposal": true, "canonical_rows_unchanged": true, @@ -1537,7 +1537,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1550,7 +1550,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1566,24 +1566,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1592,7 +1592,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1600,8 +1600,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1609,8 +1609,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1618,10 +1618,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -1634,7 +1634,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1647,7 +1647,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1663,24 +1663,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1689,7 +1689,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1697,8 +1697,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1706,8 +1706,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1715,10 +1715,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -1731,7 +1731,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1744,7 +1744,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1760,24 +1760,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1786,7 +1786,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1794,8 +1794,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1803,8 +1803,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1812,10 +1812,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -1826,7 +1826,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -1834,7 +1834,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1847,7 +1847,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1863,24 +1863,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1889,7 +1889,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -1897,8 +1897,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -1906,8 +1906,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -1919,7 +1919,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -1930,7 +1930,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -1938,7 +1938,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -1951,7 +1951,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -1967,24 +1967,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -1993,7 +1993,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2001,8 +2001,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2010,8 +2010,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2023,7 +2023,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -2037,7 +2037,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -2050,7 +2050,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2066,24 +2066,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -2092,7 +2092,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2100,8 +2100,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2109,8 +2109,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2118,10 +2118,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -2131,7 +2131,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -2139,7 +2139,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -2152,7 +2152,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2168,24 +2168,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -2194,7 +2194,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2202,8 +2202,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2211,8 +2211,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2223,7 +2223,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -2239,7 +2239,7 @@ "stale_apply_refused": true, "stale_execute": { "returncode": 3, - "stderr": "ERROR: assert_approved_proposal: proposal 0b5cfd03-8c1f-509a-b1e1-a05e45164d8d is not the exact immutable approved snapshot\nCONTEXT: PL/pgSQL function kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamp with time zone,text) line 22 at RAISE", + "stderr": "ERROR: assert_approved_proposal: proposal edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b is not the exact immutable approved snapshot\nCONTEXT: PL/pgSQL function kb_stage.assert_approved_proposal(uuid,text,jsonb,text,uuid,timestamp with time zone,text) line 22 at RAISE", "stdout": "" } }, @@ -2267,7 +2267,7 @@ }, "container_isolation": { "canary_label": "proposal-apply-lifecycle", - "instance_label": "working-leo-approve-claim-1281-2032206", + "instance_label": "working-leo-approve-claim-539-2219717", "lifecycle_labeled": true, "network_disabled": true, "network_mode": "none", @@ -2332,45 +2332,32 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "claim_evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "created_by": null, - "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", - "weight": 0.9 - }, - { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 + }, + { + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "created_by": null, + "role": "grounds", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", + "weight": 0.9 } ], "claims": [ - { - "confidence": 0.9, - "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "status": "open", - "superseded_by": null, - "tags": [ - "working-leo", - "clone-canary" - ], - "text": "An approved strict proposal can create exact canonical rows atomically.", - "type": "structural" - }, { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2379,6 +2366,19 @@ ], "text": "Row-level proof is the authority for canonical KB state.", "type": "concept" + }, + { + "confidence": 0.9, + "created_by": null, + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" } ], "reasoning_tools": [ @@ -2386,25 +2386,25 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], "sources": [ { "created_by": null, - "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null }, { "created_by": null, - "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2419,7 +2419,7 @@ "public.reasoning_tools": 1, "public.sources": 2 }, - "payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02" + "payload_sha256": "e033bd4e742dfa0dad7d26e2f2b1f18eb71996541cdbc575bb2d4504c045e36f" }, "post_rollback_worker_apply": { "proposal_status": "canceled", @@ -2445,7 +2445,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -2453,7 +2453,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -2466,7 +2466,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2482,24 +2482,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -2508,7 +2508,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2516,8 +2516,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2525,8 +2525,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2537,7 +2537,7 @@ "proposal_type": "approve_claim", "rationale": "Exercise strict canonical bundle review and apply lifecycle.", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "source_ref": "working-leo:approve-claim-clone-canary", @@ -2553,7 +2553,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -2566,7 +2566,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2582,24 +2582,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -2608,7 +2608,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2616,8 +2616,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2625,8 +2625,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2634,10 +2634,10 @@ ] } }, - "proposal_id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "proposal_id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_db_role": "kb_review", "reviewed_by_handle": "m3ta" @@ -2648,7 +2648,7 @@ "applied_by_agent_id": null, "applied_by_handle": null, "channel": "clone_canary", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -2656,7 +2656,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -2669,7 +2669,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2685,24 +2685,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -2711,7 +2711,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -2719,8 +2719,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -2728,8 +2728,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2749,7 +2749,7 @@ "review_apply": { "returncode": 0, "stderr": "", - "stdout": "{\"id\": \"0b5cfd03-8c1f-509a-b1e1-a05e45164d8d\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:30:07.092864+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" + "stdout": "{\"id\": \"edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b\", \"proposal_type\": \"approve_claim\", \"review_note\": \"Reviewed exact strict payload inside the disposable clone.\", \"reviewed_at\": \"2026-07-15 03:59:09.091704+00\", \"reviewed_by_agent_id\": \"99999999-9999-9999-9999-999999999999\", \"reviewed_by_db_role\": \"kb_review\", \"reviewed_by_handle\": \"m3ta\", \"status\": \"approved\"}" }, "review_dry_run": { "returncode": 0, @@ -2773,7 +2773,7 @@ }, "rollback_plan": { "execution_authority": "disposable_clone_admin_only", - "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "rollback_sql_sha256": "50758dab3f998289a879cedb4a3f4535814e70c7f4dde417812092b9fe194901", "schema": "livingip.proposalApplyRollback.v2" }, "rollback_replay": { @@ -2787,45 +2787,32 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "claim_evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "created_by": null, - "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", - "weight": 0.9 - }, - { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 + }, + { + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "created_by": null, + "role": "grounds", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", + "weight": 0.9 } ], "claims": [ - { - "confidence": 0.9, - "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "status": "open", - "superseded_by": null, - "tags": [ - "working-leo", - "clone-canary" - ], - "text": "An approved strict proposal can create exact canonical rows atomically.", - "type": "structural" - }, { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -2834,6 +2821,19 @@ ], "text": "Row-level proof is the authority for canonical KB state.", "type": "concept" + }, + { + "confidence": 0.9, + "created_by": null, + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "status": "open", + "superseded_by": null, + "tags": [ + "working-leo", + "clone-canary" + ], + "text": "An approved strict proposal can create exact canonical rows atomically.", + "type": "structural" } ], "reasoning_tools": [ @@ -2841,25 +2841,25 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], "sources": [ { "created_by": null, - "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "excerpt": "Disposable clone lifecycle canary source A.", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null }, { "created_by": null, - "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "excerpt": "Disposable clone lifecycle canary source B.", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -2961,8 +2961,8 @@ }, { "repo_relative_path": "scripts/kb_apply_prereqs.sql", - "sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", - "size_bytes": 42602 + "sha256": "d51c4b3462aac09baf68b3ca1b2255275b91a5a976f3f45ace5ed0870511e36a", + "size_bytes": 42660 }, { "repo_relative_path": "scripts/proposal_apply_lifecycle.py", @@ -3005,11 +3005,11 @@ "size_bytes": 10684 }, { - "actual_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", - "expected_sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", + "actual_sha256": "d51c4b3462aac09baf68b3ca1b2255275b91a5a976f3f45ace5ed0870511e36a", + "expected_sha256": "d51c4b3462aac09baf68b3ca1b2255275b91a5a976f3f45ace5ed0870511e36a", "matches": true, "repo_relative_path": "scripts/kb_apply_prereqs.sql", - "size_bytes": 42602 + "size_bytes": 42660 }, { "actual_sha256": "1122cc3a02a93ca1a41d6088a4852b3f4f47efa5c7a373c19c46605cff4853e6", @@ -3052,8 +3052,8 @@ }, { "repo_relative_path": "scripts/kb_apply_prereqs.sql", - "sha256": "bdf8c5da05eed10665b05ad1e331e3c9c8d72464c59889a3cf8f34ab23822faa", - "size_bytes": 42602 + "sha256": "d51c4b3462aac09baf68b3ca1b2255275b91a5a976f3f45ace5ed0870511e36a", + "size_bytes": 42660 }, { "repo_relative_path": "scripts/proposal_apply_lifecycle.py", @@ -3197,64 +3197,64 @@ "public.claim_edges": [ { "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe" } ], "public.claim_evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "role": "illustrates", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123" }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", - "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf" + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "role": "grounds", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6" } ], "public.claims": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "b4d0a944-8f11-5516-80ca-bc680f0059ad" ], "public.reasoning_tools": [ - "41b58d96-37f6-526c-b021-58f1dbcfdb6c" + "a32a7252-d39f-5ee9-873a-a82b56a6bb08" ], "public.sources": [ - "7a2198b6-16b2-52c6-a641-7ad59826e5bf", - "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "3953271f-7df5-5674-99b0-980b1b3534e6", + "3d31345d-a4f7-52a7-af4a-0034f99a8123" ] }, "expected": { "public.claim_edges": [ { "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe" } ], "public.claim_evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "role": "illustrates", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123" }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", - "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf" + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "role": "grounds", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6" } ], "public.claims": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "b4d0a944-8f11-5516-80ca-bc680f0059ad" ], "public.reasoning_tools": [ - "41b58d96-37f6-526c-b021-58f1dbcfdb6c" + "a32a7252-d39f-5ee9-873a-a82b56a6bb08" ], "public.sources": [ - "7a2198b6-16b2-52c6-a641-7ad59826e5bf", - "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "3953271f-7df5-5674-99b0-980b1b3534e6", + "3d31345d-a4f7-52a7-af4a-0034f99a8123" ] } }, @@ -3272,9 +3272,9 @@ }, "pass": true, "proposal": { - "applied_at": "2026-07-15 03:30:10.578016+00", + "applied_at": "2026-07-15 03:59:12.452878+00", "applied_by_handle": "kb-apply", - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "status": "applied" }, "rollback_cleanup": { @@ -3337,7 +3337,7 @@ "row_count": 0 }, "public.agents": { - "content_md5": "d67081359e7ec2fa2101b26f3e1b3f75", + "content_md5": "832dd26c09015b5df7cd2d417e145e17", "row_count": 2 }, "public.claim_edges": { @@ -3345,11 +3345,11 @@ "row_count": 0 }, "public.claim_evidence": { - "content_md5": "da01cd47b5562650406f21a18aaea9b6", + "content_md5": "5c05c4921a2c6599fbaf82b7257441fc", "row_count": 1 }, "public.claims": { - "content_md5": "01ad0f2d690600be6a1988899c3e743e", + "content_md5": "904d8f47716fc08d7d06c72298263586", "row_count": 1 }, "public.reasoning_tools": { @@ -3357,7 +3357,7 @@ "row_count": 0 }, "public.sources": { - "content_md5": "18a42c193671894196c47d58da8da024", + "content_md5": "e74fb3d1343235ad94af468b2007d8a6", "row_count": 1 } } diff --git a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json index b3e663d..ed8f725 100644 --- a/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json +++ b/docs/reports/leo-working-state-20260709/proposal-apply-lifecycle-receipt-current.json @@ -1,48 +1,48 @@ { "applied_row_keys": { "claim_edges": [ - "3ff15dc5-f9e8-5079-8e70-dc51d6f3e4c8" + "cd799806-18e8-5e8c-959c-5f9c267654a7" ], "claim_evidence": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb|bf697d93-8b77-5e2b-a6c0-0825e5ba76fd|grounds", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95|7a2198b6-16b2-52c6-a641-7ad59826e5bf|illustrates" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe|3d31345d-a4f7-52a7-af4a-0034f99a8123|illustrates", + "b4d0a944-8f11-5516-80ca-bc680f0059ad|3953271f-7df5-5674-99b0-980b1b3534e6|grounds" ], "claims": [ - "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95" + "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", + "b4d0a944-8f11-5516-80ca-bc680f0059ad" ], "reasoning_tools": [ - "41b58d96-37f6-526c-b021-58f1dbcfdb6c" + "a32a7252-d39f-5ee9-873a-a82b56a6bb08" ], "sources": [ - "7a2198b6-16b2-52c6-a641-7ad59826e5bf", - "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd" + "3953271f-7df5-5674-99b0-980b1b3534e6", + "3d31345d-a4f7-52a7-af4a-0034f99a8123" ] }, "applied_row_sha256": { "claim_edges": [ - "65e5186be950498bd8ff8ef2043804181ec5bef02c9c1bb36a965dd9410e8b5b" + "aae7ed87c66cf58136f2b0027ae1cddc9092cd64bfc8e617cd7746b2306274c5" ], "claim_evidence": [ - "9164b7c63641e5cbf5422f50299490053d547ba6ce1108c970b1ebfb89dc8e25", - "c098ddaadc9b7d14e3f0d48f844b88750fc7529813a20762240557abcdb1391b" + "388f3363173efda00f0688fab77fe0ce2baf62035220b843be1adea1f1c70f7f", + "55838cb722f7158cbdbdc3b79212e764f9fa6014771985aec3c1c7856967db07" ], "claims": [ - "e8cb8a99124bcc1f98fb0316132155c4db6d9dd12879f40a0ece82cc97e54085", - "4ffd395e8534ab7c9d565147667c8e207eacf70dbfcae6e8959e9b9203e4429f" + "75fe4543c9c3194612b1cf98b074ff7e361da17c9bcd59f9b6f085c2c0861277", + "5914923936817eff6d7e5c824c94c18ae6392b7a6e80c87ace2e547865b173eb" ], "reasoning_tools": [ - "355dee4df27c89809daa214fde69fdfb9f15fc2a29f3985582fe69d7bd797598" + "990dacb7b77cec117d9ee4a7630625a8782d06dfd549340b3269b8332c170576" ], "sources": [ - "cea718e74eb3d2c2672491e2e6fc523c4c4a4ae3060babbb24652f8004a2c7fd", - "d31a88fff760ed8d5985a2557f20524a372a0ea94893b7ad1aa1d24e6fe58050" + "585edbec2f98ec127041cdd662506a1494ea402f7e25ac0082dbda98197bf130", + "a8d2eead7cb3e563869978570173e2af753dfe131d4b7cfcf6dd419ffbb427e5" ] }, - "apply_payload_sha256": "89faf1f2fc9481574934de0eefb91cb8056e10784ec0f966c621621ff4f91b02", - "apply_receipt_sha256": "456247af33d4222f76c47c0a4e9228135d7a46c2c04c0f9c928b6bae5f30cde8", - "apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", - "approval_snapshot_sha256": "ae28ff3694a19603b562f3233772ea68371702f22732026c75c33af944428dab", + "apply_payload_sha256": "e033bd4e742dfa0dad7d26e2f2b1f18eb71996541cdbc575bb2d4504c045e36f", + "apply_receipt_sha256": "ac99a2a315cc8e6e214e0f2f69d1a23413da9cfd8629c202b61a678ffda6d7ca", + "apply_sql_sha256": "b52cd47182dc0f542a394147201bb3a125518f8a4bc1a7fc44f2b0caa39c4a1b", + "approval_snapshot_sha256": "1f9d0a58ad236908da931c7489fe14ee855d0f13c4d72eb5b218370e116e2096", "artifact": "proposal_apply_lifecycle_receipt", "checks": { "apply_receipt_replay_ready": true, @@ -58,11 +58,11 @@ "unrelated_rows_unchanged": true }, "current_tier": "T2_runtime", - "fresh_owned_apply_sql_sha256": "5e93caad9e259d34b2ed02f98825a41b48cff4cfe0678d60a43ed1d08298ce7a", - "fresh_preflight_artifact_sha256": "33ae0ebf83cb0d29c0f07e45587b912f7716faa7360ec585c46b65e593723dee", - "fresh_preflight_sha256": "3c4a6b90e6cbb7aa9f93966465f26ada386c2e3bd8326a8bfb23c2efb0c142b8", - "generated_at_utc": "2026-07-15T03:30:13.458916+00:00", - "lifecycle_receipt_sha256": "6a94df2a04b9b71f931d23d5e5fba3aa295395f9ef636f490bcffdd43d1af697", + "fresh_owned_apply_sql_sha256": "b52cd47182dc0f542a394147201bb3a125518f8a4bc1a7fc44f2b0caa39c4a1b", + "fresh_preflight_artifact_sha256": "2312c91d82ee378d4a53136b8e307900c97d0611d9f12098e799cb6de5d30077", + "fresh_preflight_sha256": "90facb2ca62feb1d3c7a242e84427ab402cf57148eaba40ec700f3cc4896d20f", + "generated_at_utc": "2026-07-15T03:59:15.412413+00:00", + "lifecycle_receipt_sha256": "4254f363b0c6115ecf07856c6e6a9879b43840e688aa73211cb9eff893b36c06", "pass": true, "production_apply_authorization_present": false, "production_apply_executed": false, @@ -70,7 +70,7 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "payload": { "apply_payload": { "agent_id": null, @@ -78,7 +78,7 @@ { "confidence": 0.9, "created_by": null, - "id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "status": "open", "superseded_by": null, "tags": [ @@ -91,7 +91,7 @@ { "confidence": 0.85, "created_by": null, - "id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "status": "open", "superseded_by": null, "tags": [ @@ -107,24 +107,24 @@ { "created_by": null, "edge_type": "supports", - "from_claim": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", - "to_claim": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "from_claim": "b4d0a944-8f11-5516-80ca-bc680f0059ad", + "to_claim": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "weight": 0.75 } ], "evidence": [ { - "claim_id": "32cc5b57-0d89-58aa-9cc1-f9e0c63947fb", + "claim_id": "b4d0a944-8f11-5516-80ca-bc680f0059ad", "created_by": null, "role": "grounds", - "source_id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "source_id": "3953271f-7df5-5674-99b0-980b1b3534e6", "weight": 0.9 }, { - "claim_id": "4d8f5ef5-d1a3-5043-a9e8-fdc202c10d95", + "claim_id": "a9dd972a-b867-56f7-b3c9-3913dd9a0abe", "created_by": null, "role": "illustrates", - "source_id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "source_id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "weight": 0.8 } ], @@ -133,7 +133,7 @@ "agent_id": null, "category": "verification", "description": "Verify approved proposal to canonical graph lifecycle in a disposable clone.", - "id": "41b58d96-37f6-526c-b021-58f1dbcfdb6c", + "id": "a32a7252-d39f-5ee9-873a-a82b56a6bb08", "name": "Canonical row proof canary" } ], @@ -141,8 +141,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source A.", - "hash": "approve-claim-canary-4d6107db5d-a", - "id": "bf697d93-8b77-5e2b-a6c0-0825e5ba76fd", + "hash": "approve-claim-canary-e315c2518c-a", + "id": "3953271f-7df5-5674-99b0-980b1b3534e6", "source_type": "observation", "storage_path": null, "url": null @@ -150,8 +150,8 @@ { "created_by": null, "excerpt": "Disposable clone lifecycle canary source B.", - "hash": "approve-claim-canary-4d6107db5d-b", - "id": "7a2198b6-16b2-52c6-a641-7ad59826e5bf", + "hash": "approve-claim-canary-e315c2518c-b", + "id": "3d31345d-a4f7-52a7-af4a-0034f99a8123", "source_type": "observation", "storage_path": null, "url": null @@ -161,12 +161,12 @@ }, "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "approved" }, - "proposal_payload_sha256": "3e499f82baa1fa80dba0fdeee7133dfec9c92f111a9cd1aa0b77fe0a3c12c112", + "proposal_payload_sha256": "cf2676db5a64142d07a7b46f02f1ba38bfa8cca69d03484bbcaa5eeb7002af71", "required_tier": "T2_runtime", "rollback": { "counts_after_rollback": { @@ -196,15 +196,15 @@ "applied_at": null, "applied_by_agent_id": null, "applied_by_handle": null, - "id": "0b5cfd03-8c1f-509a-b1e1-a05e45164d8d", + "id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b", "proposal_type": "approve_claim", "review_note": "Reviewed exact strict payload inside the disposable clone.", - "reviewed_at": "2026-07-15 03:30:07.092864+00", + "reviewed_at": "2026-07-15 03:59:09.091704+00", "reviewed_by_agent_id": "99999999-9999-9999-9999-999999999999", "reviewed_by_handle": "m3ta", "status": "canceled" }, - "rollback_sql_sha256": "5b184fc6a65373549b257c3dd40abac91bb90bd4c75b890798fcabc4174dee7b", + "rollback_sql_sha256": "50758dab3f998289a879cedb4a3f4535814e70c7f4dde417812092b9fe194901", "schema": "livingip.proposalApplyRollback.v2", "target_rows_after": { "claim_edges": [],