Merge pull request #159 from living-ip/codex/leo-proposal-apply-lifecycle-20260715
Some checks are pending
CI / lint-and-test (push) Waiting to run

Rehearse approved proposal apply and compensating rollback
This commit is contained in:
twentyOne2x 2026-07-15 06:05:45 +02:00 committed by GitHub
commit 2416f918ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 8638 additions and 953 deletions

View file

@ -0,0 +1,141 @@
begin;
set local standard_conforming_strings = on;
set local lock_timeout = '5s';
select pg_advisory_xact_lock(hashtextextended('proposal-rollback:' || E'edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b', 0));
do $rollback$
declare
affected integer;
approval_now jsonb;
downstream_dependency_count integer;
begin
perform 1 from kb_stage.kb_proposals
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'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":"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: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:59:12.452878+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'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'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'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'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'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'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'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'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'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'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'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'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'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'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'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'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'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;
end if;
update kb_stage.kb_proposals
set status = 'canceled',
applied_by_handle = null,
applied_by_agent_id = null,
applied_at = null,
updated_at = now()
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":"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;
end if;
end
$rollback$;
commit;

View file

@ -0,0 +1,219 @@
{
"applied_row_keys": {
"claim_edges": [
"cd799806-18e8-5e8c-959c-5f9c267654a7"
],
"claim_evidence": [
"a9dd972a-b867-56f7-b3c9-3913dd9a0abe|3d31345d-a4f7-52a7-af4a-0034f99a8123|illustrates",
"b4d0a944-8f11-5516-80ca-bc680f0059ad|3953271f-7df5-5674-99b0-980b1b3534e6|grounds"
],
"claims": [
"a9dd972a-b867-56f7-b3c9-3913dd9a0abe",
"b4d0a944-8f11-5516-80ca-bc680f0059ad"
],
"reasoning_tools": [
"a32a7252-d39f-5ee9-873a-a82b56a6bb08"
],
"sources": [
"3953271f-7df5-5674-99b0-980b1b3534e6",
"3d31345d-a4f7-52a7-af4a-0034f99a8123"
]
},
"applied_row_sha256": {
"claim_edges": [
"aae7ed87c66cf58136f2b0027ae1cddc9092cd64bfc8e617cd7746b2306274c5"
],
"claim_evidence": [
"388f3363173efda00f0688fab77fe0ce2baf62035220b843be1adea1f1c70f7f",
"55838cb722f7158cbdbdc3b79212e764f9fa6014771985aec3c1c7856967db07"
],
"claims": [
"75fe4543c9c3194612b1cf98b074ff7e361da17c9bcd59f9b6f085c2c0861277",
"5914923936817eff6d7e5c824c94c18ae6392b7a6e80c87ace2e547865b173eb"
],
"reasoning_tools": [
"990dacb7b77cec117d9ee4a7630625a8782d06dfd549340b3269b8332c170576"
],
"sources": [
"585edbec2f98ec127041cdd662506a1494ea402f7e25ac0082dbda98197bf130",
"a8d2eead7cb3e563869978570173e2af753dfe131d4b7cfcf6dd419ffbb427e5"
]
},
"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,
"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_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_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,
"proposal_before_apply": {
"applied_at": null,
"applied_by_agent_id": null,
"applied_by_handle": null,
"id": "edaf2c90-af15-5a2f-b6b9-fe08ab9ae81b",
"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_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_handle": "m3ta",
"status": "approved"
},
"proposal_payload_sha256": "cf2676db5a64142d07a7b46f02f1ba38bfa8cca69d03484bbcaa5eeb7002af71",
"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": "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_handle": "m3ta",
"status": "canceled"
},
"rollback_sql_sha256": "50758dab3f998289a879cedb4a3f4535814e70c7f4dde417812092b9fe194901",
"schema": "livingip.proposalApplyRollback.v2",
"target_rows_after": {
"claim_edges": [],
"claim_evidence": [],
"claims": [],
"reasoning_tools": [],
"sources": []
}
},
"schema": "livingip.proposalApplyLifecycleReceipt.v2",
"strongest_claim_allowed": "deterministic disposable-clone apply and compensating rollback"
}

View file

@ -0,0 +1,260 @@
{
"artifact": "proposal_apply_production_authorization_packet",
"authorization_record_required": {
"authorization_text": "<EXACT_TEXT_FROM_VERIFIER>",
"authorized": true,
"binding_sha256": "6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a",
"expires_at_utc": "<UTC>",
"operator_identity": "<OPERATOR_IDENTITY>",
"production_rollback_sql_sha256": "<EXACT_PRODUCTION_ROLLBACK_SHA256>",
"received_at_utc": "<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 6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a. I also authorize conditional production rollback SHA-256 <PRODUCTION_ROLLBACK_SQL_SHA256> 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 <OPERATOR_IDENTITY>; received <UTC>; expires <UTC>.",
"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-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": "bd3c17628c6cf7da734be01149bbf1cc77a6d71b",
"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-15T02:07:27.133665+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": "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: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-15T02:07:27.133665+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
}
}

View file

@ -0,0 +1,62 @@
# Proposal Apply Production Authorization Packet
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`
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: `6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a`
## Production Preconditions
- `approval_gate_ready`: `False`
- `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`
- `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 6f1984f3a69ad049d4bbcc408ed2542dc5f081806ec9baa9a35c8959e5dab62a. I also authorize conditional production rollback SHA-256 <PRODUCTION_ROLLBACK_SQL_SHA256> 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 <OPERATOR_IDENTITY>; received <UTC>; expires <UTC>.
## 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

View file

@ -0,0 +1,32 @@
{
"artifact": "proposal_apply_production_target_readback",
"schema": "livingip.proposalApplyProductionTargetReadback.v1",
"observed_at_utc": "2026-07-15T02:07:27.133665+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."
}

View file

