From 224a448bb195be610aaec2f4423105f2bf10284d Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Wed, 15 Jul 2026 05:34:16 +0200 Subject: [PATCH] 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)