@ -14,6 +14,7 @@ dependencies = [
[project.optional-dependencies] [project.optional-dependencies]
dev = [ dev = [
"hypothesis>=6,<7",
"pytest>=8", "pytest>=8",
"pytest-asyncio>=0.23", "pytest-asyncio>=0.23",
"ruff>=0.3", "ruff>=0.3",

View file

@ -111,8 +111,17 @@ CLAIM_TYPES = {"empirical", "structural", "normative", "meta", "concept"}
SOURCE_TYPES = {"paper", "article", "transcript", "observation", "dataset", "post", "dm", "other"} SOURCE_TYPES = {"paper", "article", "transcript", "observation", "dataset", "post", "dm", "other"}
EVIDENCE_ROLES = {"grounds", "illustrates", "contradicts"} EVIDENCE_ROLES = {"grounds", "illustrates", "contradicts"}
EDGE_TYPES = { EDGE_TYPES = {
"supports", "challenges", "requires", "relates", "contradicts", "supports",
"supersedes", "derives_from", "cites", "causes", "constrains", "accelerates", "challenges",
"requires",
"relates",
"contradicts",
"supersedes",
"derives_from",
"cites",
"causes",
"constrains",
"accelerates",
} }
MAX_BUNDLE_ROWS = { MAX_BUNDLE_ROWS = {
@ -143,6 +152,21 @@ def _jsonb(value: Any) -> str:
return sql_literal(json.dumps(value, sort_keys=True)) + "::jsonb" 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: def _text_array(values: list[str]) -> str:
if not values: if not values:
return "'{}'::text[]" 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}") raise ValueError(f"{path} contains unknown fields: {unknown}")
def _validate_approval_meta( def _validate_approval_meta(approval: dict[str, Any], proposal_type: str, apply_payload: dict[str, Any]) -> None:
approval: dict[str, Any], proposal_type: str, apply_payload: dict[str, Any]
) -> None:
if not isinstance(approval, dict): if not isinstance(approval, dict):
raise ValueError("approved proposal metadata is required") raise ValueError("approved proposal metadata is required")
if approval.get("proposal_type") != proposal_type: 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: def _approval_guard_sql(proposal_id: str, approval: dict[str, Any]) -> str:
return f"""select kb_stage.assert_approved_proposal( return f"""select kb_stage.assert_approved_proposal(
{sql_literal(proposal_id)}::uuid, {sql_literal(proposal_id)}::uuid,
{sql_literal(approval['proposal_type'])}, {sql_literal(approval["proposal_type"])},
{_jsonb(approval['payload'])}, {_jsonb(approval["payload"])},
{sql_literal(approval['reviewed_by_handle'])}, {sql_literal(approval["reviewed_by_handle"])},
{sql_literal(approval.get('reviewed_by_agent_id'))}::uuid, {sql_literal(approval.get("reviewed_by_agent_id"))}::uuid,
{sql_literal(approval['reviewed_at'])}::timestamptz, {sql_literal(approval["reviewed_at"])}::timestamptz,
{sql_literal(approval['review_note'])} {sql_literal(approval["review_note"])}
);""" );"""
@ -245,12 +267,12 @@ end
$verify$;""" $verify$;"""
finish_sql = f"""select kb_stage.finish_approved_proposal( finish_sql = f"""select kb_stage.finish_approved_proposal(
{sql_literal(proposal_id)}::uuid, {sql_literal(proposal_id)}::uuid,
{sql_literal(approval['proposal_type'])}, {sql_literal(approval["proposal_type"])},
{_jsonb(approval['payload'])}, {_jsonb(approval["payload"])},
{sql_literal(approval['reviewed_by_handle'])}, {sql_literal(approval["reviewed_by_handle"])},
{sql_literal(approval.get('reviewed_by_agent_id'))}::uuid, {sql_literal(approval.get("reviewed_by_agent_id"))}::uuid,
{sql_literal(approval['reviewed_at'])}::timestamptz, {sql_literal(approval["reviewed_at"])}::timestamptz,
{sql_literal(approval['review_note'])}, {sql_literal(approval["review_note"])},
{sql_literal(applied_by)} {sql_literal(applied_by)}
);""" );"""
return checks_sql + "\n" + finish_sql return checks_sql + "\n" + finish_sql
@ -301,9 +323,9 @@ update public.strategies
insert into public.strategies insert into public.strategies
(agent_id, diagnosis, guiding_policy, proximate_objectives, version, active) (agent_id, diagnosis, guiding_policy, proximate_objectives, version, active)
select {sql_literal(agent_id)}::uuid, select {sql_literal(agent_id)}::uuid,
{sql_literal(strategy['diagnosis'])}, {sql_literal(strategy["diagnosis"])},
{sql_literal(strategy['guiding_policy'])}, {sql_literal(strategy["guiding_policy"])},
{_jsonb(strategy['proximate_objectives'])}, {_jsonb(strategy["proximate_objectives"])},
coalesce(max(version), 0) + 1, coalesce(max(version), 0) + 1,
true true
from public.strategies from public.strategies
@ -325,9 +347,7 @@ values
raise exception 'apply_proposal: expected exactly one active strategy for agent %', {sql_literal(agent_id)}; raise exception 'apply_proposal: expected exactly one active strategy for agent %', {sql_literal(agent_id)};
end if;""" end if;"""
ledger = _ledger_and_verify( ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval)
proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval
)
return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, 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], approval: dict[str, Any],
) -> str: ) -> str:
_validate_approval_meta(approval, "add_edge", apply_payload) _validate_approval_meta(approval, "add_edge", apply_payload)
f = apply_payload.get("from_claim") _reject_unknown(apply_payload, {"from_claim", "to_claim", "edge_type", "weight"}, "add_edge apply_payload")
t = apply_payload.get("to_claim") 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") et = apply_payload.get("edge_type")
w = apply_payload.get("weight") if et not in EDGE_TYPES:
if not (f and t and et): raise ValueError(f"add_edge.edge_type must be one of {sorted(EDGE_TYPES)}")
raise ValueError("add_edge apply_payload requires 'from_claim', 'to_claim', 'edge_type'") w = _weight(apply_payload.get("weight"), "add_edge.weight")
if f == t: if f == t:
raise ValueError("add_edge from_claim and to_claim must differ") 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}" edge_lock_key = f"claim_edge:{f}:{t}:{et}"
canonical = f""" canonical = f"""
@ -354,8 +376,8 @@ def build_add_edge_sql(
select pg_advisory_xact_lock(hashtextextended({sql_literal(edge_lock_key)}, 0)); 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 the edge unless an identical (from,to,type) edge already exists
insert into public.claim_edges (from_claim, to_claim, edge_type, weight) insert into public.claim_edges (id, from_claim, to_claim, edge_type, weight)
select {sql_literal(f)}::uuid, {sql_literal(t)}::uuid, select {sql_literal(row_id)}::uuid, {sql_literal(f)}::uuid, {sql_literal(t)}::uuid,
{sql_literal(et)}::edge_type, {sql_literal(w)} {sql_literal(et)}::edge_type, {sql_literal(w)}
where not exists ( where not exists (
select 1 from public.claim_edges 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); and edge_type = {sql_literal(et)}::edge_type);
""".rstrip() """.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 where from_claim = {sql_literal(f)}::uuid
and to_claim = {sql_literal(t)}::uuid and to_claim = {sql_literal(t)}::uuid
and edge_type = {sql_literal(et)}::edge_type 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'; raise exception 'apply_proposal: claim_edge row does not match strict apply payload';
end if;""" end if;"""
ledger = _ledger_and_verify( ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval)
proposal_id, applied_by or SERVICE_AGENT_HANDLE, checks, approval
)
return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, 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], approval: dict[str, Any],
) -> str: ) -> str:
_validate_approval_meta(approval, "attach_evidence", apply_payload) _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 [] evidence: list[dict[str, Any]] = apply_payload.get("evidence") or []
if not evidence: if not evidence:
raise ValueError("attach_evidence apply_payload requires non-empty 'evidence'") raise ValueError("attach_evidence apply_payload requires non-empty 'evidence'")
@ -399,17 +428,17 @@ def build_attach_evidence_sql(
statements = [] statements = []
checks = [] checks = []
for i, ev in enumerate(evidence): for i, ev in enumerate(evidence):
claim_id = ev.get("claim_id") _reject_unknown(
source_id = ev.get("source_id") ev,
role = ev.get("role") or "grounds" {"claim_id", "source_id", "role", "weight"},
weight = ev.get("weight") f"attach_evidence.evidence[{i}]",
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."
) )
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"
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")
statements.append( statements.append(
f"""insert into public.claim_evidence (claim_id, source_id, role, weight) f"""insert into public.claim_evidence (claim_id, source_id, role, weight)
select {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid, select {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid,
@ -417,7 +446,14 @@ select {sql_literal(claim_id)}::uuid, {sql_literal(source_id)}::uuid,
on conflict (claim_id, source_id, role) do nothing;""" on conflict (claim_id, source_id, role) do nothing;"""
) )
checks.append( 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 where claim_id = {sql_literal(claim_id)}::uuid
and source_id = {sql_literal(source_id)}::uuid and source_id = {sql_literal(source_id)}::uuid
and role = {sql_literal(role)}::evidence_role and role = {sql_literal(role)}::evidence_role
@ -434,9 +470,7 @@ on conflict (claim_id, source_id, role) do nothing;"""
) )
canonical = "\n".join(statements) canonical = "\n".join(statements)
ledger = _ledger_and_verify( ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval)
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))
@ -445,6 +479,9 @@ def build_approve_claim_sql(
proposal_id: str, proposal_id: str,
applied_by: str | None, applied_by: str | None,
approval: dict[str, Any], approval: dict[str, Any],
*,
fresh_owned: bool = False,
fresh_preflight_sha256: str | None = None,
) -> str: ) -> str:
"""Build one conflict-safe transaction for a reviewed canonical graph bundle.""" """Build one conflict-safe transaction for a reviewed canonical graph bundle."""
_validate_approval_meta(approval, "approve_claim", apply_payload) _validate_approval_meta(approval, "approve_claim", apply_payload)
@ -509,12 +546,8 @@ def build_approve_claim_sql(
"status": status, "status": status,
"confidence": _weight(row.get("confidence"), f"{path}.confidence"), "confidence": _weight(row.get("confidence"), f"{path}.confidence"),
"tags": tags, "tags": tags,
"created_by": _uuid( "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True),
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),
),
"superseded_by": _uuid(
row.get("superseded_by"), f"{path}.superseded_by", nullable=True
),
} }
) )
@ -543,9 +576,7 @@ def build_approve_claim_sql(
"storage_path": row.get("storage_path"), "storage_path": row.get("storage_path"),
"excerpt": row.get("excerpt"), "excerpt": row.get("excerpt"),
"hash": source_hash, "hash": source_hash,
"created_by": _uuid( "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True),
row.get("created_by", agent_id), f"{path}.created_by", nullable=True
),
} }
) )
@ -566,9 +597,7 @@ def build_approve_claim_sql(
"source_id": _uuid(row.get("source_id"), f"{path}.source_id"), "source_id": _uuid(row.get("source_id"), f"{path}.source_id"),
"role": role, "role": role,
"weight": _weight(row.get("weight"), f"{path}.weight"), "weight": _weight(row.get("weight"), f"{path}.weight"),
"created_by": _uuid( "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True),
row.get("created_by", agent_id), f"{path}.created_by", nullable=True
),
} }
) )
@ -589,13 +618,12 @@ def build_approve_claim_sql(
raise ValueError(f"{path} cannot be a self-edge") raise ValueError(f"{path} cannot be a self-edge")
edges.append( edges.append(
{ {
"id": deterministic_row_uuid(proposal_id, "claim_edge", from_claim, to_claim, edge_type),
"from_claim": from_claim, "from_claim": from_claim,
"to_claim": to_claim, "to_claim": to_claim,
"edge_type": edge_type, "edge_type": edge_type,
"weight": _weight(row.get("weight"), f"{path}.weight"), "weight": _weight(row.get("weight"), f"{path}.weight"),
"created_by": _uuid( "created_by": _uuid(row.get("created_by", agent_id), f"{path}.created_by", nullable=True),
row.get("created_by", agent_id), f"{path}.created_by", nullable=True
),
} }
) )
@ -639,169 +667,212 @@ def build_approve_claim_sql(
) )
_dedupe([row["id"] for row in reasoning_tools], "approve_claim.reasoning_tools ids") _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] = [] statements: list[str] = []
checks: 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: if sources:
collision_checks = [] collision_checks = []
for row in sources: for row in sources:
collision_checks.append( collision_checks.append(
f""" if exists (select 1 from public.sources f""" if exists (select 1 from public.sources
where hash = {sql_literal(row['hash'])} where hash = {sql_literal(row["hash"])}
and id <> {sql_literal(row['id'])}::uuid) then and id <> {sql_literal(row["id"])}::uuid) then
raise exception 'approve_claim: source hash collision for source %', {sql_literal(row['id'])}; raise exception 'approve_claim: source hash collision for source %', {sql_literal(row["id"])};
end if;""" end if;"""
) )
statements.append( statements.append("do $source_conflicts$\nbegin\n" + "\n".join(collision_checks) + "\nend\n$source_conflicts$;")
"do $source_conflicts$\nbegin\n"
+ "\n".join(collision_checks)
+ "\nend\n$source_conflicts$;"
)
for row in claims: for row in claims:
tags = _text_array(row["tags"]) tags = _text_array(row["tags"])
conflict_clause = ";" if fresh_owned else "\non conflict (id) do nothing;"
statements.append( statements.append(
f"""insert into public.claims (id, type, text, status, confidence, tags, created_by, superseded_by) 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'])}, 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["status"])}, {sql_literal(row["confidence"])}, {tags},
{sql_literal(row['created_by'])}::uuid, {sql_literal(row['superseded_by'])}::uuid {sql_literal(row["created_by"])}::uuid, {sql_literal(row["superseded_by"])}::uuid{conflict_clause}"""
on conflict (id) do nothing;"""
) )
checks.append( checks.append(
f""" if not exists (select 1 from public.claims f""" if not exists (select 1 from public.claims
where id = {sql_literal(row['id'])}::uuid where id = {sql_literal(row["id"])}::uuid
and type = {sql_literal(row['type'])} and type = {sql_literal(row["type"])}
and text = {sql_literal(row['text'])} and text = {sql_literal(row["text"])}
and status = {sql_literal(row['status'])} and status = {sql_literal(row["status"])}
and confidence is not distinct from {sql_literal(row['confidence'])} and confidence is not distinct from {sql_literal(row["confidence"])}
and tags is not distinct from {tags} and tags is not distinct from {tags}
and created_by is not distinct from {sql_literal(row['created_by'])}::uuid 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 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'])}; raise exception 'approve_claim: claim row does not match strict apply payload: %', {sql_literal(row["id"])};
end if;""" end if;"""
) )
for row in sources: for row in sources:
conflict_clause = ";" if fresh_owned else "\non conflict do nothing;"
statements.append( statements.append(
f"""insert into public.sources (id, source_type, url, storage_path, excerpt, hash, created_by) 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'])}, 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["storage_path"])}, {sql_literal(row["excerpt"])}, {sql_literal(row["hash"])},
{sql_literal(row['created_by'])}::uuid {sql_literal(row["created_by"])}::uuid{conflict_clause}"""
on conflict do nothing;"""
) )
checks.append( checks.append(
f""" if exists (select 1 from public.sources f""" if exists (select 1 from public.sources
where hash = {sql_literal(row['hash'])} where hash = {sql_literal(row["hash"])}
and id <> {sql_literal(row['id'])}::uuid) then and id <> {sql_literal(row["id"])}::uuid) then
raise exception 'approve_claim: source hash collision for source %', {sql_literal(row['id'])}; raise exception 'approve_claim: source hash collision for source %', {sql_literal(row["id"])};
end if; end if;
if not exists (select 1 from public.sources if not exists (select 1 from public.sources
where id = {sql_literal(row['id'])}::uuid where id = {sql_literal(row["id"])}::uuid
and source_type = {sql_literal(row['source_type'])} and source_type = {sql_literal(row["source_type"])}
and url is not distinct from {sql_literal(row['url'])} and url is not distinct from {sql_literal(row["url"])}
and storage_path is not distinct from {sql_literal(row['storage_path'])} and storage_path is not distinct from {sql_literal(row["storage_path"])}
and excerpt is not distinct from {sql_literal(row['excerpt'])} and excerpt is not distinct from {sql_literal(row["excerpt"])}
and hash = {sql_literal(row['hash'])} and hash = {sql_literal(row["hash"])}
and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then 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'])}; raise exception 'approve_claim: source row does not match strict apply payload: %', {sql_literal(row["id"])};
end if;""" end if;"""
) )
for row in reasoning_tools: for row in reasoning_tools:
conflict_clause = ";" if fresh_owned else "\non conflict (id) do nothing;"
statements.append( statements.append(
f"""insert into public.reasoning_tools (id, agent_id, name, description, category) f"""insert into public.reasoning_tools (id, agent_id, name, description, category)
select {sql_literal(row['id'])}::uuid, {sql_literal(row['agent_id'])}::uuid, select {sql_literal(row["id"])}::uuid, {sql_literal(row["agent_id"])}::uuid,
{sql_literal(row['name'])}, {sql_literal(row['description'])}, {sql_literal(row['category'])} {sql_literal(row["name"])}, {sql_literal(row["description"])}, {sql_literal(row["category"])}{conflict_clause}"""
on conflict (id) do nothing;"""
) )
checks.append( checks.append(
f""" if not exists (select 1 from public.reasoning_tools f""" if not exists (select 1 from public.reasoning_tools
where id = {sql_literal(row['id'])}::uuid where id = {sql_literal(row["id"])}::uuid
and agent_id is not distinct from {sql_literal(row['agent_id'])}::uuid and agent_id is not distinct from {sql_literal(row["agent_id"])}::uuid
and name = {sql_literal(row['name'])} and name = {sql_literal(row["name"])}
and description = {sql_literal(row['description'])} and description = {sql_literal(row["description"])}
and category is not distinct from {sql_literal(row['category'])}) then 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'])}; raise exception 'approve_claim: reasoning tool row does not match strict apply payload: %', {sql_literal(row["id"])};
end if;""" end if;"""
) )
for row in evidence: for row in evidence:
conflict_clause = ";" if fresh_owned else "\non conflict (claim_id, source_id, role) do nothing;"
statements.append( statements.append(
f"""insert into public.claim_evidence (claim_id, source_id, role, weight, created_by) 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, 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["role"])}::evidence_role, {sql_literal(row["weight"])},
{sql_literal(row['created_by'])}::uuid {sql_literal(row["created_by"])}::uuid{conflict_clause}"""
on conflict (claim_id, source_id, role) do nothing;"""
) )
checks.append( checks.append(
f""" if exists (select 1 from public.claim_evidence f""" -- Accept a legacy receipt id only when exactly one semantic row matches.
where claim_id = {sql_literal(row['claim_id'])}::uuid if (select count(*) from public.claim_evidence
and source_id = {sql_literal(row['source_id'])}::uuid where claim_id = {sql_literal(row["claim_id"])}::uuid
and role = {sql_literal(row['role'])}::evidence_role and source_id = {sql_literal(row["source_id"])}::uuid
and (weight is distinct from {sql_literal(row['weight'])} and role = {sql_literal(row["role"])}::evidence_role) <> 1 then
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 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'; raise exception 'approve_claim: evidence row does not match strict apply payload';
end if; end if;
if not exists (select 1 from public.claim_evidence if not exists (select 1 from public.claim_evidence
where claim_id = {sql_literal(row['claim_id'])}::uuid where claim_id = {sql_literal(row["claim_id"])}::uuid
and source_id = {sql_literal(row['source_id'])}::uuid and source_id = {sql_literal(row["source_id"])}::uuid
and role = {sql_literal(row['role'])}::evidence_role and role = {sql_literal(row["role"])}::evidence_role
and weight is not distinct from {sql_literal(row['weight'])} and weight is not distinct from {sql_literal(row["weight"])}
and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then 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'; raise exception 'approve_claim: evidence row does not match strict apply payload';
end if;""" end if;"""
) )
for row in edges: for row in edges:
edge_lock_key = ( edge_lock_key = f"claim_edge:{row['from_claim']}:{row['to_claim']}:{row['edge_type']}"
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( statements.append(
f"""select pg_advisory_xact_lock(hashtextextended({sql_literal(edge_lock_key)}, 0)); 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) insert into public.claim_edges (id, from_claim, to_claim, edge_type, weight, created_by)
select {sql_literal(row['from_claim'])}::uuid, {sql_literal(row['to_claim'])}::uuid, 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["edge_type"])}::edge_type, {sql_literal(row["weight"])},
{sql_literal(row['created_by'])}::uuid {sql_literal(row["created_by"])}::uuid{edge_insert_guard}"""
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);"""
) )
checks.append( checks.append(
f""" if exists (select 1 from public.claim_edges f""" -- Accept a legacy receipt id only when exactly one semantic row matches.
where from_claim = {sql_literal(row['from_claim'])}::uuid if (select count(*) from public.claim_edges
and to_claim = {sql_literal(row['to_claim'])}::uuid where from_claim = {sql_literal(row["from_claim"])}::uuid
and edge_type = {sql_literal(row['edge_type'])}::edge_type and to_claim = {sql_literal(row["to_claim"])}::uuid
and (weight is distinct from {sql_literal(row['weight'])} and edge_type = {sql_literal(row["edge_type"])}::edge_type) <> 1 then
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 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'; raise exception 'approve_claim: edge row does not match strict apply payload';
end if; end if;
if not exists (select 1 from public.claim_edges if not exists (select 1 from public.claim_edges
where from_claim = {sql_literal(row['from_claim'])}::uuid where from_claim = {sql_literal(row["from_claim"])}::uuid
and to_claim = {sql_literal(row['to_claim'])}::uuid and to_claim = {sql_literal(row["to_claim"])}::uuid
and edge_type = {sql_literal(row['edge_type'])}::edge_type and edge_type = {sql_literal(row["edge_type"])}::edge_type
and weight is not distinct from {sql_literal(row['weight'])} and weight is not distinct from {sql_literal(row["weight"])}
and created_by is not distinct from {sql_literal(row['created_by'])}::uuid) then 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'; raise exception 'approve_claim: edge row does not match strict apply payload';
end if;""" end if;"""
) )
canonical = "\n\n".join(statements) canonical = "\n\n".join(statements)
ledger = _ledger_and_verify( ledger = _ledger_and_verify(proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval)
proposal_id, applied_by or SERVICE_AGENT_HANDLE, "\n".join(checks), approval return _wrap_txn(
canonical,
ledger,
_approval_guard_sql(proposal_id, approval),
serializable=fresh_owned,
) )
return _wrap_txn(canonical, ledger, _approval_guard_sql(proposal_id, approval))
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 ( return (
"begin;\n" "begin;\n"
"set local standard_conforming_strings = on;\n" + ("set transaction isolation level serializable;\n" if serializable else "")
f"{approval_guard_sql}\n" + "set local standard_conforming_strings = on;\n"
f"{canonical_sql}\n" + f"{approval_guard_sql}\n"
f"{ledger_sql}\n" + f"{canonical_sql}\n"
"commit;\n" + f"{ledger_sql}\n"
+ "commit;\n"
) )
@ -813,7 +884,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"] ptype = proposal["proposal_type"]
if ptype not in BUILDERS: if ptype not in BUILDERS:
raise ValueError(f"apply_proposal cannot apply proposal_type {ptype!r}") raise ValueError(f"apply_proposal cannot apply proposal_type {ptype!r}")
@ -824,6 +901,17 @@ def build_apply_sql(proposal: dict[str, Any], applied_by: str | None) -> str:
"proposal payload has no 'apply_payload' strict contract. " "proposal payload has no 'apply_payload' strict contract. "
"Run the normalizer to produce apply_payload before applying." "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]( return BUILDERS[ptype](
apply_payload, apply_payload,
proposal["id"], proposal["id"],
@ -837,9 +925,7 @@ def assert_applyable(proposal: dict[str, Any]) -> None:
if status == "applied": if status == "applied":
raise SystemExit(f"proposal {proposal['id']} is already applied (idempotent no-op)") raise SystemExit(f"proposal {proposal['id']} is already applied (idempotent no-op)")
if status != "approved": if status != "approved":
raise SystemExit( raise SystemExit(f"proposal {proposal['id']} has status {status!r}; only 'approved' proposals apply")
f"proposal {proposal['id']} has status {status!r}; only 'approved' proposals apply"
)
def assert_receiptable(proposal: dict[str, Any]) -> None: def assert_receiptable(proposal: dict[str, Any]) -> None:
@ -877,23 +963,36 @@ def run_psql(
) -> str: ) -> str:
docker_binary = shutil.which("docker") or "docker" docker_binary = shutil.which("docker") or "docker"
command = [ command = [
docker_binary, "exec", "-e", "PGPASSWORD", "-i", args.container, docker_binary,
"psql", "-U", args.role, "-h", args.host, "-d", args.db, "exec",
"-v", "ON_ERROR_STOP=1", "-At", "-q", "-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( 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"}, env={"PGPASSWORD": password, "PATH": "/usr/bin:/bin:/usr/local/bin"},
check=False, check=False,
) )
if result.returncode != 0: if result.returncode != 0:
if redact_output_on_error: if redact_output_on_error:
raise SystemExit( raise SystemExit(f"psql failed ({result.returncode}); private postflight output redacted")
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})\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}"
)
return result.stdout return result.stdout
@ -940,7 +1039,7 @@ def capture_replay_receipt(
raise RuntimeError("postflight query did not return a JSON object") raise RuntimeError("postflight query did not return a JSON object")
apply_sql_source = "exact_executed_sql" apply_sql_source = "exact_executed_sql"
if apply_sql is None: 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" apply_sql_source = "reconstructed_current_engine"
receipt = replay_receipt.build_replay_receipt( receipt = replay_receipt.build_replay_receipt(
proposal, proposal,
@ -972,6 +1071,14 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
p.add_argument("--db", default=DEFAULT_DB) p.add_argument("--db", default=DEFAULT_DB)
p.add_argument("--host", default=DEFAULT_HOST) p.add_argument("--host", default=DEFAULT_HOST)
p.add_argument("--role", default=DEFAULT_ROLE) 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( p.add_argument(
"--receipt-only", "--receipt-only",
action="store_true", action="store_true",
@ -980,8 +1087,7 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
p.add_argument( p.add_argument(
"--receipt-dir", "--receipt-dir",
default=None, default=None,
help="private receipt directory (default: KB_APPLY_RECEIPT_DIR or " help=f"private receipt directory (default: KB_APPLY_RECEIPT_DIR or {replay_receipt.DEFAULT_RECEIPT_DIR})",
f"{replay_receipt.DEFAULT_RECEIPT_DIR})",
) )
p.add_argument( p.add_argument(
"--receipt-out", "--receipt-out",
@ -994,6 +1100,28 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
return args 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: def main(argv: list[str] | None = None) -> int:
args = parse_args(sys.argv[1:] if argv is None else argv) args = parse_args(sys.argv[1:] if argv is None else argv)
@ -1020,13 +1148,13 @@ def main(argv: list[str] | None = None) -> int:
password = load_password(args.secrets_file) password = load_password(args.secrets_file)
proposal = load_proposal(args, password) proposal = load_proposal(args, password)
assert_applyable(proposal) assert_applyable(proposal)
print(build_apply_sql(proposal, args.applied_by)) print(build_apply_sql_for_args(proposal, args, args.applied_by))
return 0 return 0
password = load_password(args.secrets_file) password = load_password(args.secrets_file)
proposal = load_proposal(args, password) proposal = load_proposal(args, password)
assert_applyable(proposal) 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) run_psql(args, sql, password)
applied_proposal = load_proposal(args, password) applied_proposal = load_proposal(args, password)
try: try:

View file

@ -35,6 +35,7 @@ from __future__ import annotations
import argparse import argparse
import json import json
import os import os
import stat
import subprocess import subprocess
import sys import sys
from pathlib import Path 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. # bundles and evidence/edge applies do not trigger a generic identity render.
RENDER_TYPES = ("revise_strategy",) 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) # # 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)]} 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 # # Side-effecting steps #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
def _psql_args(args: argparse.Namespace) -> argparse.Namespace: def _psql_args(args: argparse.Namespace) -> argparse.Namespace:
"""Namespace shaped for ap.run_psql (reuses the kb_apply connection path).""" """Namespace shaped for ap.run_psql (reuses the kb_apply connection path)."""
return argparse.Namespace( return argparse.Namespace(container=args.container, db=args.db, host=args.host, role=args.role)
container=args.container, db=args.db, host=args.host, role=args.role
)
def fetch_candidates( def fetch_candidates(
@ -181,19 +244,72 @@ def fetch_candidates(
def apply_one(args: argparse.Namespace, proposal_id: str) -> None: 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 = [ cmd = [
sys.executable, str(args.apply_script), proposal_id, sys.executable,
"--applied-by", args.applied_by, str(args.apply_script),
"--secrets-file", args.secrets_file, proposal_id,
"--container", args.container, "--db", args.db, "--applied-by",
"--host", args.host, "--role", args.role, 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) 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(
raise RuntimeError( result.stderr,
f"apply failed for {proposal_id}: {result.stdout.strip()} {result.stderr.strip()}" proposal_id,
) )
if not committed:
raise RuntimeError(
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: def render_one(args: argparse.Namespace, agent_id: str | None) -> str:
@ -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)" return "render skipped (no render-cmd configured; PR2 renderer not deployed)"
result = subprocess.run(cmd, text=True, capture_output=True, check=False) result = subprocess.run(cmd, text=True, capture_output=True, check=False)
if result.returncode != 0: if result.returncode != 0:
raise RuntimeError( raise RuntimeError(f"render failed for agent {agent_id}: {result.stdout.strip()} {result.stderr.strip()}")
f"render failed for agent {agent_id}: {result.stdout.strip()} {result.stderr.strip()}"
)
return f"rendered agent {agent_id}" 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: def run(args: argparse.Namespace) -> int:
password = ap.load_password(args.secrets_file) password = ap.load_password(args.secrets_file)
failure_counts = load_failure_state(args.failure_state_file) failure_counts = load_failure_state(args.failure_state_file)
exhausted_ids = tuple( exhausted_ids = tuple(proposal_id for proposal_id, count in failure_counts.items() if count >= args.max_attempts)
proposal_id
for proposal_id, count in failure_counts.items()
if count >= args.max_attempts
)
candidates = fetch_candidates(args, password, exhausted_ids) candidates = fetch_candidates(args, password, exhausted_ids)
for proposal_id in exhausted_ids: for proposal_id in exhausted_ids:
@ -263,6 +373,15 @@ def run(args: argparse.Namespace) -> int:
print(f"applied {pid} ({ptype})") print(f"applied {pid} ({ptype})")
if ptype in RENDER_TYPES: if ptype in RENDER_TYPES:
print(" " + render_one(args, agent_id)) 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: except Exception as exc:
failures += 1 failures += 1
# Leave the proposal at 'approved' so a fixed one reapplies next tick # 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 # so a deterministically-failing proposal hits the ceiling instead of
# retrying forever. Surface loudly for the operator. # retrying forever. Surface loudly for the operator.
failure_counts[pid] = failure_counts.get(pid, 0) + 1 failure_counts[pid] = failure_counts.get(pid, 0) + 1
print(f"ERROR applying {pid} ({ptype}) [attempt {failure_counts[pid]}/" print(
f"{args.max_attempts}]: {exc}", file=sys.stderr) 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) save_failure_state(args.failure_state_file, failure_counts)
return 1 if failures else 0 return 1 if failures else 0
def parse_args(argv: list[str]) -> argparse.Namespace: def parse_args(argv: list[str]) -> argparse.Namespace:
p = argparse.ArgumentParser( p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
p.add_argument( 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.", 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("--limit", type=int, default=20, help="max candidates fetched per tick")
p.add_argument( 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 " help="max proposals actually APPLIED per tick (default 1: applies land "
"one-at-a-time and observably, not a whole-queue drain)", "one-at-a-time and observably, not a whole-queue drain)",
) )
p.add_argument( 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 " help="consecutive apply failures before a proposal is treated as a "
"poison pill and skipped (needs a human fix, not endless retries)", "poison pill and skipped (needs a human fix, not endless retries)",
) )
p.add_argument( p.add_argument(
"--failure-state-file", "--failure-state-file",
default=os.environ.get("KB_APPLY_WORKER_STATE", "/opt/teleo-eval/logs/kb-apply-worker-failures.json"), 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 " help="persisted per-proposal failure counts (survives oneshot ticks so the poison-pill ceiling actually bites)",
"the poison-pill ceiling actually bites)",
) )
p.add_argument( 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)", help="handle recorded as applied_by (default: the kb-apply service agent)",
) )
p.add_argument( 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)", help="path to the apply_proposal.py engine (the sole apply path)",
) )
p.add_argument( 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 "
"<proposal-id>.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}'. " help="render hook template, e.g. 'python3 render_soul.py --agent-id {agent_id}'. "
"Empty (default) skips render until the SOUL renderer is deployed.", "Empty (default) skips render until the SOUL renderer is deployed.",
) )

View file

@ -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())

View file

@ -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( def resolve_receipt_path(
proposal_id: str, proposal_id: str,
*, *,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,8 @@ image="${POSTGRES_CANARY_IMAGE:-postgres:16}"
source_tier="${SOURCE_TIER:-live-readonly}" source_tier="${SOURCE_TIER:-live-readonly}"
normalization_json="" normalization_json=""
output="${repo_root}/docs/reports/leo-working-state-20260709/approve-claim-clone-canary-current.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 while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
@ -20,6 +22,14 @@ while [[ $# -gt 0 ]]; do
output="$2" output="$2"
shift 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)
source_container="$2" source_container="$2"
shift 2 shift 2
@ -99,11 +109,19 @@ service_state() {
} }
mkdir -p "$workdir" "$(dirname "$output")" 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)" source_counts_before="$(source_counts)"
service_before="$(service_state)" service_before="$(service_state)"
docker run -d --name "$container" \ docker run -d --name "$container" \
--network none \ --network none \
--label livingip.canary=proposal-apply-lifecycle \
--label "livingip.canary.instance=${container}" \
--tmpfs /var/lib/postgresql/data:rw,nosuid,size=512m \ --tmpfs /var/lib/postgresql/data:rw,nosuid,size=512m \
-e POSTGRES_PASSWORD="isolated-postgres-${RANDOM}-${RANDOM}" \ -e POSTGRES_PASSWORD="isolated-postgres-${RANDOM}-${RANDOM}" \
-e POSTGRES_DB=teleo \ -e POSTGRES_DB=teleo \
@ -127,6 +145,12 @@ if [[ "$ready_streak" -lt 2 ]]; then
fi fi
container_network_mode="$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$container")" container_network_mode="$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$container")"
container_mounts_json="$(docker inspect -f '{{json .Mounts}}' "$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" \ docker exec "$source_container" pg_dump -U postgres -d "$source_db" \
--schema-only --no-owner --no-privileges >"$workdir/schema.sql" --schema-only --no-owner --no-privileges >"$workdir/schema.sql"
@ -165,6 +189,13 @@ normalization_args=()
if [[ -n "$normalization_json" ]]; then if [[ -n "$normalization_json" ]]; then
normalization_args=(--normalization-json "$normalization_json") normalization_args=(--normalization-json "$normalization_json")
fi 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 set +e
python3 "$repo_root/scripts/run_approve_claim_clone_canary.py" \ 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" \ --review-secrets-file "$workdir/kb-review.env" \
--secrets-file "$workdir/kb-apply.env" \ --secrets-file "$workdir/kb-apply.env" \
"${normalization_args[@]}" \ "${normalization_args[@]}" \
"${artifact_args[@]}" \
--output "$output" \ --output "$output" \
>"$workdir/stdout.json" 2>"$workdir/stderr.log" >"$workdir/stdout.json" 2>"$workdir/stderr.log"
canary_rc=$? canary_rc=$?
@ -192,6 +224,20 @@ container_name_readback="$(
docker container ls -a --filter "name=^/${container}$" --format '{{.Names}}' 2>&1 docker container ls -a --filter "name=^/${container}$" --format '{{.Names}}' 2>&1
)" )"
container_name_readback_rc=$? 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 if [[ -e "$workdir" || -L "$workdir" ]]; then
outer_workdir_lexists=true outer_workdir_lexists=true
else else
@ -214,6 +260,9 @@ OUTER_CONTAINER_REMOVE_RC="$outer_container_remove_rc" \
OUTER_WORKDIR_REMOVE_RC="$outer_workdir_remove_rc" \ OUTER_WORKDIR_REMOVE_RC="$outer_workdir_remove_rc" \
CONTAINER_NAME_READBACK="$container_name_readback" \ CONTAINER_NAME_READBACK="$container_name_readback" \
CONTAINER_NAME_READBACK_RC="$container_name_readback_rc" \ 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" \ OUTER_WORKDIR_LEXISTS="$outer_workdir_lexists" \
CANARY_RC="$canary_rc" \ CANARY_RC="$canary_rc" \
SOURCE_TIER="$source_tier" \ SOURCE_TIER="$source_tier" \
@ -221,219 +270,6 @@ SOURCE_NETWORK_MODE="$source_network_mode" \
SOURCE_CANARY_LABEL="$source_canary_label" \ SOURCE_CANARY_LABEL="$source_canary_label" \
CANARY_NETWORK_MODE="$container_network_mode" \ CANARY_NETWORK_MODE="$container_network_mode" \
CANARY_MOUNTS_JSON="$container_mounts_json" \ CANARY_MOUNTS_JSON="$container_mounts_json" \
python3 - "$output" <<'PY' CANARY_LABEL="$container_canary_label" \
import hashlib CANARY_INSTANCE_LABEL="$container_instance_label" \
import json python3 "$repo_root/scripts/finalize_approve_claim_isolated_canary.py" "$output"
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

View file

@ -30,6 +30,10 @@ sys.path.insert(0, str(REPO_ROOT / "scripts"))
import apply_proposal as ap # noqa: E402 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): def _approval_meta(proposal_type, apply_payload):
return { return {
@ -112,7 +116,7 @@ def test_revise_strategy_rejects_bad_node_type():
# --- add_edge ------------------------------------------------------------- # # --- add_edge ------------------------------------------------------------- #
def test_add_edge_sql_dedup_guard(): 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)) sql = ap.build_add_edge_sql(payload, "pid-2", None, _approval_meta("add_edge", payload))
assert "insert into public.claim_edges" in sql assert "insert into public.claim_edges" in sql
assert "not exists" 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(): 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)) 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")] 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 "claim_edge row does not match strict apply payload" in verify
assert sql.startswith("begin;") assert sql.startswith("begin;")
assert sql.rstrip().endswith("commit;") assert sql.rstrip().endswith("commit;")
assert sql.index("raise exception 'apply_proposal: claim_edge row") < sql.index( assert sql.index("raise exception 'apply_proposal: claim_edge row") < sql.index("kb_stage.finish_approved_proposal")
"kb_stage.finish_approved_proposal"
)
def test_add_edge_rejects_self_loop(): def test_add_edge_rejects_self_loop():
@ -144,22 +146,18 @@ def test_add_edge_rejects_self_loop():
# --- attach_evidence ------------------------------------------------------ # # --- attach_evidence ------------------------------------------------------ #
def test_attach_evidence_sql_with_source_id(): 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)) sql = ap.build_attach_evidence_sql(payload, "pid-3", None, _approval_meta("attach_evidence", payload))
assert "insert into public.claim_evidence" 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)" in sql
assert "::evidence_role" in sql assert "::evidence_role" in sql
assert "not exists" in sql assert "not exists" in sql
def test_attach_evidence_semantic_row_accepts_match_and_rejects_weight_mismatch(): def test_attach_evidence_semantic_row_accepts_match_and_rejects_weight_mismatch():
payload = { payload = {"evidence": [{"claim_id": CLAIM_A, "source_id": SOURCE_A, "role": "grounds", "weight": 0.78}]}
"evidence": [ sql = ap.build_attach_evidence_sql(payload, "pid-3", None, _approval_meta("attach_evidence", payload))
{"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)
)
verify = sql[sql.index("do $verify$") : sql.index("kb_stage.finish_approved_proposal")] verify = sql[sql.index("do $verify$") : sql.index("kb_stage.finish_approved_proposal")]
assert "weight is not distinct from 0.78" in verify assert "weight is not distinct from 0.78" in verify
@ -167,9 +165,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 "evidence row % does not match strict apply payload" in verify
assert sql.startswith("begin;") assert sql.startswith("begin;")
assert sql.rstrip().endswith("commit;") assert sql.rstrip().endswith("commit;")
assert sql.index("raise exception 'apply_proposal: evidence row") < sql.index( assert sql.index("raise exception 'apply_proposal: evidence row") < sql.index("kb_stage.finish_approved_proposal")
"kb_stage.finish_approved_proposal"
)
def test_attach_evidence_requires_source_id(): def test_attach_evidence_requires_source_id():
@ -231,9 +227,7 @@ def _approve_claim_bundle():
{"claim_id": claim_a, "source_id": source_a, "role": "grounds", "weight": 0.9}, {"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}, {"claim_id": claim_b, "source_id": source_b, "role": "illustrates", "weight": None},
], ],
"edges": [ "edges": [{"from_claim": claim_a, "to_claim": claim_b, "edge_type": "supports", "weight": 0.7}],
{"from_claim": claim_a, "to_claim": claim_b, "edge_type": "supports", "weight": 0.7}
],
"reasoning_tools": [ "reasoning_tools": [
{ {
"id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee", "id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
@ -259,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.claims" in sql
assert "insert into public.sources" in sql assert "insert into public.sources" in sql
assert "insert into public.claim_evidence" 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.claim_edges" in sql
assert "insert into public.reasoning_tools" in sql assert "insert into public.reasoning_tools" in sql
assert "source hash collision" in sql assert "source hash collision" in sql
@ -291,9 +287,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 "approve_claim: edge row does not match strict apply payload" in verify
assert sql.startswith("begin;") assert sql.startswith("begin;")
assert sql.rstrip().endswith("commit;") assert sql.rstrip().endswith("commit;")
assert sql.index("raise exception 'approve_claim: evidence row") < sql.index( assert sql.index("raise exception 'approve_claim: evidence row") < sql.index("kb_stage.finish_approved_proposal")
"kb_stage.finish_approved_proposal"
)
def test_approve_claim_bundle_rejects_duplicate_source_hashes(): def test_approve_claim_bundle_rejects_duplicate_source_hashes():
@ -388,6 +382,34 @@ def test_apply_sql_locks_and_binds_approval_before_canonical_write():
assert "Reviewed exact strict payload." in sql 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(): def test_build_apply_sql_requires_review_provenance():
proposal = { proposal = {
"id": "99999999-9999-4999-8999-999999999999", "id": "99999999-9999-4999-8999-999999999999",
@ -445,7 +467,7 @@ def test_assert_applyable_allows_approved():
# --- ledger flip: concurrency guard + FK stamp --------------------------- # # --- ledger flip: concurrency guard + FK stamp --------------------------- #
def test_ledger_transition_uses_payload_bound_security_functions(): 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)) 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.assert_approved_proposal" in sql
assert "kb_stage.finish_approved_proposal" in sql assert "kb_stage.finish_approved_proposal" in sql
@ -459,7 +481,7 @@ def test_ledger_transition_uses_payload_bound_security_functions():
def test_ledger_flip_stamps_agent_fk(): 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)) 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 # Hard resolve into a variable + NOT-NULL assert, never a silent inline
# subselect that would stamp NULL on an unresolved handle. # subselect that would stamp NULL on an unresolved handle.
@ -468,7 +490,7 @@ def test_ledger_flip_stamps_agent_fk():
def test_build_apply_sql_defaults_applied_by_to_service_agent(): 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 = { proposal = {
"id": "pid", "id": "pid",
"proposal_type": "add_edge", "proposal_type": "add_edge",

View file

@ -6,7 +6,10 @@ standalone (`python3 tests/test_apply_worker.py`).
""" """
import argparse import argparse
import json
import stat
import sys import sys
import tempfile
from pathlib import Path from pathlib import Path
try: try:
@ -40,19 +43,33 @@ sys.path.insert(0, str(REPO_ROOT / "scripts"))
import apply_worker as w # noqa: E402 import apply_worker as w # noqa: E402
@pytest.fixture(autouse=True) def _dependency_restore():
def restore_apply_worker_dependencies():
original_load_password = w.ap.load_password original_load_password = w.ap.load_password
original_load_failure_state = w.load_failure_state original_load_failure_state = w.load_failure_state
original_fetch_candidates = w.fetch_candidates original_fetch_candidates = w.fetch_candidates
original_apply_one = w.apply_one original_apply_one = w.apply_one
original_render_one = w.render_one original_render_one = w.render_one
original_subprocess_run = w.subprocess.run
yield yield
w.ap.load_password = original_load_password w.ap.load_password = original_load_password
w.load_failure_state = original_load_failure_state w.load_failure_state = original_load_failure_state
w.fetch_candidates = original_fetch_candidates w.fetch_candidates = original_fetch_candidates
w.apply_one = original_apply_one w.apply_one = original_apply_one
w.render_one = original_render_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 ------------------------------------------------------ # # --- candidate query ------------------------------------------------------ #
@ -116,22 +133,283 @@ def test_render_command_expands_agent_id():
# --- enablement gate ------------------------------------------------------ # # --- enablement gate ------------------------------------------------------ #
def _args(**over): def _args(**over):
base = dict( base = dict(
enable=False, limit=20, max_per_tick=1, max_attempts=3, enable=False,
failure_state_file=None, applied_by="kb-apply", limit=20,
apply_script="apply_proposal.py", render_cmd="", max_per_tick=1,
secrets_file="x", container="teleo-pg", db="teleo", max_attempts=3,
host="127.0.0.1", role="kb_apply", 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) base.update(over)
return argparse.Namespace(**base) 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): def test_report_only_gate_does_not_apply(monkeypatch=None):
calls = [] calls = []
w.ap.load_password = lambda _f: "pw" w.ap.load_password = lambda _f: "pw"
w.fetch_candidates = lambda a, p, excluded: [ w.fetch_candidates = lambda a, p, excluded: [{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}]
{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}
]
w.apply_one = lambda a, pid: calls.append(pid) w.apply_one = lambda a, pid: calls.append(pid)
rc = w.run(_args(enable=False)) 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(): def test_enabled_worker_applies_and_renders():
applied, rendered = [], [] applied, rendered = [], []
w.ap.load_password = lambda _f: "pw" w.ap.load_password = lambda _f: "pw"
w.fetch_candidates = lambda a, p, excluded: [ w.fetch_candidates = lambda a, p, excluded: [{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}]
{"id": "p1", "proposal_type": "revise_strategy", "agent_id": "ag"}
]
w.apply_one = lambda a, pid: applied.append(pid) w.apply_one = lambda a, pid: applied.append(pid)
w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" 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(): def test_enabled_worker_skips_render_for_add_edge():
applied, rendered = [], [] applied, rendered = [], []
w.ap.load_password = lambda _f: "pw" w.ap.load_password = lambda _f: "pw"
w.fetch_candidates = lambda a, p, excluded: [ w.fetch_candidates = lambda a, p, excluded: [{"id": "e1", "proposal_type": "add_edge", "agent_id": None}]
{"id": "e1", "proposal_type": "add_edge", "agent_id": None}
]
w.apply_one = lambda a, pid: applied.append(pid) w.apply_one = lambda a, pid: applied.append(pid)
w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" 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(): def test_enabled_worker_skips_render_for_approve_claim():
applied, rendered = [], [] applied, rendered = [], []
w.ap.load_password = lambda _f: "pw" w.ap.load_password = lambda _f: "pw"
w.fetch_candidates = lambda a, p, excluded: [ w.fetch_candidates = lambda a, p, excluded: [{"id": "c1", "proposal_type": "approve_claim", "agent_id": "ag"}]
{"id": "c1", "proposal_type": "approve_claim", "agent_id": "ag"}
]
w.apply_one = lambda a, pid: applied.append(pid) w.apply_one = lambda a, pid: applied.append(pid)
w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok" w.render_one = lambda a, agent_id: rendered.append(agent_id) or "ok"
@ -263,7 +535,7 @@ if __name__ == "__main__":
failures = 0 failures = 0
for name, fn in sorted(globals().items()): for name, fn in sorted(globals().items()):
if name.startswith("test_") and callable(fn): if name.startswith("test_") and callable(fn):
restore = restore_apply_worker_dependencies() restore = _dependency_restore()
next(restore) next(restore)
try: try:
fn() fn()

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,11 @@ sys.path.insert(0, str(ROOT / "scripts"))
import run_approve_claim_clone_canary as canary # noqa: E402 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: def _passing_result(expected_rows: dict, expected_deltas: dict) -> dict:
proposal_id = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" proposal_id = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"
return { return {

View file

@ -2,6 +2,8 @@
from __future__ import annotations from __future__ import annotations
import hashlib
import json
import subprocess import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
@ -11,8 +13,10 @@ import pytest
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts")) sys.path.insert(0, str(ROOT / "scripts"))
WRAPPER = ROOT / "scripts" / "run_approve_claim_isolated_container_canary.sh" 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 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 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( monkeypatch.setattr(
canary.shutil, canary.shutil,
"which", "which",
lambda executable: "/opt/homebrew/bin/docker" lambda executable: "/opt/homebrew/bin/docker" if executable == "docker" else None,
if executable == "docker"
else None,
) )
def fake_run(command: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]: 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( monkeypatch.setattr(
apply.shutil, apply.shutil,
"which", "which",
lambda executable: "/opt/homebrew/bin/docker" lambda executable: "/opt/homebrew/bin/docker" if executable == "docker" else None,
if executable == "docker"
else None,
) )
def fake_run(command: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]: 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: 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 'source_canary_label" != "working-leo-approved-source"' in text
assert "--network none" in text assert "--network none" in text
assert "--tmpfs /var/lib/postgresql/data:rw,nosuid,size=512m" 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_NETWORK_MODE="$container_network_mode"' in text
assert 'CANARY_MOUNTS_JSON="$container_mounts_json"' in text assert 'CANARY_MOUNTS_JSON="$container_mounts_json"' in text
assert 'data["checks"]["outer_source_tier_enforced"]' in text assert 'checks["outer_source_tier_enforced"]' in text
assert 'data["checks"]["outer_container_network_disabled"]' in text assert 'checks["outer_container_network_disabled"]' in text
assert 'data["checks"]["outer_container_has_no_docker_volumes"]' in text assert 'checks["outer_container_has_no_docker_volumes"]' in text
assert 'source_tier != "live-readonly" or service_observable' 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